Commit f43ee81e authored by Amaury Forgeot d'Arc's avatar Amaury Forgeot d'Arc

#4170: Fix segfault when pickling a defauldict object.

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.
parent 73b90a8d
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import os import os
import copy import copy
import pickle
import tempfile import tempfile
import unittest import unittest
from test import support from test import support
...@@ -164,6 +165,13 @@ class TestDefaultDict(unittest.TestCase): ...@@ -164,6 +165,13 @@ class TestDefaultDict(unittest.TestCase):
finally: finally:
os.remove(tfn) 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(): def test_main():
support.run_unittest(TestDefaultDict) support.run_unittest(TestDefaultDict)
......
...@@ -15,6 +15,9 @@ What's New in Python 3.0 beta 5 ...@@ -15,6 +15,9 @@ What's New in Python 3.0 beta 5
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #4170: Pickling a collections.defaultdict object would crash the
interpreter.
- Issue #4146: Compilation on OpenBSD has been restored. - Issue #4146: Compilation on OpenBSD has been restored.
- Issue #3574: compile() incorrectly handled source code encoded as Latin-1. - Issue #3574: compile() incorrectly handled source code encoded as Latin-1.
......
...@@ -1155,6 +1155,7 @@ defdict_reduce(defdictobject *dd) ...@@ -1155,6 +1155,7 @@ defdict_reduce(defdictobject *dd)
*/ */
PyObject *args; PyObject *args;
PyObject *items; PyObject *items;
PyObject *iter;
PyObject *result; PyObject *result;
if (dd->default_factory == NULL || dd->default_factory == Py_None) if (dd->default_factory == NULL || dd->default_factory == Py_None)
args = PyTuple_New(0); args = PyTuple_New(0);
...@@ -1167,8 +1168,15 @@ defdict_reduce(defdictobject *dd) ...@@ -1167,8 +1168,15 @@ defdict_reduce(defdictobject *dd)
Py_DECREF(args); Py_DECREF(args);
return NULL; 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, 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(items);
Py_DECREF(args); Py_DECREF(args);
return result; return result;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment