diff options
| author | Tim Foley <tim.foley.is@gmail.com> | 2017-07-11 17:47:58 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-11 17:47:58 -0700 |
| commit | 88f451cfafbf3a30033e750873c79f761b2bd1a5 (patch) | |
| tree | 915b5124f0da1eed6b85f1616178e80a0dfbe3af | |
| parent | d8d8fefb9693e83bea215629f3a77f8a48d2f50f (diff) | |
| parent | 24a44ffdd6e5648b3e0528ac3ccc871da853158c (diff) | |
Merge pull request #76 from tfoleyNV/gh-75
Make parser recovering more robust to avoid infinite loops
| -rw-r--r-- | source/slang/parser.cpp | 51 | ||||
| -rw-r--r-- | tests/bugs/gh-75.hlsl | 24 | ||||
| -rw-r--r-- | tests/bugs/gh-75.hlsl.expected | 6 |
3 files changed, 72 insertions, 9 deletions
diff --git a/source/slang/parser.cpp b/source/slang/parser.cpp index 759fc0c20..de63793b1 100644 --- a/source/slang/parser.cpp +++ b/source/slang/parser.cpp @@ -303,17 +303,40 @@ namespace Slang if (!parser->isRecovering) return true; - // Determine if we are looking for a closing token at all... - bool lookingForClose = false; + // Determine if we are looking for common closing tokens, + // so that we can know whether or we are allowed to skip + // over them. + + bool lookingForEOF = false; + bool lookingForRCurly = false; + bool lookingForRParen = false; + bool lookingForRSquare = false; + for (int ii = 0; ii < recoverBeforeCount; ++ii) { - if (IsClosingToken(recoverBefore[ii])) - lookingForClose = true; + switch (recoverBefore[ii]) + { + default: + break; + + case TokenType::EndOfFile: lookingForEOF = true; break; + case TokenType::RBrace: lookingForRCurly = true; break; + case TokenType::RParent: lookingForRParen = true; break; + case TokenType::RBracket: lookingForRSquare = true; break; + } } for (int ii = 0; ii < recoverAfterCount; ++ii) { - if (IsClosingToken(recoverAfter[ii])) - lookingForClose = true; + switch (recoverBefore[ii]) + { + default: + break; + + case TokenType::EndOfFile: lookingForEOF = true; break; + case TokenType::RBrace: lookingForRCurly = true; break; + case TokenType::RParent: lookingForRParen = true; break; + case TokenType::RBracket: lookingForRSquare = true; break; + } } TokenReader* tokenReader = &parser->tokenReader; @@ -354,12 +377,23 @@ namespace Slang // we are looking for a closing token case TokenType::RParent: case TokenType::RBracket: - if (!lookingForClose) + if (lookingForRParen || lookingForRSquare || lookingForRCurly || lookingForEOF) + { + // We are looking for a closing token, so it is okay to skip these + } + else return false; break; - // never skip a `}`, to avoid spurious errors + // Don't skip a `}`, to avoid spurious errors, + // with the exception of when we are looking for EOF case TokenType::RBrace: + if (lookingForRCurly || lookingForEOF) + { + // We are looking for end-of-file, so it is okay to skip here + } + else + return false; } @@ -2342,7 +2376,6 @@ namespace Slang while(!AdvanceIfMatch(parser, closingToken)) { ParseDecl(parser, containerDecl); - TryRecover(parser); } } diff --git a/tests/bugs/gh-75.hlsl b/tests/bugs/gh-75.hlsl new file mode 100644 index 000000000..fbaaf6a73 --- /dev/null +++ b/tests/bugs/gh-75.hlsl @@ -0,0 +1,24 @@ +//TEST:SIMPLE:-profile cs_5_0 + +// Missing opening `{` sends parser into infinite loop + +struct LightCB +{ + float3 vec3Val; // We're using 2 values. [0]: worldDir [1]: intensity +}; + +StructuredBuffer<LightCB> gLightIn; +AppendStructuredBuffer<LightCB> gLightOut; + +[numthreads(1, 1, 1)] +void main() +{ + uint numLights = 0; + uint stride; + gLightIn.GetDimensions(numLights, stride); + + for (uint i = 0; i < numLights; i++) + + gLightOut.Append(gLightIn[i]); + } +}
\ No newline at end of file diff --git a/tests/bugs/gh-75.hlsl.expected b/tests/bugs/gh-75.hlsl.expected new file mode 100644 index 000000000..345acd804 --- /dev/null +++ b/tests/bugs/gh-75.hlsl.expected @@ -0,0 +1,6 @@ +result code = -1 +standard error = { +tests/bugs/gh-75.hlsl(24): error 20001: unexpected '}', expected identifier +} +standard output = { +} |
