expressions: Parse multiple sets of parentheses for grouping together.
authorBen Pfaff <blp@cs.stanford.edu>
Wed, 6 Oct 2021 05:15:28 +0000 (22:15 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Wed, 6 Oct 2021 05:15:28 +0000 (22:15 -0700)
Fuzzers are fond of driving expression parsers to failure by exhausting
the stack in trivial ways.  This defeats the simplest attempts by
lining up thousands of left parentheses in a row.

I am a bit curious whether the fuzzer will now invent something more
sophisticated, such as nested function calls or non-empty expressions like
1+(1+(1+(1+(1+....

This fixes bug #61286.
Thanks to Irfan Ariq for reporting the bug.

src/language/expressions/parse.c

index 57307bf306f89d6ec83d5f57f33d2a405da71a30..0493ed878bfd98283451eed17b06a66ea88b3409 100644 (file)
@@ -953,11 +953,22 @@ parse_primary (struct lexer *lexer, struct expression *e)
 
     case T_LPAREN:
       {
-        union any_node *node;
-       lex_get (lexer);
-       node = parse_or (lexer, e);
-       if (node != NULL && !lex_force_match (lexer, T_RPAREN))
+        /* Count number of left parentheses so that we can match them against
+           an equal number of right parentheses.  This defeats trivial attempts
+           to exhaust the stack with a lot of left parentheses.  (More
+           sophisticated attacks will still succeed.) */
+        size_t n = 0;
+        while (lex_match (lexer, T_LPAREN))
+          n++;
+
+        union any_node *node = parse_or (lexer, e);
+       if (!node)
           return NULL;
+
+        for (size_t i = 0; i < n; i++)
+          if (!lex_force_match (lexer, T_RPAREN))
+            return NULL;
+
         return node;
       }