Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cfcb952

Browse files
authored
[3.9] bpo-42218: Correctly handle errors in left-recursive rules (GH-23065) (GH-23066)
Left-recursive rules need to check for errors explicitly, since even if the rule returns NULL, the parsing might continue and lead to long-distance failures. Co-authored-by: Pablo Galindo <[email protected]> (cherry picked from commit 02cdfc9) Automerge-Triggered-By: GH:lysnikolaou
1 parent dbaa07d commit cfcb952

File tree

4 files changed

+32
-0
lines changed

4 files changed

+32
-0
lines changed

Lib/test/test_syntax.py

+8
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,14 @@ def func2():
964964
"""
965965
self._check_error(code, "invalid syntax")
966966

967+
def test_invalid_line_continuation_left_recursive(self):
968+
# Check bpo-42218: SyntaxErrors following left-recursive rules
969+
# (t_primary_raw in this case) need to be tested explicitly
970+
self._check_error("A.\u018a\\ ",
971+
"unexpected character after line continuation character")
972+
self._check_error("A.\u03bc\\\n",
973+
"unexpected EOF while parsing")
974+
967975
def test_main():
968976
support.run_unittest(SyntaxTestCase)
969977
from test import test_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed a bug in the PEG parser that was causing crashes in debug mode. Now errors are checked
2+
in left-recursive rules to avoid cases where such errors do not get handled in time and appear
3+
as long-distance crashes in other places.

Parser/pegen/parse.c

+18
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,8 @@ dotted_name_rule(Parser *p)
34603460
}
34613461
p->mark = _mark;
34623462
void *_raw = dotted_name_raw(p);
3463+
if (p->error_indicator)
3464+
return NULL;
34633465
if (_raw == NULL || p->mark <= _resmark)
34643466
break;
34653467
_resmark = p->mark;
@@ -9044,6 +9046,8 @@ bitwise_or_rule(Parser *p)
90449046
}
90459047
p->mark = _mark;
90469048
void *_raw = bitwise_or_raw(p);
9049+
if (p->error_indicator)
9050+
return NULL;
90479051
if (_raw == NULL || p->mark <= _resmark)
90489052
break;
90499053
_resmark = p->mark;
@@ -9158,6 +9162,8 @@ bitwise_xor_rule(Parser *p)
91589162
}
91599163
p->mark = _mark;
91609164
void *_raw = bitwise_xor_raw(p);
9165+
if (p->error_indicator)
9166+
return NULL;
91619167
if (_raw == NULL || p->mark <= _resmark)
91629168
break;
91639169
_resmark = p->mark;
@@ -9272,6 +9278,8 @@ bitwise_and_rule(Parser *p)
92729278
}
92739279
p->mark = _mark;
92749280
void *_raw = bitwise_and_raw(p);
9281+
if (p->error_indicator)
9282+
return NULL;
92759283
if (_raw == NULL || p->mark <= _resmark)
92769284
break;
92779285
_resmark = p->mark;
@@ -9386,6 +9394,8 @@ shift_expr_rule(Parser *p)
93869394
}
93879395
p->mark = _mark;
93889396
void *_raw = shift_expr_raw(p);
9397+
if (p->error_indicator)
9398+
return NULL;
93899399
if (_raw == NULL || p->mark <= _resmark)
93909400
break;
93919401
_resmark = p->mark;
@@ -9539,6 +9549,8 @@ sum_rule(Parser *p)
95399549
}
95409550
p->mark = _mark;
95419551
void *_raw = sum_raw(p);
9552+
if (p->error_indicator)
9553+
return NULL;
95429554
if (_raw == NULL || p->mark <= _resmark)
95439555
break;
95449556
_resmark = p->mark;
@@ -9698,6 +9710,8 @@ term_rule(Parser *p)
96989710
}
96999711
p->mark = _mark;
97009712
void *_raw = term_raw(p);
9713+
if (p->error_indicator)
9714+
return NULL;
97019715
if (_raw == NULL || p->mark <= _resmark)
97029716
break;
97039717
_resmark = p->mark;
@@ -10302,6 +10316,8 @@ primary_rule(Parser *p)
1030210316
}
1030310317
p->mark = _mark;
1030410318
void *_raw = primary_raw(p);
10319+
if (p->error_indicator)
10320+
return NULL;
1030510321
if (_raw == NULL || p->mark <= _resmark)
1030610322
break;
1030710323
_resmark = p->mark;
@@ -13962,6 +13978,8 @@ t_primary_rule(Parser *p)
1396213978
}
1396313979
p->mark = _mark;
1396413980
void *_raw = t_primary_raw(p);
13981+
if (p->error_indicator)
13982+
return NULL;
1396513983
if (_raw == NULL || p->mark <= _resmark)
1396613984
break;
1396713985
_resmark = p->mark;

Tools/peg_generator/pegen/c_generator.py

+3
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,9 @@ def _set_up_rule_memoization(self, node: Rule, result_type: str) -> None:
496496
)
497497
self.print("p->mark = _mark;")
498498
self.print(f"void *_raw = {node.name}_raw(p);")
499+
self.print("if (p->error_indicator)")
500+
with self.indent():
501+
self.print("return NULL;")
499502
self.print("if (_raw == NULL || p->mark <= _resmark)")
500503
with self.indent():
501504
self.print("break;")

0 commit comments

Comments
 (0)