diff options
author | neonene <53406459+neonene@users.noreply.github.com> | 2024-08-24 04:07:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-24 04:07:01 (GMT) |
commit | 5ff638f1b53587b9f912a18fc776a2a141fd7bed (patch) | |
tree | d9eec36771430a7cee176255f5ae6f1c8ecabf1f | |
parent | 556e8556849cb9df0666629b0f564b5dd203344c (diff) | |
download | cpython-5ff638f1b53587b9f912a18fc776a2a141fd7bed.zip cpython-5ff638f1b53587b9f912a18fc776a2a141fd7bed.tar.gz cpython-5ff638f1b53587b9f912a18fc776a2a141fd7bed.tar.bz2 |
gh-123243: Fix reference leak in `_decimal` (#123244)
-rw-r--r-- | Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst | 1 | ||||
-rw-r--r-- | Modules/_decimal/_decimal.c | 26 |
2 files changed, 25 insertions, 2 deletions
diff --git a/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst b/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst new file mode 100644 index 0000000..cf52585 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-22-20-10-13.gh-issue-123243.Kifj1L.rst @@ -0,0 +1 @@ +Fix memory leak in :mod:`!_decimal`. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 15855e2..0e743a6 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -1390,6 +1390,10 @@ context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED) CtxCaps(self) = 1; self->tstate = NULL; + if (type == state->PyDecContext_Type) { + PyObject_GC_Track(self); + } + assert(PyObject_GC_IsTracked((PyObject *)self)); return (PyObject *)self; } @@ -2038,6 +2042,10 @@ PyDecType_New(PyTypeObject *type) MPD(dec)->alloc = _Py_DEC_MINALLOC; MPD(dec)->data = dec->data; + if (type == state->PyDec_Type) { + PyObject_GC_Track(dec); + } + assert(PyObject_GC_IsTracked((PyObject *)dec)); return (PyObject *)dec; } #define dec_alloc(st) PyDecType_New((st)->PyDec_Type) @@ -6143,8 +6151,22 @@ decimal_clear(PyObject *module) Py_CLEAR(state->SignalTuple); Py_CLEAR(state->PyDecimal); - PyMem_Free(state->signal_map); - PyMem_Free(state->cond_map); + if (state->signal_map != NULL) { + for (DecCondMap *cm = state->signal_map; cm->name != NULL; cm++) { + Py_DECREF(cm->ex); + } + PyMem_Free(state->signal_map); + state->signal_map = NULL; + } + + if (state->cond_map != NULL) { + // cond_map[0].ex has borrowed a reference from signal_map[0].ex + for (DecCondMap *cm = state->cond_map + 1; cm->name != NULL; cm++) { + Py_DECREF(cm->ex); + } + PyMem_Free(state->cond_map); + state->cond_map = NULL; + } return 0; } |