Skip to content

Commit f93b578

Browse files
committed
gh-144169: Fix three crashes in AST objects with non-str kwargs
1 parent f3dd0ca commit f93b578

File tree

4 files changed

+34
-6
lines changed

4 files changed

+34
-6
lines changed

Lib/test/test_ast/test_ast.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,12 @@ def test_replace_reject_unknown_instance_fields(self):
14431443
self.assertIs(node.ctx, context)
14441444
self.assertRaises(AttributeError, getattr, node, 'unknown')
14451445

1446+
def test_replace_non_str_kwarg(self):
1447+
node = ast.Name(id="x")
1448+
with self.assertRaisesRegex(TypeError, "got an unexpected keyword argument <object object"):
1449+
node.__replace__(**{object(): "y"})
1450+
1451+
14461452
class ASTHelpers_Test(unittest.TestCase):
14471453
maxDiff = None
14481454

@@ -3304,6 +3310,26 @@ class _AllFieldTypes(ast.AST):
33043310
self.assertIs(obj.a, None)
33053311
self.assertEqual(obj.b, [])
33063312

3313+
def test_non_str_kwarg(self):
3314+
with (
3315+
self.assertRaises(TypeError),
3316+
self.assertWarnsRegex(DeprecationWarning, "got an unexpected keyword argument <object object"),
3317+
):
3318+
ast.Name(**{object(): 'y'})
3319+
3320+
class FakeStr:
3321+
def __init__(self, value):
3322+
self.value = value
3323+
3324+
def __hash__(self):
3325+
return hash(self.value)
3326+
3327+
def __eq__(self, other):
3328+
return isinstance(other, str) and self.value == other
3329+
3330+
with self.assertRaisesRegex(TypeError, "got multiple values for argument"):
3331+
ast.Name("x", **{FakeStr('id'): 'y'})
3332+
33073333

33083334
@support.cpython_only
33093335
class ModuleStateTests(unittest.TestCase):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix three crashes when non-string keyword arguments are supplied to objects
2+
in the :mod:`ast` module.

Parser/asdl_c.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,7 @@ def visitModule(self, mod):
942942
}
943943
if (p == 0) {
944944
PyErr_Format(PyExc_TypeError,
945-
"%.400s got multiple values for argument '%U'",
945+
"%.400s got multiple values for argument %R",
946946
Py_TYPE(self)->tp_name, key);
947947
res = -1;
948948
goto cleanup;
@@ -965,7 +965,7 @@ def visitModule(self, mod):
965965
else if (contains == 0) {
966966
if (PyErr_WarnFormat(
967967
PyExc_DeprecationWarning, 1,
968-
"%.400s.__init__ got an unexpected keyword argument '%U'. "
968+
"%.400s.__init__ got an unexpected keyword argument %R. "
969969
"Support for arbitrary keyword arguments is deprecated "
970970
"and will be removed in Python 3.15.",
971971
Py_TYPE(self)->tp_name, key
@@ -1207,7 +1207,7 @@ def visitModule(self, mod):
12071207
if (rc == 0) {
12081208
PyErr_Format(PyExc_TypeError,
12091209
"%.400s.__replace__ got an unexpected keyword "
1210-
"argument '%U'.", Py_TYPE(self)->tp_name, key);
1210+
"argument %R.", Py_TYPE(self)->tp_name, key);
12111211
Py_DECREF(expecting);
12121212
return -1;
12131213
}

Python/Python-ast.c

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)