summaryrefslogtreecommitdiffstats
path: root/Modules/cPickle.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/cPickle.c')
-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;