From 1d766449fd90ed3e769fd55d1a28f26bf41dc863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Mon, 24 Feb 2025 01:09:14 +0100 Subject: [PATCH] gh-130151: Fix reference leaks in `_hashlib.hmac_{new,digest}` (GH-130152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix leak in `_hashlib.hmac_new` * fix leak in `hmac_digest` * fix exception type in `_hashlib.HMAC.copy` (cherry picked from commit 071820113f11b8f6a21f98652d0840e10268114c) Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- ...-02-15-12-36-49.gh-issue-130151.3IFumF.rst | 2 ++ Modules/_hashopenssl.c | 36 +++++++++---------- 2 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst diff --git a/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst b/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst new file mode 100644 index 00000000000000..4638f138bc43ba --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-02-15-12-36-49.gh-issue-130151.3IFumF.rst @@ -0,0 +1,2 @@ +Fix reference leaks in :func:`!_hashlib.hmac_new` and +:func:`!_hashlib.hmac_digest`. Patch by Bénédikt Tran. diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index a04dc26587ad99..2f7d277e07bac0 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -1557,7 +1557,6 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, PyObject *digestmod) /*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/ { - PyTypeObject *type = get_hashlib_state(module)->HMACtype; PY_EVP_MD *digest; HMAC_CTX *ctx = NULL; HMACobject *self = NULL; @@ -1570,8 +1569,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, } if (digestmod == NULL) { - PyErr_SetString( - PyExc_TypeError, "Missing required parameter 'digestmod'."); + PyErr_SetString(PyExc_TypeError, + "Missing required parameter 'digestmod'."); return NULL; } @@ -1582,40 +1581,37 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, ctx = HMAC_CTX_new(); if (ctx == NULL) { - _setException(PyExc_ValueError, NULL); + PyErr_NoMemory(); goto error; } - r = HMAC_Init_ex( - ctx, - (const char*)key->buf, - (int)key->len, - digest, - NULL /*impl*/); + r = HMAC_Init_ex(ctx, key->buf, (int)key->len, digest, NULL /* impl */); PY_EVP_MD_free(digest); if (r == 0) { _setException(PyExc_ValueError, NULL); goto error; } - self = (HMACobject *)PyObject_New(HMACobject, type); + _hashlibstate *state = get_hashlib_state(module); + self = PyObject_New(HMACobject, state->HMACtype); if (self == NULL) { goto error; } self->ctx = ctx; + ctx = NULL; // 'ctx' is now owned by 'self' HASHLIB_INIT_MUTEX(self); if ((msg_obj != NULL) && (msg_obj != Py_None)) { - if (!_hmac_update(self, msg_obj)) + if (!_hmac_update(self, msg_obj)) { goto error; + } } - - return (PyObject*)self; + return (PyObject *)self; error: if (ctx) HMAC_CTX_free(ctx); - if (self) PyObject_Free(self); + Py_XDECREF(self); return NULL; } @@ -1682,14 +1678,14 @@ _hashlib_HMAC_copy_impl(HMACobject *self) HMAC_CTX *ctx = HMAC_CTX_new(); if (ctx == NULL) { - return _setException(PyExc_ValueError, NULL); + return PyErr_NoMemory(); } if (!locked_HMAC_CTX_copy(ctx, self)) { HMAC_CTX_free(ctx); return _setException(PyExc_ValueError, NULL); } - retval = (HMACobject *)PyObject_New(HMACobject, Py_TYPE(self)); + retval = PyObject_New(HMACobject, Py_TYPE(self)); if (retval == NULL) { HMAC_CTX_free(ctx); return NULL; @@ -1704,7 +1700,10 @@ static void _hmac_dealloc(HMACobject *self) { PyTypeObject *tp = Py_TYPE(self); - HMAC_CTX_free(self->ctx); + if (self->ctx != NULL) { + HMAC_CTX_free(self->ctx); + self->ctx = NULL; + } PyObject_Free(self); Py_DECREF(tp); } @@ -1749,6 +1748,7 @@ _hmac_digest(HMACobject *self, unsigned char *buf, unsigned int len) return 0; } if (!locked_HMAC_CTX_copy(temp_ctx, self)) { + HMAC_CTX_free(temp_ctx); _setException(PyExc_ValueError, NULL); return 0; }