diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-11-07 09:15:32 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-11-07 09:15:32 (GMT) |
commit | da87e45add0d8a4834a43a57ba26e6c6d74a7ab8 (patch) | |
tree | c694d5651ac6a8e1087294a321f4e78480f530c3 /Modules | |
parent | 43415ba5717fcdac45c36f6880e90a114dd538ad (diff) | |
download | cpython-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.c | 21 |
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; |