https://github.com/python/cpython/commit/20d278623d1e63d3167ba49fbd8099bdece45c3f
commit: 20d278623d1e63d3167ba49fbd8099bdece45c3f
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2026-09-06T16:30:57+02:00
summary:

gh-155843: properly initialize HMAC objects to prevent crashes after allocation 
failures (#155845)

files:
A Misc/NEWS.d/next/Library/2026-08-15-13-54-22.gh-issue-155843.PD5Af3.rst
M Modules/hmacmodule.c

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 00000000000000..dd743a71369141
--- /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 0f9eca2f73bd0c..96a91ce9754bdc 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;
@@ -676,6 +668,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 initializes the memory to zero but the unknown kind is -1
+    self->kind = Py_hmac_kind_hash_unknown;
+    return self;
+}
+
 /*
  * Use the HMAC information 'info' to populate the corresponding fields.
  *
@@ -687,7 +697,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 +766,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 +802,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 +814,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 +857,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(cls);
     if (copy == NULL) {
         return NULL;
     }
@@ -868,7 +874,6 @@ _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls)
         return NULL;
     }
 
-    HASHLIB_INIT_MUTEX(copy);
     return (PyObject *)copy;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to