gh-135561 made _hacl_convert_errno() attach a thread state with PyGILState_Ensure() before setting an exception, because it may be called while the GIL is released. Since gh-135239, _hacl_hmac_state_update_once() calls _hacl_convert_errno() from inside HASHLIB_EXTERNAL_INSTRUCTIONS_UNLOCKED (in _hmac.new()) and HASHLIB_EXTERNAL_INSTRUCTIONS_LOCKED (in _hmac.HMAC.update()).
The following issues arise on DEBUG builds:
If a chunk fails in the chunking loop of _hacl_hmac_state_update(), the loop then runs assert(PyErr_Occurred()). By that point, _hacl_convert_errno() has already called PyGILState_Release(), so PyErr_Occurred() runs without an attached thread state. The loop only runs for buffers larger than UINT32_MAX bytes.
In _hmac.HMAC.update(), PyGILState_Ensure() runs while self->mutex is held, so a thread state is attached while the object's lock is held.
In practice, you need a HACL* update() failure such as MaximumLengthExceeded, and release builds ignore the HACL* exit code of update() anyway. However, since I wrote the module with DEBUG builds in mind just in case, I still want to cover that case.
Activity
pythongh-159786: Convert HACL* update() errors in `_hmac` after relea…
pythongh-159786: Convert HACL* update() errors in `_hmac` after relea…
pythongh-159786: Convert HACL* update() errors in `_hmac` after relea…
gh-159786: Convert HACL* update() errors in `_hmac` after releasing t…
[3.15] gh-159786: Convert HACL* update() errors in `_hmac` after rele…