summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst2
-rw-r--r--Modules/_pickle.c15
2 files changed, 17 insertions, 0 deletions
diff --git a/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst b/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst
new file mode 100644
index 0000000..8bde68f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-07-28-20-48-05.bpo-41422.iMwnMu.rst
@@ -0,0 +1,2 @@
+Fixed memory leaks of :class:`pickle.Pickler` and :class:`pickle.Unpickler` involving cyclic references via the
+internal memo mapping.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index d2f6d71..2bf9977 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -4712,6 +4712,14 @@ Pickler_traverse(PicklerObject *self, visitproc visit, void *arg)
Py_VISIT(self->fast_memo);
Py_VISIT(self->reducer_override);
Py_VISIT(self->buffer_callback);
+ PyMemoTable *memo = self->memo;
+ if (memo && memo->mt_table) {
+ Py_ssize_t i = memo->mt_allocated;
+ while (--i >= 0) {
+ Py_VISIT(memo->mt_table[i].me_key);
+ }
+ }
+
return 0;
}
@@ -7181,6 +7189,13 @@ Unpickler_traverse(UnpicklerObject *self, visitproc visit, void *arg)
Py_VISIT(self->stack);
Py_VISIT(self->pers_func);
Py_VISIT(self->buffers);
+ PyObject **memo = self->memo;
+ if (memo) {
+ Py_ssize_t i = self->memo_size;
+ while (--i >= 0) {
+ Py_VISIT(memo[i]);
+ }
+ }
return 0;
}