From 1d3aedeaae2d89b84f6f79179c2f9b831263d156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sat, 15 Aug 2026 13:55:29 +0200 Subject: [PATCH 1/5] gh-155843: properly initialize HMAC objects to prevent crashes after allocation failures --- ...-08-15-13-54-22.gh-issue-155843.PD5Af3.rst | 2 ++ Modules/hmacmodule.c | 33 +++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-08-15-13-54-22.gh-issue-155843.PD5Af3.rst diff --git a/Misc/NEWS.d/next/Library/2026-08-15-13-54-22.gh-issue-155843.PD5Af3.rst b/Misc/NEWS.d/next/Library/2026-08-15-13-54-22.gh-issue-155843.PD5Af3.rst new file mode 100644 index 000000000000000..dd743a71369141e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-15-13-54-22.gh-issue-155843.PD5Af3.rst @@ -0,0 +1,2 @@ +:mod:`hmac`: ensure that HMAC objects are properly initialized to prevent +rare crashes on allocation failures. Patch by Bénédikt Tran. diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index 0f9eca2f73bd0c5..efd47b25a46e0e1 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -676,6 +676,24 @@ has_uint32_t_buffer_length(const Py_buffer *buffer) // --- HMAC object ------------------------------------------------------------ +/* + * Create a zero-initialized untracked HMAC object. + * + * Return NULL on failure with an exception set. + */ +static HMACObject * +hmac_new_object(PyTypeObject *tp) +{ + HMACObject *self = (HMACObject *)tp->tp_alloc(tp, 0); + if (self == NULL) { + return NULL; + } + HASHLIB_INIT_MUTEX(self); + // tp_alloc initialize the memory to zero but the unknown kind must be -1 + self->kind = Py_hmac_kind_hash_unknown; + return self; +} + /* * Use the HMAC information 'info' to populate the corresponding fields. * @@ -687,7 +705,7 @@ hmac_set_hinfo(hmacmodule_state *state, HMACObject *self, const py_hmac_hinfo *info) { assert(info->display_name != NULL); - self->name = Py_NewRef(info->display_name); + Py_XSETREF(self->name, Py_NewRef(info->display_name)); assert_is_static_hmac_hash_kind(info->kind); self->kind = narrow_hmac_hash_kind(state, info->kind); assert(info->block_size <= Py_hmac_hash_max_block_size); @@ -756,16 +774,15 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj, return NULL; } - HMACObject *self = PyObject_New(HMACObject, state->hmac_type); + HMACObject *self = hmac_new_object(state->hmac_type); if (self == NULL) { return NULL; } - HASHLIB_INIT_MUTEX(self); hmac_set_hinfo(state, self, info); int rc; // Create the HACL* internal state with the given key. Py_buffer key; - GET_BUFFER_VIEW_OR_ERROR(keyobj, &key, goto error_on_key); + GET_BUFFER_VIEW_OR_ERROR(keyobj, &key, goto error); rc = hmac_new_initial_state(self, key.buf, key.len); PyBuffer_Release(&key); if (rc < 0) { @@ -793,8 +810,6 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj, assert(rc == 0); return (PyObject *)self; -error_on_key: - self->state = NULL; error: Py_DECREF(self); return NULL; @@ -807,7 +822,7 @@ static void hmac_copy_hinfo(HMACObject *out, const HMACObject *src) { assert(src->name != NULL); - out->name = Py_NewRef(src->name); + Py_XSETREF(out->name, Py_NewRef(src->name)); assert(src->kind != Py_hmac_kind_hash_unknown); out->kind = src->kind; assert(src->block_size <= Py_hmac_hash_max_block_size); @@ -850,8 +865,7 @@ static PyObject * _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls) /*[clinic end generated code: output=a955bfa55b65b215 input=17b2c0ad0b147e36]*/ { - hmacmodule_state *state = get_hmacmodule_state_by_cls(cls); - HMACObject *copy = PyObject_New(HMACObject, state->hmac_type); + HMACObject *copy = hmac_new_object(Py_TYPE(self)); if (copy == NULL) { return NULL; } @@ -868,7 +882,6 @@ _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls) return NULL; } - HASHLIB_INIT_MUTEX(copy); return (PyObject *)copy; } From b8bd6a53526ed749e9e100b779056b9944eeb89d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 16 Aug 2026 09:39:04 +0200 Subject: [PATCH 2/5] Update Modules/hmacmodule.c --- Modules/hmacmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index efd47b25a46e0e1..f65ae815b6fa259 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -865,7 +865,7 @@ static PyObject * _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls) /*[clinic end generated code: output=a955bfa55b65b215 input=17b2c0ad0b147e36]*/ { - HMACObject *copy = hmac_new_object(Py_TYPE(self)); + HMACObject *copy = hmac_new_object(cls); if (copy == NULL) { return NULL; } From 3e389b3887ee87ca325cca8ed28c632709a232a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:26:15 +0200 Subject: [PATCH 3/5] fix warnings --- Modules/hmacmodule.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index f65ae815b6fa259..dcb71cc11675b82 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -271,14 +271,6 @@ get_hmacmodule_state(PyObject *module) return (hmacmodule_state *)state; } -static inline hmacmodule_state * -get_hmacmodule_state_by_cls(PyTypeObject *cls) -{ - void *state = PyType_GetModuleState(cls); - assert(state != NULL); - return (hmacmodule_state *)state; -} - // --- HMAC Object ------------------------------------------------------------ typedef Hacl_Streaming_HMAC_agile_state HACL_HMAC_state; From 9c169701d3b8bd3f48384cbcabed2cb9c6fe160d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:27:14 +0200 Subject: [PATCH 4/5] Update Modules/hmacmodule.c --- Modules/hmacmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index dcb71cc11675b82..f8f9ad32b401f4f 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -681,7 +681,7 @@ hmac_new_object(PyTypeObject *tp) return NULL; } HASHLIB_INIT_MUTEX(self); - // tp_alloc initialize the memory to zero but the unknown kind must be -1 + // tp_alloc initialize the memory to zero but the unknown kind is -1 self->kind = Py_hmac_kind_hash_unknown; return self; } From 4255203a7b4a15a7cef5072777dae1e29c9171e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A9n=C3=A9dikt=20Tran?= <10796600+picnixz@users.noreply.github.com> Date: Sun, 16 Aug 2026 10:27:52 +0200 Subject: [PATCH 5/5] Update Modules/hmacmodule.c --- Modules/hmacmodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/hmacmodule.c b/Modules/hmacmodule.c index f8f9ad32b401f4f..96a91ce9754bdc0 100644 --- a/Modules/hmacmodule.c +++ b/Modules/hmacmodule.c @@ -681,7 +681,7 @@ hmac_new_object(PyTypeObject *tp) return NULL; } HASHLIB_INIT_MUTEX(self); - // tp_alloc initialize the memory to zero but the unknown kind is -1 + // tp_alloc initializes the memory to zero but the unknown kind is -1 self->kind = Py_hmac_kind_hash_unknown; return self; }