https://github.com/python/cpython/commit/bc92e7878f252fffbabfce6a0a453f99248b5f94 commit: bc92e7878f252fffbabfce6a0a453f99248b5f94 branch: 3.13 author: Jelle Zijlstra <[email protected]> committer: JelleZijlstra <[email protected]> date: 2026-01-27T20:37:35-08:00 summary:
[3.13] gh-144169: Fix three crashes in AST objects with non-str kwargs (GH-144178) (#144260) (cherry picked from commit 639c1ad4f1ef5c2409a62fa8ed16e6aa3a6f9ab8) Co-authored-by: Jelle Zijlstra <[email protected]> Co-authored-by: Victor Stinner <[email protected]> files: A Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst M Lib/test/test_ast/test_ast.py M Parser/asdl_c.py M Python/Python-ast.c diff --git a/Lib/test/test_ast/test_ast.py b/Lib/test/test_ast/test_ast.py index a8d111a4afe797..38dfc533c7eb2c 100644 --- a/Lib/test/test_ast/test_ast.py +++ b/Lib/test/test_ast/test_ast.py @@ -3141,6 +3141,27 @@ class _AllFieldTypes(ast.AST): self.assertIs(obj.a, None) self.assertEqual(obj.b, []) + def test_non_str_kwarg(self): + warn_msg = "got an unexpected keyword argument <object object" + with ( + self.assertRaises(TypeError), + self.assertWarnsRegex(DeprecationWarning, warn_msg), + ): + ast.Name(**{object(): 'y'}) + + class FakeStr: + def __init__(self, value): + self.value = value + + def __hash__(self): + return hash(self.value) + + def __eq__(self, other): + return isinstance(other, str) and self.value == other + + with self.assertRaisesRegex(TypeError, "got multiple values for argument"): + ast.Name("x", **{FakeStr('id'): 'y'}) + @support.cpython_only class ModuleStateTests(unittest.TestCase): diff --git a/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst b/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst new file mode 100644 index 00000000000000..e2ef3d7c051d14 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-01-23-06-43-21.gh-issue-144169.LFy9yi.rst @@ -0,0 +1,2 @@ +Fix three crashes when non-string keyword arguments are supplied to objects +in the :mod:`ast` module. diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 99312b36cd33c3..b69f7f0f0727d2 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -939,7 +939,7 @@ def visitModule(self, mod): } if (p == 0) { PyErr_Format(PyExc_TypeError, - "%.400s got multiple values for argument '%U'", + "%.400s got multiple values for argument %R", Py_TYPE(self)->tp_name, key); res = -1; goto cleanup; @@ -962,7 +962,7 @@ def visitModule(self, mod): else if (contains == 0) { if (PyErr_WarnFormat( PyExc_DeprecationWarning, 1, - "%.400s.__init__ got an unexpected keyword argument '%U'. " + "%.400s.__init__ got an unexpected keyword argument %R. " "Support for arbitrary keyword arguments is deprecated " "and will be removed in Python 3.15.", Py_TYPE(self)->tp_name, key diff --git a/Python/Python-ast.c b/Python/Python-ast.c index a71262c7f84abe..1871ca3fb3dd65 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -5136,7 +5136,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw) } if (p == 0) { PyErr_Format(PyExc_TypeError, - "%.400s got multiple values for argument '%U'", + "%.400s got multiple values for argument %R", Py_TYPE(self)->tp_name, key); res = -1; goto cleanup; @@ -5159,7 +5159,7 @@ ast_type_init(PyObject *self, PyObject *args, PyObject *kw) else if (contains == 0) { if (PyErr_WarnFormat( PyExc_DeprecationWarning, 1, - "%.400s.__init__ got an unexpected keyword argument '%U'. " + "%.400s.__init__ got an unexpected keyword argument %R. " "Support for arbitrary keyword arguments is deprecated " "and will be removed in Python 3.15.", Py_TYPE(self)->tp_name, key _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
