Просмотр исходного кода

Handle recursion limit errors in postfix expressions (#1081)

Jon Meow 4 лет назад
Родитель
Сommit
7e9b24390f
2 измененных файлов с 24 добавлено и 2 удалено
  1. 15 0
      toolchain/parser/parse_tree_test.cpp
  2. 9 2
      toolchain/parser/parser_impl.cpp

+ 15 - 0
toolchain/parser/parse_tree_test.cpp

@@ -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
toolchain/parser/parser_impl.cpp

@@ -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_;
   }
 }