Skip to content

Commit 7da0479

Browse files
committed
gh-157890: Raise SyntaxError for malformed Unicode escapes in format specifiers
Raise `SyntaxError` instead of leaking `UnicodeDecodeError` when malformed Unicode character name escapes occur in f-string or t-string format specifiers.
1 parent 6b97452 commit 7da0479

4 files changed

Lines changed: 15 additions & 1 deletion

File tree

‎Lib/test/test_fstring.py‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,6 +1045,12 @@ def test_misformed_unicode_character_name(self):
10451045
r"f'\N{'",
10461046
r"f'\N{GREEK CAPITAL LETTER DELTA'",
10471047

1048+
# Malformed Unicode escapes in format specifiers
1049+
# are decoded through a separate parser path.
1050+
r"f'{x:\N}'",
1051+
r"f'{x:\N{'",
1052+
r"f'{x:{y}\N{'",
1053+
10481054
# Here are the non-f-string versions,
10491055
# which should give the same errors.
10501056
r"'\N'",

‎Lib/test/test_tstring.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ def test_syntax_errors(self):
354354
with self.subTest(case), self.assertRaisesRegex(SyntaxError, err):
355355
eval(case)
356356

357+
# Malformed Unicode escapes in format specifiers are decoded
358+
# through a separate parser path.
359+
with self.assertRaises(SyntaxError):
360+
eval(r"t'{x:\N}'")
361+
357362
def test_runtime_errors(self):
358363
# Test missing variables
359364
with self.assertRaises(NameError):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Raise :exc:`SyntaxError` instead of :exc:`UnicodeDecodeError` for malformed
2+
Unicode character name escapes in f-string and t-string format specifiers.

‎Parser/action_helpers.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1504,8 +1504,9 @@ expr_ty _PyPegen_decoded_constant_from_token(Parser* p, Token* tok) {
15041504

15051505
int is_raw = tok->is_raw;
15061506

1507-
PyObject* str = _PyPegen_decode_string(p, is_raw, bstr, bsize, tok);
1507+
PyObject *str = _PyPegen_decode_string(p, is_raw, bstr, bsize, tok);
15081508
if (str == NULL) {
1509+
_Pypegen_raise_decode_error(p);
15091510
return NULL;
15101511
}
15111512
if (_PyArena_AddPyObject(p->arena, str) < 0) {

0 commit comments

Comments
 (0)