Skip to content

Commit 90d0d66

Browse files
authored
[3.15] gh-160268: Fix tokenize on a mismatched closing bracket in an f-string (GH-160272) (#160335)
Since gh-105042, `tokenize` tolerates mismatched brackets. That also let a mismatched closing bracket pop the brace that opened an f-string replacement field, which the f-string state relies on. In `f'{]a'`, this triggered an assertion failure in _PyLexer_scan_string. Check the replacement field brace in both modes. (cherry picked from commit 86758d1)
1 parent c6ada40 commit 90d0d66

2 files changed

Lines changed: 10 additions & 4 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a crash in :mod:`tokenize` when a mismatched closing bracket follows the
2+
opening brace of an f-string or t-string replacement field, as in ``f'{]a'``.
3+
It now raises the same "unmatched" error as the parser.

‎Parser/lexer/lexer.c‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,9 +1293,9 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
12931293
if (tok->level > 0) {
12941294
tok->level--;
12951295
int opening = tok->parenstack[tok->level];
1296-
if (!tok->tok_extra_tokens && !((opening == '(' && c == ')') ||
1297-
(opening == '[' && c == ']') ||
1298-
(opening == '{' && c == '}'))) {
1296+
if (!((opening == '(' && c == ')') ||
1297+
(opening == '[' && c == ']') ||
1298+
(opening == '{' && c == '}'))) {
12991299
/* If the opening bracket belongs to an f-string's expression
13001300
part (e.g. f"{)}") and the closing bracket is an arbitrary
13011301
nested expression, then instead of matching a different
@@ -1309,7 +1309,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
13091309
"%c-string: unmatched '%c'", TOK_GET_STRING_PREFIX(tok), c));
13101310
}
13111311
}
1312-
if (tok->parenlinenostack[tok->level] != tok->lineno) {
1312+
if (tok->tok_extra_tokens) {
1313+
/* Allow other mismatched brackets. */
1314+
}
1315+
else if (tok->parenlinenostack[tok->level] != tok->lineno) {
13131316
return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok,
13141317
"closing parenthesis '%c' does not match "
13151318
"opening parenthesis '%c' on line %d",

0 commit comments

Comments
 (0)