# HG changeset patch # Parent b6e33798f82a2c025ad9cd55b0d656f3c78a3684 Issue #25395: Fix crashes with highly nested OrderedDict diff -r b6e33798f82a Lib/test/test_collections.py --- a/Lib/test/test_collections.py Sun Oct 18 09:53:17 2015 +0300 +++ b/Lib/test/test_collections.py Sun Oct 18 09:01:27 2015 +0000 @@ -2025,6 +2025,14 @@ items = [('a', 1), ('c', 3), ('b', 2)] self.assertEqual(list(MyOD(items).items()), items) + def test_highly_nested(self): + # Issue 25395: crashes during garbage collection + obj = None + for _ in range(1000): + obj = self.module.OrderedDict([(None, obj)]) + del obj + support.gc_collect() + class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase): diff -r b6e33798f82a Misc/NEWS --- a/Misc/NEWS Sun Oct 18 09:53:17 2015 +0300 +++ b/Misc/NEWS Sun Oct 18 09:01:27 2015 +0000 @@ -11,6 +11,9 @@ Core and Builtins ----------------- +- Issue #25395: Fix crash when highly nested OrderedDict structures were + garbage collected. + - Issue #25274: sys.setrecursionlimit() now raises a RecursionError if the new recursion limit is too low depending at the current recursion depth. Modify also the "lower-water mark" formula to make it monotonic. This mark is used diff -r b6e33798f82a Objects/odictobject.c --- a/Objects/odictobject.c Sun Oct 18 09:53:17 2015 +0300 +++ b/Objects/odictobject.c Sun Oct 18 09:01:27 2015 +0000 @@ -1438,16 +1438,18 @@ odict_dealloc(PyODictObject *self) { PyObject_GC_UnTrack(self); - Py_TRASHCAN_SAFE_BEGIN(self); - Py_XDECREF(self->od_inst_dict); + Py_TRASHCAN_SAFE_BEGIN(self) + + Py_CLEAR(self->od_inst_dict); if (self->od_weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)self); _odict_clear_nodes(self); - Py_TRASHCAN_SAFE_END(self); /* must be last */ PyDict_Type.tp_dealloc((PyObject *)self); + + Py_TRASHCAN_SAFE_END(self) }; /* tp_repr */