Skip to content

Commit 9b23f8f

Browse files
authored
[3.10] bpo-46707: Avoid potential exponential backtracking in some syntax errors (GH-31241). (GH-31242)
(cherry picked from commit b71dc71) Co-authored-by: Pablo Galindo Salgado <[email protected]>
1 parent 7445949 commit 9b23f8f

File tree

4 files changed

+901
-884
lines changed

4 files changed

+901
-884
lines changed

Grammar/python.gram

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,13 +863,15 @@ invalid_expression:
863863
RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Perhaps you forgot a comma?") }
864864
| a=disjunction 'if' b=disjunction !('else'|':') { RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "expected 'else' after 'if' expression") }
865865

866+
invalid_left_assignment_prefixes(memo): list|tuple|genexp|'True'|'None'|'False'
867+
866868
invalid_named_expression:
867869
| a=expression ':=' expression {
868870
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(
869871
a, "cannot use assignment expressions with %s", _PyPegen_get_expr_name(a)) }
870872
| a=NAME '=' b=bitwise_or !('='|':=') {
871873
p->in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_RANGE(a, b, "invalid syntax. Maybe you meant '==' or ':=' instead of '='?") }
872-
| !(list|tuple|genexp|'True'|'None'|'False') a=bitwise_or b='=' bitwise_or !('='|':=') {
874+
| !invalid_left_assignment_prefixes a=bitwise_or b='=' bitwise_or !('='|':=') {
873875
p->in_raw_rule ? NULL : RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot assign to %s here. Maybe you meant '==' instead of '='?",
874876
_PyPegen_get_expr_name(a)) }
875877

Lib/test/test_syntax.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,6 +1617,14 @@ def test_error_on_parser_stack_overflow(self):
16171617
with self.assertRaises(MemoryError):
16181618
compile(source, "<string>", mode)
16191619

1620+
@support.cpython_only
1621+
def test_deep_invalid_rule(self):
1622+
# Check that a very deep invalid rule in the PEG
1623+
# parser doesn't have exponential backtracking.
1624+
source = "d{{{{{{{{{{{{{{{{{{{{{{{{{```{{{{{{{ef f():y"
1625+
with self.assertRaises(SyntaxError):
1626+
compile(source, "<string>", "exec")
1627+
16201628

16211629
def test_main():
16221630
support.run_unittest(SyntaxTestCase)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Avoid potential exponential backtracking when producing some syntax errors
2+
involving lots of brackets. Patch by Pablo Galindo.

0 commit comments

Comments
 (0)