From f915addb0316450fea1a3cb9c3f750c82b7b6202 Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Tue, 15 Feb 2022 20:22:03 -0500 Subject: [PATCH 1/5] For multi-character tokens like <=, >=, ==, fix assert when the first character is the last character in an f-string missing the trailing right brace. --- Lib/test/test_fstring.py | 3 +++ Parser/string_parser.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index d0b1ade15137ba..0f8b9eb45ae242 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -1053,6 +1053,9 @@ def test_mismatched_braces(self): "f'{{{'", "f'{{}}{'", "f'{'", + "f'x{<'", # See bpo-46762. + "f'x{>'", + "f'x{='", ]) # But these are just normal strings. diff --git a/Parser/string_parser.c b/Parser/string_parser.c index 0b5e30ba2ca6a4..ffed9d924c2466 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -653,8 +653,8 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec (ch == '!' || ch == ':' || ch == '}' || ch == '=' || ch == '>' || ch == '<')) { /* See if there's a next character. */ - if (*str+1 < end) { - char next = *(*str+1); + if (*str + 1 < end) { + char next = *(*str + 1); /* For "!=". since '=' is not an allowed conversion character, nothing is lost in this test. */ @@ -666,12 +666,12 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec *str += 1; continue; } - /* Don't get out of the loop for these, if they're single - chars (not part of 2-char tokens). If by themselves, they - don't end an expression (unlike say '!'). */ - if (ch == '>' || ch == '<') { - continue; - } + } + /* Don't get out of the loop for these, if they're single + chars (not part of 2-char tokens). If by themselves, they + don't end an expression (unlike say '!'). */ + if (ch == '=' || ch == '>' || ch == '<') { + continue; } /* Normal way out of this loop. */ From b53c09c6f55cc9cc79bee4ab8daabc3a30b34290 Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Tue, 15 Feb 2022 20:27:02 -0500 Subject: [PATCH 2/5] Add blurb. --- .../Core and Builtins/2022-02-15-20-26-46.bpo-46762.1H7vab.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2022-02-15-20-26-46.bpo-46762.1H7vab.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2022-02-15-20-26-46.bpo-46762.1H7vab.rst b/Misc/NEWS.d/next/Core and Builtins/2022-02-15-20-26-46.bpo-46762.1H7vab.rst new file mode 100644 index 00000000000000..cd53eb4ffaddd9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2022-02-15-20-26-46.bpo-46762.1H7vab.rst @@ -0,0 +1,2 @@ +Fix an assert failure in debug builds when a '<', '>', or '=' is the last +character in an f-string that's missing a closing right brace. From 6ee0c4fa6fd9554879cde1a50faae0a2a8f48810 Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Tue, 15 Feb 2022 20:35:26 -0500 Subject: [PATCH 3/5] Fixed handling of '='. --- Parser/string_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Parser/string_parser.c b/Parser/string_parser.c index ffed9d924c2466..7830f31359ac70 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -670,7 +670,7 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec /* Don't get out of the loop for these, if they're single chars (not part of 2-char tokens). If by themselves, they don't end an expression (unlike say '!'). */ - if (ch == '=' || ch == '>' || ch == '<') { + if (ch == '>' || ch == '<') { continue; } From 133d1078b903f8484a88cfa55da63324c6f431c1 Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Tue, 15 Feb 2022 20:36:46 -0500 Subject: [PATCH 4/5] Fix test case for '='. --- Lib/test/test_fstring.py | 1 - 1 file changed, 1 deletion(-) diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index 0f8b9eb45ae242..0c255c2af22179 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -1055,7 +1055,6 @@ def test_mismatched_braces(self): "f'{'", "f'x{<'", # See bpo-46762. "f'x{>'", - "f'x{='", ]) # But these are just normal strings. From 6bf62164c40b61dcfc68c2bb12523f63c7abb5cf Mon Sep 17 00:00:00 2001 From: "Eric V. Smith" Date: Wed, 16 Feb 2022 02:41:09 -0500 Subject: [PATCH 5/5] Remove some spaces added by Visual Studio. Improve a comment. --- Parser/string_parser.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Parser/string_parser.c b/Parser/string_parser.c index 7830f31359ac70..fae2a3648cf9f9 100644 --- a/Parser/string_parser.c +++ b/Parser/string_parser.c @@ -653,8 +653,8 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec (ch == '!' || ch == ':' || ch == '}' || ch == '=' || ch == '>' || ch == '<')) { /* See if there's a next character. */ - if (*str + 1 < end) { - char next = *(*str + 1); + if (*str+1 < end) { + char next = *(*str+1); /* For "!=". since '=' is not an allowed conversion character, nothing is lost in this test. */ @@ -698,10 +698,10 @@ fstring_find_expr(Parser *p, const char **str, const char *end, int raw, int rec } } expr_end = *str; - /* If we leave this loop in a string or with mismatched parens, we - don't care. We'll get a syntax error when compiling the - expression. But, we can produce a better error message, so - let's just do that.*/ + /* If we leave the above loop in a string or with mismatched parens, we + don't really care. We'll get a syntax error when compiling the + expression. But, we can produce a better error message, so let's just + do that.*/ if (quote_char) { RAISE_SYNTAX_ERROR("f-string: unterminated string"); goto error;