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;
 }