Skip to content

Commit c3621d5

Browse files
committed
gh-159672: Reject invalid literals during keyword replay
A trial can reject a bytes literal without a pending exception. Stop the decode-error path before it requires that exception, and preserve the original syntax error.
1 parent 92b636a commit c3621d5

2 files changed

Lines changed: 15 additions & 0 deletions

File tree

‎Lib/test/test_traceback.py‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,6 +1943,16 @@ def test_keyword_replay_respects_feature_version(self):
19431943
ast.parse(source, feature_version=(3, 9))
19441944
self.assertIsNone(caught.exception._metadata)
19451945

1946+
@cpython_only
1947+
def test_keyword_trials_reject_invalid_literals(self):
1948+
for literal in ("b'é'", r"'\xzz'", r"'\U00110000'"):
1949+
for mode in ("exec", "eval", "single"):
1950+
source = "npt " + literal
1951+
with self.subTest(source=source, mode=mode):
1952+
with self.assertRaises(SyntaxError) as caught:
1953+
compile(source, "<test>", mode)
1954+
self.assertIsNone(caught.exception._metadata)
1955+
19461956
@cpython_only
19471957
def test_keyword_trials_do_not_call_normalizer(self):
19481958
with unittest.mock.patch("unicodedata.normalize") as normalize:

‎Parser/pegen_errors.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ _Pypegen_tokenizer_error(Parser *p)
104104
int
105105
_Pypegen_raise_decode_error(Parser *p)
106106
{
107+
if (p->keyword_trial != NULL) {
108+
// A trial can reject a literal without creating a syntax exception.
109+
p->error_indicator = 1;
110+
return -1;
111+
}
107112
assert(PyErr_Occurred());
108113
const char *errtype = NULL;
109114
if (PyErr_ExceptionMatches(PyExc_UnicodeError)) {

0 commit comments

Comments
 (0)