From f43ee81ef211d9c79f8bbaa3ab369d387c2dfeb6 Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Thu, 30 Oct 2008 20:58:42 +0000 Subject: [PATCH] #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. --- Lib/test/test_defaultdict.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_collectionsmodule.c | 10 +++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_defaultdict.py b/Lib/test/test_defaultdict.py index 49519ab06a0..00bd9dc516e 100644 --- a/Lib/test/test_defaultdict.py +++ b/Lib/test/test_defaultdict.py @@ -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) diff --git a/Misc/NEWS b/Misc/NEWS index 5b5a125af49..a557b52df73 100644 --- 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. diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c index 8e5142051a2..d7a60429a3e 100644 --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -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;