From 562462415ab0f69323547da884d5b663364e14ca 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, 19 Oct 2026 16:43:09 -0700 Subject: [PATCH] gh-159811: Raise OpenSSL errors in `_hashlib.HASH` after re-attaching the thread state `_hashlib_HASH_hash()` set an exception when EVP_DigestUpdate() failed, but it is called inside a GIL-released region by `_hashlib.HASH.update()` and by the `_hashlib.HASH` constructor when the data exceeds HASHLIB_GIL_MINSIZE bytes. Setting the exception with the thread state detached crashed the interpreter instead of raising a ValueError. Only report the failure in `_hashlib_HASH_hash()` and set the exception in its callers once the thread state is re-attached. The OpenSSL error queue is per thread, so the exception message is unaffected. --- ...2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst | 3 +++ Modules/_hashopenssl.c | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst diff --git a/Misc/NEWS.d/next/Library/2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst b/Misc/NEWS.d/next/Library/2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst new file mode 100644 index 000000000000000..f63cd928a6a33cf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst @@ -0,0 +1,3 @@ +Fix a crash in :mod:`hashlib` when the OpenSSL routine used by +:meth:`hash.update() ` or by hash object constructors +fails on data larger than 2048 bytes. Patch by Bénédikt Tran. diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index d23767afeb96cfb..d20bdc605cf35b0 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -847,6 +847,12 @@ new_hash_object(PyTypeObject *type) return retval; } +/* + * Update the digest context of 'self' with 'len' bytes from 'vp'. + * + * Return 0 on success and -1 if EVP_DigestUpdate() failed. No exception + * is set, so that this can be called without an attached thread state. + */ static int _hashlib_HASH_hash(HASHobject *self, const void *vp, Py_ssize_t len) { @@ -858,7 +864,6 @@ _hashlib_HASH_hash(HASHobject *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)) { - notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate)); return -1; } len -= process; @@ -991,7 +996,11 @@ _hashlib_HASH_update_impl(HASHobject *self, PyObject *obj) result = _hashlib_HASH_hash(self, view.buf, view.len) ); PyBuffer_Release(&view); - return result < 0 ? NULL : Py_None; + if (result < 0) { + notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate)); + return NULL; + } + Py_RETURN_NONE; } static PyMethodDef HASH_methods[] = { @@ -1305,7 +1314,7 @@ _hashlib_HASH(_hashlibstate *state, const char *digestname, PyObject *data_obj, result = _hashlib_HASH_hash(self, view.buf, view.len) ); if (result == -1) { - assert(PyErr_Occurred()); + notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate)); Py_CLEAR(self); goto exit; }