Browse Source
bpo-46503: Prevent an assert from firing when parsing some invalid \N sequences in f-strings. (GH-30865)
* bpo-46503: Prevent an assert from firing. Also fix one nearby tiny PEP-7 nit.
* Added blurb.
pull/30875/head
Eric V. Smith
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with
19 additions and
2 deletions
-
Lib/test/test_fstring.py
-
Misc/NEWS.d/next/Core and Builtins/2022-01-24-21-24-41.bpo-46503.4UrPsE.rst
-
Parser/string_parser.c
|
|
|
@ -746,12 +746,16 @@ x = ( |
|
|
|
# differently inside f-strings. |
|
|
|
self.assertAllRaise(SyntaxError, r"\(unicode error\) 'unicodeescape' codec can't decode bytes in position .*: malformed \\N character escape", |
|
|
|
[r"f'\N'", |
|
|
|
r"f'\N '", |
|
|
|
r"f'\N '", # See bpo-46503. |
|
|
|
r"f'\N{'", |
|
|
|
r"f'\N{GREEK CAPITAL LETTER DELTA'", |
|
|
|
|
|
|
|
# Here are the non-f-string versions, |
|
|
|
# which should give the same errors. |
|
|
|
r"'\N'", |
|
|
|
r"'\N '", |
|
|
|
r"'\N '", |
|
|
|
r"'\N{'", |
|
|
|
r"'\N{GREEK CAPITAL LETTER DELTA'", |
|
|
|
]) |
|
|
|
|
|
|
|
@ -0,0 +1 @@ |
|
|
|
Fix an assert when parsing some invalid \N escape sequences in f-strings. |
|
|
|
@ -442,12 +442,23 @@ fstring_find_literal(Parser *p, const char **str, const char *end, int raw, |
|
|
|
if (!raw && ch == '\\' && s < end) { |
|
|
|
ch = *s++; |
|
|
|
if (ch == 'N') { |
|
|
|
/* We need to look at and skip matching braces for "\N{name}" |
|
|
|
sequences because otherwise we'll think the opening '{' |
|
|
|
starts an expression, which is not the case with "\N". |
|
|
|
Keep looking for either a matched '{' '}' pair, or the end |
|
|
|
of the string. */ |
|
|
|
|
|
|
|
if (s < end && *s++ == '{') { |
|
|
|
while (s < end && *s++ != '}') { |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
break; |
|
|
|
|
|
|
|
/* This is an invalid "\N" sequence, since it's a "\N" not |
|
|
|
followed by a "{". Just keep parsing this literal. This |
|
|
|
error will be caught later by |
|
|
|
decode_unicode_with_escapes(). */ |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (ch == '{' && warn_invalid_escape_sequence(p, ch, t) < 0) { |
|
|
|
return -1; |
|
|
|
@ -491,7 +502,8 @@ done: |
|
|
|
*literal = PyUnicode_DecodeUTF8Stateful(literal_start, |
|
|
|
s - literal_start, |
|
|
|
NULL, NULL); |
|
|
|
} else { |
|
|
|
} |
|
|
|
else { |
|
|
|
*literal = decode_unicode_with_escapes(p, literal_start, |
|
|
|
s - literal_start, t); |
|
|
|
} |
|
|
|
|