gh-130151: Fix reference leaks in _hashlib.hmac_{new,digest} (GH-130152)

* fix leak in `_hashlib.hmac_new`
* fix leak in `hmac_digest`
* fix exception type in `_hashlib.HMAC.copy`
This commit is contained in:
Bénédikt Tran 2025-02-24 01:09:14 +01:00 committed by GitHub
parent 72ea3c030a
commit 071820113f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 18 deletions

View File

@ -0,0 +1,2 @@
Fix reference leaks in :func:`!_hashlib.hmac_new` and
:func:`!_hashlib.hmac_digest`. Patch by Bénédikt Tran.

View File

@ -1556,7 +1556,6 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
PyObject *digestmod) PyObject *digestmod)
/*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/ /*[clinic end generated code: output=c20d9e4d9ed6d219 input=5f4071dcc7f34362]*/
{ {
PyTypeObject *type = get_hashlib_state(module)->HMACtype;
PY_EVP_MD *digest; PY_EVP_MD *digest;
HMAC_CTX *ctx = NULL; HMAC_CTX *ctx = NULL;
HMACobject *self = NULL; HMACobject *self = NULL;
@ -1569,8 +1568,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
} }
if (digestmod == NULL) { if (digestmod == NULL) {
PyErr_SetString( PyErr_SetString(PyExc_TypeError,
PyExc_TypeError, "Missing required parameter 'digestmod'."); "Missing required parameter 'digestmod'.");
return NULL; return NULL;
} }
@ -1581,40 +1580,37 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
ctx = HMAC_CTX_new(); ctx = HMAC_CTX_new();
if (ctx == NULL) { if (ctx == NULL) {
_setException(PyExc_ValueError, NULL); PyErr_NoMemory();
goto error; goto error;
} }
r = HMAC_Init_ex( r = HMAC_Init_ex(ctx, key->buf, (int)key->len, digest, NULL /* impl */);
ctx,
(const char*)key->buf,
(int)key->len,
digest,
NULL /*impl*/);
PY_EVP_MD_free(digest); PY_EVP_MD_free(digest);
if (r == 0) { if (r == 0) {
_setException(PyExc_ValueError, NULL); _setException(PyExc_ValueError, NULL);
goto error; goto error;
} }
self = (HMACobject *)PyObject_New(HMACobject, type); _hashlibstate *state = get_hashlib_state(module);
self = PyObject_New(HMACobject, state->HMACtype);
if (self == NULL) { if (self == NULL) {
goto error; goto error;
} }
self->ctx = ctx; self->ctx = ctx;
ctx = NULL; // 'ctx' is now owned by 'self'
HASHLIB_INIT_MUTEX(self); HASHLIB_INIT_MUTEX(self);
if ((msg_obj != NULL) && (msg_obj != Py_None)) { if ((msg_obj != NULL) && (msg_obj != Py_None)) {
if (!_hmac_update(self, msg_obj)) if (!_hmac_update(self, msg_obj)) {
goto error; goto error;
}
} }
return (PyObject *)self;
return (PyObject*)self;
error: error:
if (ctx) HMAC_CTX_free(ctx); if (ctx) HMAC_CTX_free(ctx);
if (self) PyObject_Free(self); Py_XDECREF(self);
return NULL; return NULL;
} }
@ -1681,14 +1677,14 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
HMAC_CTX *ctx = HMAC_CTX_new(); HMAC_CTX *ctx = HMAC_CTX_new();
if (ctx == NULL) { if (ctx == NULL) {
return _setException(PyExc_ValueError, NULL); return PyErr_NoMemory();
} }
if (!locked_HMAC_CTX_copy(ctx, self)) { if (!locked_HMAC_CTX_copy(ctx, self)) {
HMAC_CTX_free(ctx); HMAC_CTX_free(ctx);
return _setException(PyExc_ValueError, NULL); return _setException(PyExc_ValueError, NULL);
} }
retval = (HMACobject *)PyObject_New(HMACobject, Py_TYPE(self)); retval = PyObject_New(HMACobject, Py_TYPE(self));
if (retval == NULL) { if (retval == NULL) {
HMAC_CTX_free(ctx); HMAC_CTX_free(ctx);
return NULL; return NULL;
@ -1703,7 +1699,10 @@ static void
_hmac_dealloc(HMACobject *self) _hmac_dealloc(HMACobject *self)
{ {
PyTypeObject *tp = Py_TYPE(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); PyObject_Free(self);
Py_DECREF(tp); Py_DECREF(tp);
} }
@ -1748,6 +1747,7 @@ _hmac_digest(HMACobject *self, unsigned char *buf, unsigned int len)
return 0; return 0;
} }
if (!locked_HMAC_CTX_copy(temp_ctx, self)) { if (!locked_HMAC_CTX_copy(temp_ctx, self)) {
HMAC_CTX_free(temp_ctx);
_setException(PyExc_ValueError, NULL); _setException(PyExc_ValueError, NULL);
return 0; return 0;
} }