gh-145492: Fix defaultdict __repr__ infinite recursion (GH-145659)

Co-Authored-By: Thomas Kowalski <thom.kowa@gmail.com>
This commit is contained in:
Matt Van Horn 2026-03-10 06:20:42 -07:00 committed by GitHub
parent 728e4a075e
commit 2d35f9bc1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 2 deletions

View file

@ -204,5 +204,20 @@ def default_factory():
self.assertEqual(test_dict[key], 2)
self.assertEqual(count, 2)
def test_repr_recursive_factory(self):
# gh-145492: defaultdict.__repr__ should not cause infinite recursion
# when the factory's __repr__ calls repr() on the defaultdict.
class ProblematicFactory:
def __call__(self):
return {}
def __repr__(self):
repr(dd)
return "ProblematicFactory()"
dd = defaultdict(ProblematicFactory())
# Should not raise RecursionError
r = repr(dd)
self.assertIn('ProblematicFactory()', r)
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1,3 @@
Fix infinite recursion in :class:`collections.defaultdict` ``__repr__``
when a ``defaultdict`` contains itself. Based on analysis by KowalskiThomas
in :gh:`145492`.

View file

@ -2385,9 +2385,10 @@ defdict_repr(PyObject *op)
}
defrepr = PyUnicode_FromString("...");
}
else
else {
defrepr = PyObject_Repr(dd->default_factory);
Py_ReprLeave(dd->default_factory);
Py_ReprLeave(dd->default_factory);
}
}
if (defrepr == NULL) {
Py_DECREF(baserepr);