[Python-checkins] r60664 - in python/branches/release25-maint: Lib/test/test_defaultdict.py Misc/NEWS Modules/collectionsmodule.c

amaury.forgeotdarc python-checkins at python.org
Fri Feb 8 02:05:21 CET 2008


Author: amaury.forgeotdarc
Date: Fri Feb  8 02:05:21 2008
New Revision: 60664

Modified:
   python/branches/release25-maint/Lib/test/test_defaultdict.py
   python/branches/release25-maint/Misc/NEWS
   python/branches/release25-maint/Modules/collectionsmodule.c
Log:
issue 2045: Infinite recursion when printing a subclass of defaultdict,
if default_factory is set to a bound method.

Backport of r60663.


Modified: python/branches/release25-maint/Lib/test/test_defaultdict.py
==============================================================================
--- python/branches/release25-maint/Lib/test/test_defaultdict.py	(original)
+++ python/branches/release25-maint/Lib/test/test_defaultdict.py	Fri Feb  8 02:05:21 2008
@@ -141,6 +141,29 @@
         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)

Modified: python/branches/release25-maint/Misc/NEWS
==============================================================================
--- python/branches/release25-maint/Misc/NEWS	(original)
+++ python/branches/release25-maint/Misc/NEWS	Fri Feb  8 02:05:21 2008
@@ -12,6 +12,9 @@
 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

Modified: python/branches/release25-maint/Modules/collectionsmodule.c
==============================================================================
--- python/branches/release25-maint/Modules/collectionsmodule.c	(original)
+++ python/branches/release25-maint/Modules/collectionsmodule.c	Fri Feb  8 02:05:21 2008
@@ -1217,7 +1217,17 @@
 	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;


More information about the Python-checkins mailing list