Fix issues with preprocessor on very malformed shaders
Trac #15236,#15237,#15238,#15239
Error out instead of continued processing when we already know the preprocessor directives are bungled.
Generally be more careful about the order in which cpp->elsetracker and cpp->ifdepth are checked/operated on.
Validate all accesses of cpp->elsedepth to ensure no out of bounds accesses occur.
Also slipped in a few indentation/spacing fixes.
Signed-off-by: Nicolas Capens
git-svn-id: https://angleproject.googlecode.com/svn/trunk@540 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/preprocessor/cpp.c b/src/compiler/preprocessor/cpp.c
index 204a213..03ab787 100644
--- a/src/compiler/preprocessor/cpp.c
+++ b/src/compiler/preprocessor/cpp.c
@@ -84,7 +84,6 @@
static Scope *macros = 0;
#define MAX_MACRO_ARGS 64
-#define MAX_IF_NESTING 64
static SourceLoc ifloc; /* outermost #if */
@@ -285,18 +284,30 @@
atom = yylvalpp->sc_ident;
if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
depth++; cpp->ifdepth++; cpp->elsetracker++;
+ if (cpp->ifdepth > MAX_IF_NESTING) {
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ cpp->CompileError = 1;
+ return 0;
+ }
+ // sanity check elsetracker
+ if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+ CPPErrorToInfoLog("mismatched #if/#endif statements");
+ cpp->CompileError = 1;
+ return 0;
+ }
cpp->elsedepth[cpp->elsetracker] = 0;
- }
- else if (atom == endifAtom) {
+ }
+ else if (atom == endifAtom) {
if(--depth<0){
- --cpp->elsetracker;
+ if (cpp->elsetracker)
+ --cpp->elsetracker;
if (cpp->ifdepth)
--cpp->ifdepth;
break;
}
- --cpp->elsetracker;
- --cpp->ifdepth;
- }
+ --cpp->elsetracker;
+ --cpp->ifdepth;
+ }
else if (((int)(matchelse) != 0)&& depth==0) {
if (atom == elseAtom ) {
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
@@ -325,6 +336,7 @@
else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
CPPErrorToInfoLog("#else after a #else");
cpp->CompileError=1;
+ return 0;
}
};
return token;
@@ -469,15 +481,24 @@
static int CPPif(yystypepp * yylvalpp) {
int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
int res = 0, err = 0;
- cpp->elsetracker++;
- cpp->elsedepth[cpp->elsetracker] = 0;
+
if (!cpp->ifdepth++)
ifloc = *cpp->tokenLoc;
- if(cpp->ifdepth >MAX_IF_NESTING){
+ if(cpp->ifdepth > MAX_IF_NESTING){
CPPErrorToInfoLog("max #if nesting depth exceeded");
- return 0;
- }
- token = eval(token, MIN_PREC, &res, &err, yylvalpp);
+ cpp->CompileError = 1;
+ return 0;
+ }
+ cpp->elsetracker++;
+ // sanity check elsetracker
+ if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+ CPPErrorToInfoLog("mismatched #if/#endif statements");
+ cpp->CompileError = 1;
+ return 0;
+ }
+ cpp->elsedepth[cpp->elsetracker] = 0;
+
+ token = eval(token, MIN_PREC, &res, &err, yylvalpp);
if (token != '\n') {
CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
while (token != '\n') {
@@ -499,12 +520,20 @@
{
int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
int name = yylvalpp->sc_ident;
- if(++cpp->ifdepth >MAX_IF_NESTING){
- CPPErrorToInfoLog("max #if nesting depth exceeded");
- return 0;
- }
- cpp->elsetracker++;
+ if(++cpp->ifdepth > MAX_IF_NESTING){
+ CPPErrorToInfoLog("max #if nesting depth exceeded");
+ cpp->CompileError = 1;
+ return 0;
+ }
+ cpp->elsetracker++;
+ // sanity check elsetracker
+ if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+ CPPErrorToInfoLog("mismatched #if/#endif statements");
+ cpp->CompileError = 1;
+ return 0;
+ }
cpp->elsedepth[cpp->elsetracker] = 0;
+
if (token != CPP_IDENTIFIER) {
defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
} else {
@@ -748,6 +777,7 @@
if (!cpp->ifdepth ){
CPPErrorToInfoLog("#else mismatch");
cpp->CompileError=1;
+ return 0;
}
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
if (token != '\n') {
@@ -763,14 +793,17 @@
token = CPPelse(0, yylvalpp);
}else{
CPPErrorToInfoLog("#else after a #else");
- cpp->ifdepth=0;
+ cpp->ifdepth = 0;
+ cpp->elsetracker = 0;
cpp->pastFirstStatement = 1;
+ cpp->CompileError = 1;
return 0;
}
} else if (yylvalpp->sc_ident == elifAtom) {
if (!cpp->ifdepth){
CPPErrorToInfoLog("#elif mismatch");
cpp->CompileError=1;
+ return 0;
}
// this token is really a dont care, but we still need to eat the tokens
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
@@ -779,18 +812,22 @@
if (token <= 0) { // EOF or error
CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
cpp->CompileError = 1;
- break;
+ return 0;
}
}
token = CPPelse(0, yylvalpp);
} else if (yylvalpp->sc_ident == endifAtom) {
- --cpp->elsetracker;
if (!cpp->ifdepth){
CPPErrorToInfoLog("#endif mismatch");
cpp->CompileError=1;
+ return 0;
}
else
- --cpp->ifdepth;
+ --cpp->ifdepth;
+
+ if (cpp->elsetracker)
+ --cpp->elsetracker;
+
} else if (yylvalpp->sc_ident == ifAtom) {
token = CPPif(yylvalpp);
} else if (yylvalpp->sc_ident == ifdefAtom) {
@@ -1051,9 +1088,14 @@
int ChkCorrectElseNesting(void)
{
- if(cpp->elsedepth[cpp->elsetracker]==0){
- cpp->elsedepth[cpp->elsetracker]=1;
- return 1;
+ // sanity check to make sure elsetracker is in a valid range
+ if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
+ return 0;
+ }
+
+ if (cpp->elsedepth[cpp->elsetracker] == 0) {
+ cpp->elsedepth[cpp->elsetracker] = 1;
+ return 1;
}
return 0;
}