mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
7c26472d09
commit
0daf72194b
|
@ -746,12 +746,16 @@ x = (
|
||||||
# differently inside f-strings.
|
# differently inside f-strings.
|
||||||
self.assertAllRaise(SyntaxError, r"\(unicode error\) 'unicodeescape' codec can't decode bytes in position .*: malformed \\N character escape",
|
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 '",
|
||||||
|
r"f'\N '", # See bpo-46503.
|
||||||
r"f'\N{'",
|
r"f'\N{'",
|
||||||
r"f'\N{GREEK CAPITAL LETTER DELTA'",
|
r"f'\N{GREEK CAPITAL LETTER DELTA'",
|
||||||
|
|
||||||
# Here are the non-f-string versions,
|
# Here are the non-f-string versions,
|
||||||
# which should give the same errors.
|
# which should give the same errors.
|
||||||
r"'\N'",
|
r"'\N'",
|
||||||
|
r"'\N '",
|
||||||
|
r"'\N '",
|
||||||
r"'\N{'",
|
r"'\N{'",
|
||||||
r"'\N{GREEK CAPITAL LETTER DELTA'",
|
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) {
|
if (!raw && ch == '\\' && s < end) {
|
||||||
ch = *s++;
|
ch = *s++;
|
||||||
if (ch == 'N') {
|
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++ == '{') {
|
if (s < end && *s++ == '{') {
|
||||||
while (s < end && *s++ != '}') {
|
while (s < end && *s++ != '}') {
|
||||||
}
|
}
|
||||||
continue;
|
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) {
|
if (ch == '{' && warn_invalid_escape_sequence(p, ch, t) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -491,7 +502,8 @@ done:
|
||||||
*literal = PyUnicode_DecodeUTF8Stateful(literal_start,
|
*literal = PyUnicode_DecodeUTF8Stateful(literal_start,
|
||||||
s - literal_start,
|
s - literal_start,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
*literal = decode_unicode_with_escapes(p, literal_start,
|
*literal = decode_unicode_with_escapes(p, literal_start,
|
||||||
s - literal_start, t);
|
s - literal_start, t);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue