Handle recursion limit errors in postfix expressions (#1081)

This commit is contained in:
Jon Meow
2022-02-16 09:05:55 -08:00
committed by GitHub
parent 2e99b4d00f
commit 7e9b24390f
2 changed files with 24 additions and 2 deletions
+15
View File
@@ -1265,5 +1265,20 @@ TEST_F(ParseTreeTest, RecursionLimit) {
EXPECT_TRUE(tree.HasErrors());
}
TEST_F(ParseTreeTest, ParsePostfixExpressionRegression) {
// Stack depth errors could cause ParsePostfixExpression to infinitely loop
// when calling children and those children error. Because of the fragility of
// stack depth, this tries a few different values.
for (int n = 0; n <= 10; ++n) {
std::string code = "var x: auto = ";
code.append(ParseTree::StackDepthLimit - n, '*');
code += "(z);";
TokenizedBuffer tokens = GetTokenizedBuffer(code);
ASSERT_FALSE(tokens.HasErrors());
ParseTree tree = ParseTree::Parse(tokens, consumer);
EXPECT_TRUE(tree.HasErrors());
}
}
} // namespace
} // namespace Carbon::Testing
+9 -2
View File
@@ -912,6 +912,7 @@ auto ParseTree::Parser::ParsePostfixExpression() -> llvm::Optional<Node> {
auto start = GetSubtreeStartPosition();
llvm::Optional<Node> expression = ParsePrimaryExpression();
TokenizedBuffer::TokenIterator last_position = position_;
while (true) {
switch (NextTokenKind()) {
case TokenKind::Period():
@@ -923,10 +924,16 @@ auto ParseTree::Parser::ParsePostfixExpression() -> llvm::Optional<Node> {
expression = ParseCallExpression(start, !expression);
break;
default: {
default:
return expression;
}
}
// This is subject to an infinite loop if a child call fails, so monitor for
// stalling.
if (last_position == position_) {
CHECK(expression == llvm::None);
return expression;
}
last_position = position_;
}
}