https://github.com/python/cpython/commit/9643ce9019c9f01a0e5d773d3abddb79471fa19a commit: 9643ce9019c9f01a0e5d773d3abddb79471fa19a branch: 3.13 author: Bénédikt Tran <10796600+picn...@users.noreply.github.com> committer: picnixz <10796600+picn...@users.noreply.github.com> date: 2025-03-03T11:01:01Z summary:
[3.13] gh-127667: fix memory leaks in `hashlib` (GH-127668) (#130784) gh-127667: fix memory leaks in `hashlib` (GH-127668) - Correctly handle `NULL` values returned by `EVP_MD_CTX_md`. - Correctly free resources in error branches. - Consistently suppress `_setException()` return value when needed. - Collapse `_setException() + return NULL` into a single statement. (cherry-picked from commit 097846502b7f33cb327d512e2a396acf4f4de46e) files: M Modules/_hashopenssl.c diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index 2f7d277e07bac0..fef0ed4a0b8844 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -427,7 +427,8 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht) } } if (digest == NULL) { - _setException(state->unsupported_digestmod_error, "unsupported hash type %s", name); + (void)_setException(state->unsupported_digestmod_error, + "unsupported hash type %s", name); return NULL; } return digest; @@ -442,7 +443,6 @@ py_digest_by_name(PyObject *module, const char *name, enum Py_hash_type py_ht) */ static PY_EVP_MD* py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type py_ht) { - PY_EVP_MD* evp; PyObject *name_obj = NULL; const char *name; @@ -468,12 +468,7 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type return NULL; } - evp = py_digest_by_name(module, name, py_ht); - if (evp == NULL) { - return NULL; - } - - return evp; + return py_digest_by_name(module, name, py_ht); } static EVPobject * @@ -506,7 +501,7 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len) else process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int); if (!EVP_DigestUpdate(self->ctx, (const void*)cp, process)) { - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); return -1; } len -= process; @@ -582,17 +577,20 @@ EVP_digest_impl(EVPobject *self) } if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - return _setException(PyExc_ValueError, NULL); + goto error; } digest_size = EVP_MD_CTX_size(temp_ctx); if (!EVP_DigestFinal(temp_ctx, digest, NULL)) { - _setException(PyExc_ValueError, NULL); - return NULL; + goto error; } retval = PyBytes_FromStringAndSize((const char *)digest, digest_size); EVP_MD_CTX_free(temp_ctx); return retval; + +error: + EVP_MD_CTX_free(temp_ctx); + return _setException(PyExc_ValueError, NULL); } /*[clinic input] @@ -617,17 +615,20 @@ EVP_hexdigest_impl(EVPobject *self) /* Get the raw (binary) digest value */ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - return _setException(PyExc_ValueError, NULL); + goto error; } digest_size = EVP_MD_CTX_size(temp_ctx); if (!EVP_DigestFinal(temp_ctx, digest, NULL)) { - _setException(PyExc_ValueError, NULL); - return NULL; + goto error; } EVP_MD_CTX_free(temp_ctx); return _Py_strhex((const char *)digest, (Py_ssize_t)digest_size); + +error: + EVP_MD_CTX_free(temp_ctx); + return _setException(PyExc_ValueError, NULL); } /*[clinic input] @@ -695,7 +696,11 @@ EVP_get_digest_size(EVPobject *self, void *closure) static PyObject * EVP_get_name(EVPobject *self, void *closure) { - return py_digest_name(EVP_MD_CTX_md(self->ctx)); + const EVP_MD *md = EVP_MD_CTX_md(self->ctx); + if (md == NULL) { + return _setException(PyExc_ValueError, NULL); + } + return py_digest_name(md); } static PyGetSetDef EVP_getseters[] = { @@ -793,21 +798,22 @@ EVPXOF_digest_impl(EVPobject *self, Py_ssize_t length) } if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - Py_DECREF(retval); - EVP_MD_CTX_free(temp_ctx); - return _setException(PyExc_ValueError, NULL); + goto error; } if (!EVP_DigestFinalXOF(temp_ctx, (unsigned char*)PyBytes_AS_STRING(retval), - length)) { - Py_DECREF(retval); - EVP_MD_CTX_free(temp_ctx); - _setException(PyExc_ValueError, NULL); - return NULL; + length)) + { + goto error; } EVP_MD_CTX_free(temp_ctx); return retval; + +error: + Py_DECREF(retval); + EVP_MD_CTX_free(temp_ctx); + return _setException(PyExc_ValueError, NULL); } /*[clinic input] @@ -841,15 +847,10 @@ EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length) /* Get the raw (binary) digest value */ if (!locked_EVP_MD_CTX_copy(temp_ctx, self)) { - PyMem_Free(digest); - EVP_MD_CTX_free(temp_ctx); - return _setException(PyExc_ValueError, NULL); + goto error; } if (!EVP_DigestFinalXOF(temp_ctx, digest, length)) { - PyMem_Free(digest); - EVP_MD_CTX_free(temp_ctx); - _setException(PyExc_ValueError, NULL); - return NULL; + goto error; } EVP_MD_CTX_free(temp_ctx); @@ -857,6 +858,11 @@ EVPXOF_hexdigest_impl(EVPobject *self, Py_ssize_t length) retval = _Py_strhex((const char *)digest, length); PyMem_Free(digest); return retval; + +error: + PyMem_Free(digest); + EVP_MD_CTX_free(temp_ctx); + return _setException(PyExc_ValueError, NULL); } static PyMethodDef EVPXOF_methods[] = { @@ -957,7 +963,7 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj, int result = EVP_DigestInit_ex(self->ctx, digest, NULL); if (!result) { - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); Py_CLEAR(self); goto exit; } @@ -978,7 +984,7 @@ py_evp_fromname(PyObject *module, const char *digestname, PyObject *data_obj, } } - exit: +exit: if (data_obj != NULL) { PyBuffer_Release(&view); } @@ -1423,14 +1429,14 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, r = PyLong_AsUnsignedLong(r_obj); if (r == (unsigned long) -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, - "r is required and must be an unsigned int"); + "r is required and must be an unsigned int"); return NULL; } p = PyLong_AsUnsignedLong(p_obj); if (p == (unsigned long) -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, - "p is required and must be an unsigned int"); + "p is required and must be an unsigned int"); return NULL; } @@ -1439,22 +1445,22 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, future. The maxmem constant is private to OpenSSL. */ PyErr_Format(PyExc_ValueError, "maxmem must be positive and smaller than %d", - INT_MAX); + INT_MAX); return NULL; } if (dklen < 1 || dklen > INT_MAX) { PyErr_Format(PyExc_ValueError, - "dklen must be greater than 0 and smaller than %d", - INT_MAX); + "dklen must be greater than 0 and smaller than %d", + INT_MAX); return NULL; } /* let OpenSSL validate the rest */ retval = EVP_PBE_scrypt(NULL, 0, NULL, 0, n, r, p, maxmem, NULL, 0); if (!retval) { - _setException(PyExc_ValueError, "Invalid parameter combination for n, r, p, maxmem."); - return NULL; + return _setException(PyExc_ValueError, + "Invalid parameter combination for n, r, p, maxmem."); } key_obj = PyBytes_FromStringAndSize(NULL, dklen); @@ -1474,8 +1480,7 @@ _hashlib_scrypt_impl(PyObject *module, Py_buffer *password, Py_buffer *salt, if (!retval) { Py_CLEAR(key_obj); - _setException(PyExc_ValueError, NULL); - return NULL; + return _setException(PyExc_ValueError, NULL); } return key_obj; } @@ -1531,8 +1536,7 @@ _hashlib_hmac_singleshot_impl(PyObject *module, Py_buffer *key, PY_EVP_MD_free(evp); if (result == NULL) { - _setException(PyExc_ValueError, NULL); - return NULL; + return _setException(PyExc_ValueError, NULL); } return PyBytes_FromStringAndSize((const char*)md, md_len); } @@ -1581,6 +1585,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, ctx = HMAC_CTX_new(); if (ctx == NULL) { + PY_EVP_MD_free(digest); PyErr_NoMemory(); goto error; } @@ -1588,7 +1593,7 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj, 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); + (void)_setException(PyExc_ValueError, NULL); goto error; } @@ -1626,11 +1631,20 @@ locked_HMAC_CTX_copy(HMAC_CTX *new_ctx_p, HMACobject *self) return result; } +/* returning 0 means that an error occurred and an exception is set */ static unsigned int _hmac_digest_size(HMACobject *self) { - unsigned int digest_size = EVP_MD_size(HMAC_CTX_get_md(self->ctx)); + const EVP_MD *md = HMAC_CTX_get_md(self->ctx); + if (md == NULL) { + (void)_setException(PyExc_ValueError, NULL); + return 0; + } + unsigned int digest_size = EVP_MD_size(md); assert(digest_size <= EVP_MAX_MD_SIZE); + if (digest_size == 0) { + (void)_setException(PyExc_ValueError, NULL); + } return digest_size; } @@ -1658,7 +1672,7 @@ _hmac_update(HMACobject *self, PyObject *obj) PyBuffer_Release(&view); if (r == 0) { - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); return 0; } return 1; @@ -1711,7 +1725,11 @@ _hmac_dealloc(HMACobject *self) static PyObject * _hmac_repr(HMACobject *self) { - PyObject *digest_name = py_digest_name(HMAC_CTX_get_md(self->ctx)); + const EVP_MD *md = HMAC_CTX_get_md(self->ctx); + if (md == NULL) { + return _setException(PyExc_ValueError, NULL); + } + PyObject *digest_name = py_digest_name(md); if (digest_name == NULL) { return NULL; } @@ -1744,18 +1762,18 @@ _hmac_digest(HMACobject *self, unsigned char *buf, unsigned int len) { HMAC_CTX *temp_ctx = HMAC_CTX_new(); if (temp_ctx == NULL) { - PyErr_NoMemory(); + (void)PyErr_NoMemory(); return 0; } if (!locked_HMAC_CTX_copy(temp_ctx, self)) { HMAC_CTX_free(temp_ctx); - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); return 0; } int r = HMAC_Final(temp_ctx, buf, &len); HMAC_CTX_free(temp_ctx); if (r == 0) { - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); return 0; } return 1; @@ -1773,7 +1791,7 @@ _hashlib_HMAC_digest_impl(HMACobject *self) unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError, NULL); + return NULL; } int r = _hmac_digest(self, digest, digest_size); if (r == 0) { @@ -1798,7 +1816,7 @@ _hashlib_HMAC_hexdigest_impl(HMACobject *self) unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError, NULL); + return NULL; } int r = _hmac_digest(self, digest, digest_size); if (r == 0) { @@ -1812,7 +1830,7 @@ _hashlib_hmac_get_digest_size(HMACobject *self, void *closure) { unsigned int digest_size = _hmac_digest_size(self); if (digest_size == 0) { - return _setException(PyExc_ValueError, NULL); + return NULL; } return PyLong_FromLong(digest_size); } @@ -1830,7 +1848,11 @@ _hashlib_hmac_get_block_size(HMACobject *self, void *closure) static PyObject * _hashlib_hmac_get_name(HMACobject *self, void *closure) { - PyObject *digest_name = py_digest_name(HMAC_CTX_get_md(self->ctx)); + const EVP_MD *md = HMAC_CTX_get_md(self->ctx); + if (md == NULL) { + return _setException(PyExc_ValueError, NULL); + } + PyObject *digest_name = py_digest_name(md); if (digest_name == NULL) { return NULL; } @@ -1981,7 +2003,7 @@ _hashlib_get_fips_mode_impl(PyObject *module) // But 0 is also a valid result value. unsigned long errcode = ERR_peek_last_error(); if (errcode) { - _setException(PyExc_ValueError, NULL); + (void)_setException(PyExc_ValueError, NULL); return -1; } } _______________________________________________ Python-checkins mailing list -- python-checkins@python.org To unsubscribe send an email to python-checkins-le...@python.org https://mail.python.org/mailman3/lists/python-checkins.python.org/ Member address: arch...@mail-archive.com