summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Foley <tim.foley.is@gmail.com>2017-07-11 17:47:58 -0700
committerGitHub <noreply@github.com>2017-07-11 17:47:58 -0700
commit88f451cfafbf3a30033e750873c79f761b2bd1a5 (patch)
tree915b5124f0da1eed6b85f1616178e80a0dfbe3af
parentd8d8fefb9693e83bea215629f3a77f8a48d2f50f (diff)
parent24a44ffdd6e5648b3e0528ac3ccc871da853158c (diff)
Merge pull request #76 from tfoleyNV/gh-75
Make parser recovering more robust to avoid infinite loops
-rw-r--r--source/slang/parser.cpp51
-rw-r--r--tests/bugs/gh-75.hlsl24
-rw-r--r--tests/bugs/gh-75.hlsl.expected6
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 = {
+}