From 622a80e2bf32886b85d55ca67886b0755e4c74aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Tue, 20 Oct 2026 11:03:19 -0700 Subject: [PATCH] [3.14] gh-159811: Raise OpenSSL errors in `_hashlib.HASH` after re-attaching the thread state (GH-159817) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `EVP_DigestUpdate()` failed, `_hashlib_HASH_hash()` raised a Python exception, however, `_hashlib.HASH.update()` and the `_hashlib.HASH` constructor release the GIL before calling it when the data is larger than `HASHLIB_GIL_MINSIZE` bytes. `_hashlib_HASH_hash()` now only returns an error status and its callers raise the exception once they have re-attached the thread state. (cherry picked from commit 6fa2d645ea57120d1cbf38b45fc8ee2b5019090b) Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../2026-10-19-23-25-29.gh-issue-159811.cMB4DO.rst | 3 +++ Modules/_hashopenssl.c | 13 ++++++++++--- 2 files changed, 13 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 0191a958d41daa5..f3b2f10ffb2e851 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -516,6 +516,12 @@ newEVPobject(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 EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len) { @@ -527,7 +533,6 @@ 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)) { - notify_ssl_error_occurred(); return -1; } len -= process; @@ -694,8 +699,10 @@ EVP_update_impl(EVPobject *self, PyObject *obj) PyBuffer_Release(&view); - if (result == -1) + if (result == -1) { + notify_ssl_error_occurred(); return NULL; + } Py_RETURN_NONE; } @@ -1000,7 +1007,7 @@ _hashlib_HASH(PyObject *module, const char *digestname, PyObject *data_obj, result = EVP_hash(self, view.buf, view.len); } if (result == -1) { - assert(PyErr_Occurred()); + notify_ssl_error_occurred(); Py_CLEAR(self); goto exit; }