https://github.com/python/cpython/commit/9770db813fe818267e017cac9eb1328b2e2a7734
commit: 9770db813fe818267e017cac9eb1328b2e2a7734
branch: 3.14
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2026-10-19T11:46:27-07:00
summary:
[3.14] gh-155843: properly initialize HMAC objects to prevent crashes after
allocation failures (GH-155845) (#157037)
(cherry picked from commit 20d278623d1e63d3167ba49fbd8099bdece45c3f)
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 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 d3f86065125e1d5..6e1d048da820002 100644
--- a/Modules/hmacmodule.c
+++ b/Modules/hmacmodule.c
@@ -370,14 +370,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;
@@ -734,6 +726,30 @@ 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)
+{
+ // Using tp_alloc on GC objects automatically tracks them,
+ // but we need to first set the fields appropriately.
+ HMACObject *self = PyObject_GC_New(HMACObject, tp);
+ if (self == NULL) {
+ return NULL;
+ }
+ HASHLIB_INIT_MUTEX(self);
+ // PyObject_GC_New() does not zero-initialize
+ self->name = NULL;
+ self->kind = Py_hmac_kind_hash_unknown;
+ self->block_size = self->digest_size = 0;
+ self->api = (py_hmac_hacl_api){.compute = NULL, .compute_py = NULL};
+ self->state = NULL;
+ return self;
+}
+
/*
* Use the HMAC information 'info' to populate the corresponding fields.
*
@@ -745,7 +761,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);
@@ -853,16 +869,15 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj,
PyObject *msgobj,
return NULL;
}
- HMACObject *self = PyObject_GC_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) {
@@ -886,8 +901,6 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject
*msgobj,
PyObject_GC_Track(self);
return (PyObject *)self;
-error_on_key:
- self->state = NULL;
error:
Py_DECREF(self);
return NULL;
@@ -900,7 +913,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);
@@ -943,8 +956,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_GC_New(HMACObject, state->hmac_type);
+ HMACObject *copy = hmac_new_object(cls);
if (copy == NULL) {
return NULL;
}
@@ -961,7 +973,6 @@ _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls)
return NULL;
}
- HASHLIB_INIT_MUTEX(copy);
PyObject_GC_Track(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]