Skip to content

Commit 26372b1

Browse files
committed
[3.14] gh-160268: Fix tokenize on a mismatched closing bracket in an f-string (GH-160272)
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) Co-authored-by: Lysandros Nikolaou <lisandrosnik@gmail.com>
1 parent 4ba8b7b commit 26372b1

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a crash in :mod:`tokenize` when a mismatched closing bracket follows the opening brace of an f-string or t-string replacement field, as in ``f'{]a'``. 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
@@ -1283,9 +1283,9 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
12831283
if (tok->level > 0) {
12841284
tok->level--;
12851285
int opening = tok->parenstack[tok->level];
1286-
if (!tok->tok_extra_tokens && !((opening == '(' && c == ')') ||
1287-
(opening == '[' && c == ']') ||
1288-
(opening == '{' && c == '}'))) {
1286+
if (!((opening == '(' && c == ')') ||
1287+
(opening == '[' && c == ']') ||
1288+
(opening == '{' && c == '}'))) {
12891289
/* If the opening bracket belongs to an f-string's expression
12901290
part (e.g. f"{)}") and the closing bracket is an arbitrary
12911291
nested expression, then instead of matching a different
@@ -1299,7 +1299,10 @@ tok_get_normal_mode(struct tok_state *tok, tokenizer_mode* current_tok, struct t
12991299
"%c-string: unmatched '%c'", TOK_GET_STRING_PREFIX(tok), c));
13001300
}
13011301
}
1302-
if (tok->parenlinenostack[tok->level] != tok->lineno) {
1302+
if (tok->tok_extra_tokens) {
1303+
/* Allow other mismatched brackets. */
1304+
}
1305+
else if (tok->parenlinenostack[tok->level] != tok->lineno) {
13031306
return MAKE_TOKEN(_PyTokenizer_syntaxerror(tok,
13041307
"closing parenthesis '%c' does not match "
13051308
"opening parenthesis '%c' on line %d",

0 commit comments

Comments
 (0)