]> granicus.if.org Git - python/commitdiff
#4170: Fix segfault when pickling a defauldict object.
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 30 Oct 2008 20:58:42 +0000 (20:58 +0000)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>
Thu, 30 Oct 2008 20:58:42 +0000 (20:58 +0000)
The 2.x dict.iteritems() returns an iterator,
whereas the 3.0 dict.items() returns a "view",
which is iterable, but not an iterator with its __next__ method.

Patch by Hirokazu Yamamoto.

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

index 49519ab06a06484c1d86a1fc07cdf4e802c7517a..00bd9dc516e19518047a3f5117d40fd76ec64f0d 100644 (file)
@@ -2,6 +2,7 @@
 
 import os
 import copy
+import pickle
 import tempfile
 import unittest
 from test import support
@@ -164,6 +165,13 @@ class TestDefaultDict(unittest.TestCase):
         finally:
             os.remove(tfn)
 
+    def test_pickleing(self):
+        d = defaultdict(int)
+        d[1]
+        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+            s = pickle.dumps(d, proto)
+            o = pickle.loads(s)
+            self.assertEqual(d, o)
 
 def test_main():
     support.run_unittest(TestDefaultDict)
index 5b5a125af4903aeef4daefa2a01534eb8cdb69c4..a557b52df7324d02168c10d66aecb32c3ad377ba 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,9 @@ What's New in Python 3.0 beta 5
 Core and Builtins
 -----------------
 
+- Issue #4170: Pickling a collections.defaultdict object would crash the
+  interpreter.
+
 - Issue #4146: Compilation on OpenBSD has been restored.
 
 - Issue #3574: compile() incorrectly handled source code encoded as Latin-1.
index 8e5142051a2893a12504c1033188e552bd7e1189..d7a60429a3e8581bd06f389c54390be20080953a 100644 (file)
@@ -1155,6 +1155,7 @@ defdict_reduce(defdictobject *dd)
        */
        PyObject *args;
        PyObject *items;
+       PyObject *iter;
        PyObject *result;
        if (dd->default_factory == NULL || dd->default_factory == Py_None)
                args = PyTuple_New(0);
@@ -1167,8 +1168,15 @@ defdict_reduce(defdictobject *dd)
                Py_DECREF(args);
                return NULL;
        }
+       iter = PyObject_GetIter(items);
+       if (iter == NULL) {
+               Py_DECREF(items);
+               Py_DECREF(args);
+               return NULL;
+       }
        result = PyTuple_Pack(5, Py_TYPE(dd), args,
-                             Py_None, Py_None, items);
+                             Py_None, Py_None, iter);
+       Py_DECREF(iter);
        Py_DECREF(items);
        Py_DECREF(args);
        return result;