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
parent a0ce7e61
#define MAJOR_VERSION 0 #define MAJOR_VERSION 0
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 539 #define BUILD_REVISION 540
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -59,6 +59,7 @@ typedef struct Options_Rec{ ...@@ -59,6 +59,7 @@ typedef struct Options_Rec{
int DumpAtomTable; int DumpAtomTable;
} Options; } Options;
#define MAX_IF_NESTING 64
struct CPPStruct_Rec { struct CPPStruct_Rec {
// Public members // Public members
SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers SourceLoc *pLastSourceLoc; // Set at the start of each statement by the tree walkers
...@@ -80,7 +81,7 @@ struct CPPStruct_Rec { ...@@ -80,7 +81,7 @@ struct CPPStruct_Rec {
// Private members: // Private members:
SourceLoc ltokenLoc; SourceLoc ltokenLoc;
int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor) int ifdepth; //current #if-#else-#endif nesting in the cpp.c file (pre-processor)
int elsedepth[64]; //Keep a track of #if depth..Max allowed is 64. int elsedepth[MAX_IF_NESTING];//Keep a track of #if depth..Max allowed is 64.
int elsetracker; //#if-#else and #endif constructs...Counter. int elsetracker; //#if-#else and #endif constructs...Counter.
const char *ErrMsg; const char *ErrMsg;
int CompileError; //Indicate compile error when #error, #else,#elif mismatch. int CompileError; //Indicate compile error when #error, #else,#elif mismatch.
......
...@@ -84,7 +84,6 @@ static int extensionAtom = 0; ...@@ -84,7 +84,6 @@ static int extensionAtom = 0;
static Scope *macros = 0; static Scope *macros = 0;
#define MAX_MACRO_ARGS 64 #define MAX_MACRO_ARGS 64
#define MAX_IF_NESTING 64
static SourceLoc ifloc; /* outermost #if */ static SourceLoc ifloc; /* outermost #if */
...@@ -285,18 +284,30 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp) ...@@ -285,18 +284,30 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp)
atom = yylvalpp->sc_ident; atom = yylvalpp->sc_ident;
if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){ if (atom == ifAtom || atom == ifdefAtom || atom == ifndefAtom){
depth++; cpp->ifdepth++; cpp->elsetracker++; 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; cpp->elsedepth[cpp->elsetracker] = 0;
} }
else if (atom == endifAtom) { else if (atom == endifAtom) {
if(--depth<0){ if(--depth<0){
--cpp->elsetracker; if (cpp->elsetracker)
--cpp->elsetracker;
if (cpp->ifdepth) if (cpp->ifdepth)
--cpp->ifdepth; --cpp->ifdepth;
break; break;
} }
--cpp->elsetracker; --cpp->elsetracker;
--cpp->ifdepth; --cpp->ifdepth;
} }
else if (((int)(matchelse) != 0)&& depth==0) { else if (((int)(matchelse) != 0)&& depth==0) {
if (atom == elseAtom ) { if (atom == elseAtom ) {
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
...@@ -325,6 +336,7 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp) ...@@ -325,6 +336,7 @@ static int CPPelse(int matchelse, yystypepp * yylvalpp)
else if((atom==elseAtom) && (!ChkCorrectElseNesting())){ else if((atom==elseAtom) && (!ChkCorrectElseNesting())){
CPPErrorToInfoLog("#else after a #else"); CPPErrorToInfoLog("#else after a #else");
cpp->CompileError=1; cpp->CompileError=1;
return 0;
} }
}; };
return token; return token;
...@@ -469,15 +481,24 @@ error: ...@@ -469,15 +481,24 @@ error:
static int CPPif(yystypepp * yylvalpp) { static int CPPif(yystypepp * yylvalpp) {
int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
int res = 0, err = 0; int res = 0, err = 0;
cpp->elsetracker++;
cpp->elsedepth[cpp->elsetracker] = 0;
if (!cpp->ifdepth++) if (!cpp->ifdepth++)
ifloc = *cpp->tokenLoc; ifloc = *cpp->tokenLoc;
if(cpp->ifdepth >MAX_IF_NESTING){ if(cpp->ifdepth > MAX_IF_NESTING){
CPPErrorToInfoLog("max #if nesting depth exceeded"); CPPErrorToInfoLog("max #if nesting depth exceeded");
return 0; cpp->CompileError = 1;
} return 0;
token = eval(token, MIN_PREC, &res, &err, yylvalpp); }
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') { if (token != '\n') {
CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline"); CPPWarningToInfoLog("unexpected tokens following #if preprocessor directive - expected a newline");
while (token != '\n') { while (token != '\n') {
...@@ -499,12 +520,20 @@ static int CPPifdef(int defined, yystypepp * yylvalpp) ...@@ -499,12 +520,20 @@ static int CPPifdef(int defined, yystypepp * yylvalpp)
{ {
int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); int token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
int name = yylvalpp->sc_ident; int name = yylvalpp->sc_ident;
if(++cpp->ifdepth >MAX_IF_NESTING){ if(++cpp->ifdepth > MAX_IF_NESTING){
CPPErrorToInfoLog("max #if nesting depth exceeded"); CPPErrorToInfoLog("max #if nesting depth exceeded");
return 0; cpp->CompileError = 1;
} return 0;
cpp->elsetracker++; }
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; cpp->elsedepth[cpp->elsetracker] = 0;
if (token != CPP_IDENTIFIER) { if (token != CPP_IDENTIFIER) {
defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef"); defined ? CPPErrorToInfoLog("ifdef"):CPPErrorToInfoLog("ifndef");
} else { } else {
...@@ -748,6 +777,7 @@ int readCPPline(yystypepp * yylvalpp) ...@@ -748,6 +777,7 @@ int readCPPline(yystypepp * yylvalpp)
if (!cpp->ifdepth ){ if (!cpp->ifdepth ){
CPPErrorToInfoLog("#else mismatch"); CPPErrorToInfoLog("#else mismatch");
cpp->CompileError=1; cpp->CompileError=1;
return 0;
} }
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
if (token != '\n') { if (token != '\n') {
...@@ -763,14 +793,17 @@ int readCPPline(yystypepp * yylvalpp) ...@@ -763,14 +793,17 @@ int readCPPline(yystypepp * yylvalpp)
token = CPPelse(0, yylvalpp); token = CPPelse(0, yylvalpp);
}else{ }else{
CPPErrorToInfoLog("#else after a #else"); CPPErrorToInfoLog("#else after a #else");
cpp->ifdepth=0; cpp->ifdepth = 0;
cpp->elsetracker = 0;
cpp->pastFirstStatement = 1; cpp->pastFirstStatement = 1;
cpp->CompileError = 1;
return 0; return 0;
} }
} else if (yylvalpp->sc_ident == elifAtom) { } else if (yylvalpp->sc_ident == elifAtom) {
if (!cpp->ifdepth){ if (!cpp->ifdepth){
CPPErrorToInfoLog("#elif mismatch"); CPPErrorToInfoLog("#elif mismatch");
cpp->CompileError=1; cpp->CompileError=1;
return 0;
} }
// this token is really a dont care, but we still need to eat the tokens // this token is really a dont care, but we still need to eat the tokens
token = cpp->currentInput->scan(cpp->currentInput, yylvalpp); token = cpp->currentInput->scan(cpp->currentInput, yylvalpp);
...@@ -779,18 +812,22 @@ int readCPPline(yystypepp * yylvalpp) ...@@ -779,18 +812,22 @@ int readCPPline(yystypepp * yylvalpp)
if (token <= 0) { // EOF or error if (token <= 0) { // EOF or error
CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline"); CPPErrorToInfoLog("unexpect tokens following #elif preprocessor directive - expected a newline");
cpp->CompileError = 1; cpp->CompileError = 1;
break; return 0;
} }
} }
token = CPPelse(0, yylvalpp); token = CPPelse(0, yylvalpp);
} else if (yylvalpp->sc_ident == endifAtom) { } else if (yylvalpp->sc_ident == endifAtom) {
--cpp->elsetracker;
if (!cpp->ifdepth){ if (!cpp->ifdepth){
CPPErrorToInfoLog("#endif mismatch"); CPPErrorToInfoLog("#endif mismatch");
cpp->CompileError=1; cpp->CompileError=1;
return 0;
} }
else else
--cpp->ifdepth; --cpp->ifdepth;
if (cpp->elsetracker)
--cpp->elsetracker;
} else if (yylvalpp->sc_ident == ifAtom) { } else if (yylvalpp->sc_ident == ifAtom) {
token = CPPif(yylvalpp); token = CPPif(yylvalpp);
} else if (yylvalpp->sc_ident == ifdefAtom) { } else if (yylvalpp->sc_ident == ifdefAtom) {
...@@ -1051,9 +1088,14 @@ int MacroExpand(int atom, yystypepp * yylvalpp) ...@@ -1051,9 +1088,14 @@ int MacroExpand(int atom, yystypepp * yylvalpp)
int ChkCorrectElseNesting(void) int ChkCorrectElseNesting(void)
{ {
if(cpp->elsedepth[cpp->elsetracker]==0){ // sanity check to make sure elsetracker is in a valid range
cpp->elsedepth[cpp->elsetracker]=1; if (cpp->elsetracker < 0 || cpp->elsetracker >= MAX_IF_NESTING) {
return 1; return 0;
}
if (cpp->elsedepth[cpp->elsetracker] == 0) {
cpp->elsedepth[cpp->elsetracker] = 1;
return 1;
} }
return 0; return 0;
} }
......
...@@ -92,12 +92,12 @@ int ResetPreprocessor(void) ...@@ -92,12 +92,12 @@ int ResetPreprocessor(void)
cpp->lastSourceLoc.file = 0; cpp->lastSourceLoc.file = 0;
cpp->lastSourceLoc.line = 0; cpp->lastSourceLoc.line = 0;
cpp->pC=0; cpp->pC = 0;
cpp->CompileError=0; cpp->CompileError = 0;
cpp->ifdepth=0; cpp->ifdepth = 0;
for(cpp->elsetracker=0; cpp->elsetracker<64; cpp->elsetracker++) for(cpp->elsetracker = 0; cpp->elsetracker < MAX_IF_NESTING; cpp->elsetracker++)
cpp->elsedepth[cpp->elsetracker]=0; cpp->elsedepth[cpp->elsetracker] = 0;
cpp->elsetracker=0; cpp->elsetracker = 0;
cpp->tokensBeforeEOF = 0; cpp->tokensBeforeEOF = 0;
return 1; return 1;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment