Skip to content

Commit 06f8c33

Browse files
authored
bpo-42214: Fix check for NOTEQUAL token in the PEG parser for the barry_as_flufl rule (GH-23048)
1 parent 6e03c0a commit 06f8c33

File tree

6 files changed

+23
-5
lines changed

6 files changed

+23
-5
lines changed

Grammar/python.gram

+1-1
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ compare_op_bitwise_or_pair[CmpopExprPair*]:
428428
| is_bitwise_or
429429
eq_bitwise_or[CmpopExprPair*]: '==' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Eq, a) }
430430
noteq_bitwise_or[CmpopExprPair*]:
431-
| (tok='!=' {_PyPegen_check_barry_as_flufl(p) ? NULL : tok}) a=bitwise_or {_PyPegen_cmpop_expr_pair(p, NotEq, a) }
431+
| (tok='!=' { _PyPegen_check_barry_as_flufl(p, tok) ? NULL : tok}) a=bitwise_or {_PyPegen_cmpop_expr_pair(p, NotEq, a) }
432432
lte_bitwise_or[CmpopExprPair*]: '<=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, LtE, a) }
433433
lt_bitwise_or[CmpopExprPair*]: '<' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, Lt, a) }
434434
gte_bitwise_or[CmpopExprPair*]: '>=' a=bitwise_or { _PyPegen_cmpop_expr_pair(p, GtE, a) }

Lib/test/test_syntax.py

+17
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,23 @@ def test_nested_named_except_blocks(self):
955955
code += f"{' '*4*12}pass"
956956
self._check_error(code, "too many statically nested blocks")
957957

958+
def test_barry_as_flufl_with_syntax_errors(self):
959+
# The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if
960+
# is reading the wrong token in the presence of syntax errors later
961+
# in the file. See bpo-42214 for more information.
962+
code = """
963+
def func1():
964+
if a != b:
965+
raise ValueError
966+
967+
def func2():
968+
try
969+
return 1
970+
finally:
971+
pass
972+
"""
973+
self._check_error(code, "invalid syntax")
974+
958975
def test_main():
959976
support.run_unittest(SyntaxTestCase)
960977
from test import test_syntax
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixed a possible crash in the PEG parser when checking for the '!=' token in
2+
the ``barry_as_flufl`` rule. Patch by Pablo Galindo.

Parser/parser.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -21288,7 +21288,7 @@ _tmp_93_rule(Parser *p)
2128821288
)
2128921289
{
2129021290
D(fprintf(stderr, "%*c+ _tmp_93[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'!='"));
21291-
_res = _PyPegen_check_barry_as_flufl ( p ) ? NULL : tok;
21291+
_res = _PyPegen_check_barry_as_flufl ( p , tok ) ? NULL : tok;
2129221292
if (_res == NULL && PyErr_Occurred()) {
2129321293
p->error_indicator = 1;
2129421294
D(p->level--);

Parser/pegen.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,7 @@ init_normalization(Parser *p)
6262
/* Checks if the NOTEQUAL token is valid given the current parser flags
6363
0 indicates success and nonzero indicates failure (an exception may be set) */
6464
int
65-
_PyPegen_check_barry_as_flufl(Parser *p) {
66-
Token *t = p->tokens[p->fill - 1];
65+
_PyPegen_check_barry_as_flufl(Parser *p, Token* t) {
6766
assert(t->bytes != NULL);
6867
assert(t->type == NOTEQUAL);
6968

Parser/pegen.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ expr_ty _PyPegen_collect_call_seqs(Parser *, asdl_expr_seq *, asdl_seq *,
263263
int end_col_offset, PyArena *arena);
264264
expr_ty _PyPegen_concatenate_strings(Parser *p, asdl_seq *);
265265
asdl_seq *_PyPegen_join_sequences(Parser *, asdl_seq *, asdl_seq *);
266-
int _PyPegen_check_barry_as_flufl(Parser *);
266+
int _PyPegen_check_barry_as_flufl(Parser *, Token *);
267267
mod_ty _PyPegen_make_module(Parser *, asdl_stmt_seq *);
268268

269269
// Error reporting helpers

0 commit comments

Comments
 (0)