From: Ben Pfaff Date: Wed, 6 Oct 2021 05:15:28 +0000 (-0700) Subject: expressions: Parse multiple sets of parentheses for grouping together. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=bc0434f1ced83fc3a5f5ace44cbad3acdc5e3e29 expressions: Parse multiple sets of parentheses for grouping together. 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. --- diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index 57307bf306..0493ed878b 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -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; }