mirror of
https://github.com/python/cpython.git
synced 2025-07-29 14:15:07 +00:00
issue 2045: Infinite recursion when printing a subclass of defaultdict,
if default_factory is set to a bound method. Will backport.
This commit is contained in:
parent
48397d6c22
commit
b01aa430d5
3 changed files with 37 additions and 1 deletions
|
@ -141,6 +141,29 @@ class TestDefaultDict(unittest.TestCase):
|
|||
else:
|
||||
self.fail("expected KeyError")
|
||||
|
||||
def test_recursive_repr(self):
|
||||
# Issue2045: stack overflow when default_factory is a bound method
|
||||
class sub(defaultdict):
|
||||
def __init__(self):
|
||||
self.default_factory = self._factory
|
||||
def _factory(self):
|
||||
return []
|
||||
d = sub()
|
||||
self.assert_(repr(d).startswith(
|
||||
"defaultdict(<bound method sub._factory of defaultdict(..."))
|
||||
|
||||
# NOTE: printing a subclass of a builtin type does not call its
|
||||
# tp_print slot. So this part is essentially the same test as above.
|
||||
tfn = tempfile.mktemp()
|
||||
try:
|
||||
f = open(tfn, "w+")
|
||||
try:
|
||||
print >>f, d
|
||||
finally:
|
||||
f.close()
|
||||
finally:
|
||||
os.remove(tfn)
|
||||
|
||||
|
||||
def test_main():
|
||||
test_support.run_unittest(TestDefaultDict)
|
||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 2.6 alpha 1?
|
|||
Core and builtins
|
||||
-----------------
|
||||
|
||||
- Issue #2045: Fix an infinite recursion triggered when printing a subclass of
|
||||
collections.defaultdict, if its default_factory is set to a bound method.
|
||||
|
||||
- Fixed a minor memory leak in dictobject.c. The content of the free
|
||||
list was not freed on interpreter shutdown.
|
||||
|
||||
|
|
|
@ -1299,8 +1299,18 @@ defdict_repr(defdictobject *dd)
|
|||
return NULL;
|
||||
if (dd->default_factory == NULL)
|
||||
defrepr = PyString_FromString("None");
|
||||
else
|
||||
{
|
||||
int status = Py_ReprEnter(dd->default_factory);
|
||||
if (status != 0) {
|
||||
if (status < 0)
|
||||
return NULL;
|
||||
defrepr = PyString_FromString("...");
|
||||
}
|
||||
else
|
||||
defrepr = PyObject_Repr(dd->default_factory);
|
||||
Py_ReprLeave(dd->default_factory);
|
||||
}
|
||||
if (defrepr == NULL) {
|
||||
Py_DECREF(baserepr);
|
||||
return NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue