PP: Fix #1104: Missing check for #if overflow.

Also, rationalized this to generally make it safer and more readable.
It could use a more modern approach, at some point...
This commit is contained in:
John Kessenich 2017-10-16 15:29:07 -06:00
parent 1a4bbc4a95
commit 7d67c6cbc2
5 changed files with 164 additions and 17 deletions

View File

@ -0,0 +1,20 @@
cppDeepNest.frag
ERROR: 0:66: '#if/#ifdef/#ifndef' : maximum nesting depth exceeded
ERROR: 0:66: '' : missing #endif
ERROR: 0:66: '' : syntax error, unexpected $end
ERROR: 3 compilation errors. No code generated.
Shader version: 100
ERROR: node is still EOpNull!
0:? Linker Objects
Linked fragment stage:
ERROR: Linking fragment stage: Missing entry point: Each stage requires one entry point
Shader version: 100
ERROR: node is still EOpNull!
0:? Linker Objects

117
Test/cppDeepNest.frag Normal file
View File

@ -0,0 +1,117 @@
#ifdef O
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#if
#endif

View File

@ -241,15 +241,20 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
int nextAtom = atomStrings.getAtom(ppToken->name);
if (nextAtom == PpAtomIf || nextAtom == PpAtomIfdef || nextAtom == PpAtomIfndef) {
depth++;
if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if/#ifdef/#ifndef", "");
return EndOfInput;
} else {
ifdepth++;
elsetracker++;
}
} else if (nextAtom == PpAtomEndif) {
token = extraTokenCheck(nextAtom, ppToken, scanToken(ppToken));
elseSeen[elsetracker] = false;
--elsetracker;
if (depth == 0) {
// found the #endif we are looking for
if (ifdepth)
if (ifdepth > 0)
--ifdepth;
break;
}
@ -266,7 +271,7 @@ int TPpContext::CPPelse(int matchelse, TPpToken* ppToken)
parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
/* we decrement ifdepth here, because CPPif will increment
* it and we really want to leave it alone */
if (ifdepth) {
if (ifdepth > 0) {
--ifdepth;
elseSeen[elsetracker] = false;
--elsetracker;
@ -536,11 +541,12 @@ int TPpContext::evalToToken(int token, bool shortCircuit, int& res, bool& err, T
int TPpContext::CPPif(TPpToken* ppToken)
{
int token = scanToken(ppToken);
if (ifdepth >= maxIfNesting || elsetracker >= maxIfNesting) {
parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
return EndOfInput;
} else {
elsetracker++;
ifdepth++;
if (ifdepth > maxIfNesting) {
parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#if", "");
return 0;
}
int res = 0;
bool err = false;
@ -556,11 +562,14 @@ int TPpContext::CPPif(TPpToken* ppToken)
int TPpContext::CPPifdef(int defined, TPpToken* ppToken)
{
int token = scanToken(ppToken);
if (++ifdepth > maxIfNesting) {
if (ifdepth > maxIfNesting || elsetracker > maxIfNesting) {
parseContext.ppError(ppToken->loc, "maximum nesting depth exceeded", "#ifdef", "");
return 0;
}
return EndOfInput;
} else {
elsetracker++;
ifdepth++;
}
if (token != PpAtomIdentifier) {
if (defined)
parseContext.ppError(ppToken->loc, "must be followed by macro name", "#ifdef", "");
@ -886,16 +895,16 @@ int TPpContext::readCPPline(TPpToken* ppToken)
token = CPPdefine(ppToken);
break;
case PpAtomElse:
if (elsetracker[elseSeen])
if (elseSeen[elsetracker])
parseContext.ppError(ppToken->loc, "#else after #else", "#else", "");
elsetracker[elseSeen] = true;
if (! ifdepth)
elseSeen[elsetracker] = true;
if (ifdepth == 0)
parseContext.ppError(ppToken->loc, "mismatched statements", "#else", "");
token = extraTokenCheck(PpAtomElse, ppToken, scanToken(ppToken));
token = CPPelse(0, ppToken);
break;
case PpAtomElif:
if (! ifdepth)
if (ifdepth == 0)
parseContext.ppError(ppToken->loc, "mismatched statements", "#elif", "");
if (elseSeen[elsetracker])
parseContext.ppError(ppToken->loc, "#elif after #else", "#elif", "");
@ -906,7 +915,7 @@ int TPpContext::readCPPline(TPpToken* ppToken)
token = CPPelse(0, ppToken);
break;
case PpAtomEndif:
if (! ifdepth)
if (ifdepth == 0)
parseContext.ppError(ppToken->loc, "mismatched statements", "#endif", "");
else {
elseSeen[elsetracker] = false;

View File

@ -309,7 +309,7 @@ protected:
bool endOfReplacementList() { return inputStack.empty() || inputStack.back()->endOfReplacementList(); }
bool isMacroInput() { return inputStack.size() > 0 && inputStack.back()->isMacroInput(); }
static const int maxIfNesting = 64;
static const int maxIfNesting = 65;
int ifdepth; // current #if-#else-#endif nesting in the cpp.c file (pre-processor)
bool elseSeen[maxIfNesting]; // Keep a track of whether an else has been seen at a particular depth

View File

@ -82,6 +82,7 @@ INSTANTIATE_TEST_CASE_P(
"cppBad.vert",
"cppBad2.vert",
"cppComplexExpr.vert",
"cppDeepNest.frag",
"badChars.frag",
"pointCoord.frag",
"array.frag",