Skip to content

Commit de4951c

Browse files
committed
gh-159811: Raise OpenSSL errors in _hashlib.HMAC after re-attaching the thread state
`hashlib_openssl_HMAC_update_once()` set an exception when the OpenSSL HMAC update function failed, but it is called inside a GIL-released region, with the object's mutex held, by `_hashlib.HMAC.update()` and `_hashlib.hmac_new()` when the data exceeds HASHLIB_GIL_MINSIZE bytes. Setting the exception with the thread state detached crashed the interpreter instead of raising an exception. Only report the failure in `hashlib_openssl_HMAC_update_once()` and set the exception in `_hmac_update()` once the thread state is re-attached and the mutex is released, as it was done before gh-134531. The OpenSSL error queue is per thread, so the exception type and message are unaffected.
1 parent 395d766 commit de4951c

2 files changed

Lines changed: 17 additions & 6 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:`hmac` when the OpenSSL routine used by
2+
:meth:`hmac.HMAC.update` or by :func:`hmac.new` fails on data larger
3+
than 2048 bytes. Patch by Bénédikt Tran.

‎Modules/_hashopenssl.c‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1976,14 +1976,18 @@ hashlib_HMAC_get_hashlib_digest_name(HMACobject *self)
19761976
#endif
19771977
}
19781978

1979+
/*
1980+
* Update the HMAC context 'ctx' with the content of 'v'.
1981+
*
1982+
* Return 0 on success and -1 if PY_HMAC_update() failed. No exception
1983+
* is set, so that this can be called without an attached thread state.
1984+
*/
19791985
static int
19801986
hashlib_openssl_HMAC_update_once(PY_HMAC_CTX_TYPE *ctx, const Py_buffer *v)
19811987
{
1982-
if (!PY_HMAC_update(ctx, (const unsigned char *)v->buf, (size_t)v->len)) {
1983-
notify_smart_ssl_error_occurred_in(Py_STRINGIFY(PY_HMAC_update));
1984-
return -1;
1985-
}
1986-
return 0;
1988+
return PY_HMAC_update(ctx, (const unsigned char *)v->buf, (size_t)v->len)
1989+
? 0
1990+
: -1;
19871991
}
19881992

19891993
/* Thin wrapper around PY_HMAC_CTX_free that allows to pass a NULL 'ctx'. */
@@ -2243,7 +2247,11 @@ _hmac_update(HMACobject *self, PyObject *obj)
22432247
r = hashlib_openssl_HMAC_update_once(self->ctx, &view)
22442248
);
22452249
PyBuffer_Release(&view);
2246-
return r;
2250+
if (r < 0) {
2251+
notify_smart_ssl_error_occurred_in(Py_STRINGIFY(PY_HMAC_update));
2252+
return -1;
2253+
}
2254+
return 0;
22472255
}
22482256

22492257
/*[clinic input]

0 commit comments

Comments
 (0)