]> granicus.if.org Git - python/commitdiff
issue 2045: Infinite recursion when printing a subclass of defaultdict,
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Fri, 8 Feb 2008 01:05:21 +0000 (01:05 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Fri, 8 Feb 2008 01:05:21 +0000 (01:05 +0000)
if default_factory is set to a bound method.

Backport of r60663.

Lib/test/test_defaultdict.py
Misc/NEWS
Modules/collectionsmodule.c

index 08be005b424be9f8ba6a9d9d9240885d14c548ae..5724fd0460dd3890ca5d27a9654531b158913cab 100644 (file)
@@ -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)
index e3a4aceecec18fa1a9177904a443f06f8504edfc..cf73bcae07bf674536932f0d946b1e330ef21cfd 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5.2c1?
 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.
+
 - Issue #1920: "while 0" statements were completely removed by the compiler,
   even in the presence of an "else" clause, which is supposed to be run when 
   the condition is false. Now the compiler correctly emits bytecode for the
index 9d128fc95914972a2e83b95d598a97f76408bfd6..dd3c0b7d8f182d0aab41ff9b20e27b6eac2bd39d 100644 (file)
@@ -1217,7 +1217,17 @@ defdict_repr(defdictobject *dd)
        if (dd->default_factory == NULL)
                defrepr = PyString_FromString("None");
        else
-               defrepr = PyObject_Repr(dd->default_factory);
+       {
+               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;