Skip to content

Commit 5624624

Browse files
committed
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.
1 parent 395d766 commit 5624624

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)