Skip to content

Commit 6fa2d64

Browse files
authored
gh-159811: Raise OpenSSL errors in _hashlib.HASH after re-attaching the thread state (#159817)
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.
1 parent b4b81e1 commit 6fa2d64

2 files changed

Lines changed: 15 additions & 3 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a crash in :mod:`hashlib` when the OpenSSL routine used by
2+
:meth:`hash.update() <hashlib.hash.update>` or by hash object constructors
3+
fails on data larger than 2048 bytes. Patch by Bénédikt Tran.

‎Modules/_hashopenssl.c‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,12 @@ new_hash_object(PyTypeObject *type)
847847
return retval;
848848
}
849849

850+
/*
851+
* Update the digest context of 'self' with 'len' bytes from 'vp'.
852+
*
853+
* Return 0 on success and -1 if EVP_DigestUpdate() failed. No exception
854+
* is set, so that this can be called without an attached thread state.
855+
*/
850856
static int
851857
_hashlib_HASH_hash(HASHobject *self, const void *vp, Py_ssize_t len)
852858
{
@@ -858,7 +864,6 @@ _hashlib_HASH_hash(HASHobject *self, const void *vp, Py_ssize_t len)
858864
else
859865
process = Py_SAFE_DOWNCAST(len, Py_ssize_t, unsigned int);
860866
if (!EVP_DigestUpdate(self->ctx, (const void*)cp, process)) {
861-
notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate));
862867
return -1;
863868
}
864869
len -= process;
@@ -991,7 +996,11 @@ _hashlib_HASH_update_impl(HASHobject *self, PyObject *obj)
991996
result = _hashlib_HASH_hash(self, view.buf, view.len)
992997
);
993998
PyBuffer_Release(&view);
994-
return result < 0 ? NULL : Py_None;
999+
if (result < 0) {
1000+
notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate));
1001+
return NULL;
1002+
}
1003+
Py_RETURN_NONE;
9951004
}
9961005

9971006
static PyMethodDef HASH_methods[] = {
@@ -1305,7 +1314,7 @@ _hashlib_HASH(_hashlibstate *state, const char *digestname, PyObject *data_obj,
13051314
result = _hashlib_HASH_hash(self, view.buf, view.len)
13061315
);
13071316
if (result == -1) {
1308-
assert(PyErr_Occurred());
1317+
notify_ssl_error_occurred_in(Py_STRINGIFY(EVP_DigestUpdate));
13091318
Py_CLEAR(self);
13101319
goto exit;
13111320
}

0 commit comments

Comments
 (0)