summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-11-07 09:15:32 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-11-07 09:15:32 (GMT)
commitda87e45add0d8a4834a43a57ba26e6c6d74a7ab8 (patch)
treec694d5651ac6a8e1087294a321f4e78480f530c3 /Modules
parent43415ba5717fcdac45c36f6880e90a114dd538ad (diff)
downloadcpython-da87e45add0d8a4834a43a57ba26e6c6d74a7ab8.zip
cpython-da87e45add0d8a4834a43a57ba26e6c6d74a7ab8.tar.gz
cpython-da87e45add0d8a4834a43a57ba26e6c6d74a7ab8.tar.bz2
Issue #892902: Fixed pickling recursive objects.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/cPickle.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index 89448a6..0e93723 100644
--- a/Modules/cPickle.c
+++ b/Modules/cPickle.c
@@ -2533,6 +2533,27 @@ save_reduce(Picklerobject *self, PyObject *args, PyObject *fn, PyObject *ob)
/* Memoize. */
/* XXX How can ob be NULL? */
if (ob != NULL) {
+ /* If the object is already in the memo, this means it is
+ recursive. In this case, throw away everything we put on the
+ stack, and fetch the object back from the memo. */
+ if (Py_REFCNT(ob) > 1 && !self->fast) {
+ PyObject *py_ob_id = PyLong_FromVoidPtr(ob);
+ if (!py_ob_id)
+ return -1;
+ if (PyDict_GetItem(self->memo, py_ob_id)) {
+ const char pop_op = POP;
+ if (self->write_func(self, &pop_op, 1) < 0 ||
+ get(self, py_ob_id) < 0) {
+ Py_DECREF(py_ob_id);
+ return -1;
+ }
+ Py_DECREF(py_ob_id);
+ return 0;
+ }
+ Py_DECREF(py_ob_id);
+ if (PyErr_Occurred())
+ return -1;
+ }
if (state && !PyDict_Check(state)) {
if (put2(self, ob) < 0)
return -1;