From 17aae764ba30439e56e1eadeaef2fddceeae5172 Mon Sep 17 00:00:00 2001 From: Svyatoslav Tereshin Date: Tue, 6 May 2025 15:07:08 +0000 Subject: [PATCH 1/5] Fix gh-133516 --- Lib/test/test_ast/test_ast.py | 6 ++++++ .../2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst | 2 ++ Parser/pegen.c | 8 ++++++++ 3 files changed, 16 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 09cf3186e05cc1..c480f213773c25 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -821,6 +821,12 @@ def test_constant_as_name(self): with self.assertRaisesRegex(ValueError, f"identifier field can't represent '{constant}' constant"): compile(expr, "", "eval") + def test_constant_as_unicode_name(self): + for constant in b"Tru\xe1\xb5\x89", b"Fal\xc5\xbfe", b"N\xc2\xbane": + with self.assertRaises(ValueError, + msg="identifier must not be None, True or False after NFKC normalization"): + ast.parse(constant, mode="eval") + def test_precedence_enum(self): class _Precedence(enum.IntEnum): """Precedence table that originated from python grammar.""" diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst new file mode 100644 index 00000000000000..abcd12bce780a2 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst @@ -0,0 +1,2 @@ +Raise :exc:`ValueError` when constants ``True``, ``False`` or ``None`` are +used as an identifier after NFKC normalization diff --git a/Parser/pegen.c b/Parser/pegen.c index 3efeba78450d1a..13a42e6904bd5e 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -549,6 +549,14 @@ _PyPegen_new_identifier(Parser *p, const char *n) } id = id2; } + if (_PyUnicode_EqualToASCIIString(id, "None") || + _PyUnicode_EqualToASCIIString(id, "True") || + _PyUnicode_EqualToASCIIString(id, "False")) + { + PyErr_SetString(PyExc_ValueError, "identifier must not be None, True or False after NFKC normalization"); + Py_DECREF(id); + goto error; + } PyInterpreterState *interp = _PyInterpreterState_GET(); _PyUnicode_InternImmortal(interp, &id); if (_PyArena_AddPyObject(p->arena, id) < 0) From cd5e2764ae0d2648525e4d4483c30cf9e7428dcc Mon Sep 17 00:00:00 2001 From: TERESH1 Date: Tue, 6 May 2025 19:25:31 +0300 Subject: [PATCH 2/5] Fix mistake at news Add dot to end Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com> --- .../2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst index abcd12bce780a2..b93ba11f93252b 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-05-06-15-01-41.gh-issue-133516.RqWVf2.rst @@ -1,2 +1,2 @@ Raise :exc:`ValueError` when constants ``True``, ``False`` or ``None`` are -used as an identifier after NFKC normalization +used as an identifier after NFKC normalization. From 8f737e3f824a58e482e21863b07f993232d566ab Mon Sep 17 00:00:00 2001 From: Svyatoslav Tereshin Date: Tue, 6 May 2025 16:42:50 +0000 Subject: [PATCH 3/5] Fix assert in test and make error message more friendly --- Lib/test/test_ast/test_ast.py | 4 ++-- Parser/pegen.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index c480f213773c25..884765ccafc257 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -823,8 +823,8 @@ def test_constant_as_name(self): def test_constant_as_unicode_name(self): for constant in b"Tru\xe1\xb5\x89", b"Fal\xc5\xbfe", b"N\xc2\xbane": - with self.assertRaises(ValueError, - msg="identifier must not be None, True or False after NFKC normalization"): + with self.assertRaisesRegex(ValueError, + "identifier must not be None, True or False after Unicode normalization \\(NKFC\\)"): ast.parse(constant, mode="eval") def test_precedence_enum(self): diff --git a/Parser/pegen.c b/Parser/pegen.c index 13a42e6904bd5e..7bdd32cd7cf67c 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -553,7 +553,7 @@ _PyPegen_new_identifier(Parser *p, const char *n) _PyUnicode_EqualToASCIIString(id, "True") || _PyUnicode_EqualToASCIIString(id, "False")) { - PyErr_SetString(PyExc_ValueError, "identifier must not be None, True or False after NFKC normalization"); + PyErr_SetString(PyExc_ValueError, "identifier must not be None, True or False after Unicode normalization (NKFC)"); Py_DECREF(id); goto error; } From c71edcf08d8ce75dd100c2789a23515294d0a57c Mon Sep 17 00:00:00 2001 From: Svyatoslav Tereshin Date: Wed, 7 May 2025 06:41:28 +0000 Subject: [PATCH 4/5] Reformat for PEP-7 style --- Parser/pegen.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Parser/pegen.c b/Parser/pegen.c index 7bdd32cd7cf67c..48b405e8226641 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -549,11 +549,13 @@ _PyPegen_new_identifier(Parser *p, const char *n) } id = id2; } - if (_PyUnicode_EqualToASCIIString(id, "None") || - _PyUnicode_EqualToASCIIString(id, "True") || - _PyUnicode_EqualToASCIIString(id, "False")) + if (_PyUnicode_EqualToASCIIString(id, "None") + || _PyUnicode_EqualToASCIIString(id, "True") + || _PyUnicode_EqualToASCIIString(id, "False")) { - PyErr_SetString(PyExc_ValueError, "identifier must not be None, True or False after Unicode normalization (NKFC)"); + PyErr_SetString(PyExc_ValueError, + "identifier must not be None, True or False " + "after Unicode normalization (NKFC)"); Py_DECREF(id); goto error; } From 81b6c61655c47f2fdbf6afa50716a7682566366f Mon Sep 17 00:00:00 2001 From: Svyatoslav Tereshin Date: Wed, 7 May 2025 10:45:06 +0000 Subject: [PATCH 5/5] Keep the error message the same as in the `validate_name` --- Lib/test/test_ast/test_ast.py | 11 ++++++++--- Parser/pegen.c | 23 ++++++++++++++--------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index 884765ccafc257..02628868db008c 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -822,10 +822,15 @@ def test_constant_as_name(self): compile(expr, "", "eval") def test_constant_as_unicode_name(self): - for constant in b"Tru\xe1\xb5\x89", b"Fal\xc5\xbfe", b"N\xc2\xbane": + constants = [ + ("True", b"Tru\xe1\xb5\x89"), + ("False", b"Fal\xc5\xbfe"), + ("None", b"N\xc2\xbane"), + ] + for constant in constants: with self.assertRaisesRegex(ValueError, - "identifier must not be None, True or False after Unicode normalization \\(NKFC\\)"): - ast.parse(constant, mode="eval") + f"identifier field can't represent '{constant[0]}' constant"): + ast.parse(constant[1], mode="eval") def test_precedence_enum(self): class _Precedence(enum.IntEnum): diff --git a/Parser/pegen.c b/Parser/pegen.c index 48b405e8226641..81aad47010181c 100644 --- a/Parser/pegen.c +++ b/Parser/pegen.c @@ -549,15 +549,20 @@ _PyPegen_new_identifier(Parser *p, const char *n) } id = id2; } - if (_PyUnicode_EqualToASCIIString(id, "None") - || _PyUnicode_EqualToASCIIString(id, "True") - || _PyUnicode_EqualToASCIIString(id, "False")) - { - PyErr_SetString(PyExc_ValueError, - "identifier must not be None, True or False " - "after Unicode normalization (NKFC)"); - Py_DECREF(id); - goto error; + static const char * const forbidden[] = { + "None", + "True", + "False", + NULL + }; + for (int i = 0; forbidden[i] != NULL; i++) { + if (_PyUnicode_EqualToASCIIString(id, forbidden[i])) { + PyErr_Format(PyExc_ValueError, + "identifier field can't represent '%s' constant", + forbidden[i]); + Py_DECREF(id); + goto error; + } } PyInterpreterState *interp = _PyInterpreterState_GET(); _PyUnicode_InternImmortal(interp, &id);