Skip to content

Commit 9770db8

Browse files
authored
[3.14] gh-155843: properly initialize HMAC objects to prevent crashes after allocation failures (GH-155845) (#157037)
(cherry picked from commit 20d2786)
1 parent 08671e7 commit 9770db8

2 files changed

Lines changed: 31 additions & 18 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:mod:`hmac`: ensure that HMAC objects are properly initialized to prevent
2+
rare crashes on allocation failures. Patch by Bénédikt Tran.

‎Modules/hmacmodule.c‎

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,6 @@ get_hmacmodule_state(PyObject *module)
370370
return (hmacmodule_state *)state;
371371
}
372372

373-
static inline hmacmodule_state *
374-
get_hmacmodule_state_by_cls(PyTypeObject *cls)
375-
{
376-
void *state = PyType_GetModuleState(cls);
377-
assert(state != NULL);
378-
return (hmacmodule_state *)state;
379-
}
380-
381373
// --- HMAC Object ------------------------------------------------------------
382374

383375
typedef Hacl_Streaming_HMAC_agile_state HACL_HMAC_state;
@@ -734,6 +726,30 @@ has_uint32_t_buffer_length(const Py_buffer *buffer)
734726

735727
// --- HMAC object ------------------------------------------------------------
736728

729+
/*
730+
* Create a zero-initialized untracked HMAC object.
731+
*
732+
* Return NULL on failure with an exception set.
733+
*/
734+
static HMACObject *
735+
hmac_new_object(PyTypeObject *tp)
736+
{
737+
// Using tp_alloc on GC objects automatically tracks them,
738+
// but we need to first set the fields appropriately.
739+
HMACObject *self = PyObject_GC_New(HMACObject, tp);
740+
if (self == NULL) {
741+
return NULL;
742+
}
743+
HASHLIB_INIT_MUTEX(self);
744+
// PyObject_GC_New() does not zero-initialize
745+
self->name = NULL;
746+
self->kind = Py_hmac_kind_hash_unknown;
747+
self->block_size = self->digest_size = 0;
748+
self->api = (py_hmac_hacl_api){.compute = NULL, .compute_py = NULL};
749+
self->state = NULL;
750+
return self;
751+
}
752+
737753
/*
738754
* Use the HMAC information 'info' to populate the corresponding fields.
739755
*
@@ -745,7 +761,7 @@ hmac_set_hinfo(hmacmodule_state *state,
745761
HMACObject *self, const py_hmac_hinfo *info)
746762
{
747763
assert(info->display_name != NULL);
748-
self->name = Py_NewRef(info->display_name);
764+
Py_XSETREF(self->name, Py_NewRef(info->display_name));
749765
assert_is_static_hmac_hash_kind(info->kind);
750766
self->kind = narrow_hmac_hash_kind(state, info->kind);
751767
assert(info->block_size <= Py_hmac_hash_max_block_size);
@@ -853,16 +869,15 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj,
853869
return NULL;
854870
}
855871

856-
HMACObject *self = PyObject_GC_New(HMACObject, state->hmac_type);
872+
HMACObject *self = hmac_new_object(state->hmac_type);
857873
if (self == NULL) {
858874
return NULL;
859875
}
860-
HASHLIB_INIT_MUTEX(self);
861876
hmac_set_hinfo(state, self, info);
862877
int rc;
863878
// Create the HACL* internal state with the given key.
864879
Py_buffer key;
865-
GET_BUFFER_VIEW_OR_ERROR(keyobj, &key, goto error_on_key);
880+
GET_BUFFER_VIEW_OR_ERROR(keyobj, &key, goto error);
866881
rc = hmac_new_initial_state(self, key.buf, key.len);
867882
PyBuffer_Release(&key);
868883
if (rc < 0) {
@@ -886,8 +901,6 @@ _hmac_new_impl(PyObject *module, PyObject *keyobj, PyObject *msgobj,
886901
PyObject_GC_Track(self);
887902
return (PyObject *)self;
888903

889-
error_on_key:
890-
self->state = NULL;
891904
error:
892905
Py_DECREF(self);
893906
return NULL;
@@ -900,7 +913,7 @@ static void
900913
hmac_copy_hinfo(HMACObject *out, const HMACObject *src)
901914
{
902915
assert(src->name != NULL);
903-
out->name = Py_NewRef(src->name);
916+
Py_XSETREF(out->name, Py_NewRef(src->name));
904917
assert(src->kind != Py_hmac_kind_hash_unknown);
905918
out->kind = src->kind;
906919
assert(src->block_size <= Py_hmac_hash_max_block_size);
@@ -943,8 +956,7 @@ static PyObject *
943956
_hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls)
944957
/*[clinic end generated code: output=a955bfa55b65b215 input=17b2c0ad0b147e36]*/
945958
{
946-
hmacmodule_state *state = get_hmacmodule_state_by_cls(cls);
947-
HMACObject *copy = PyObject_GC_New(HMACObject, state->hmac_type);
959+
HMACObject *copy = hmac_new_object(cls);
948960
if (copy == NULL) {
949961
return NULL;
950962
}
@@ -961,7 +973,6 @@ _hmac_HMAC_copy_impl(HMACObject *self, PyTypeObject *cls)
961973
return NULL;
962974
}
963975

964-
HASHLIB_INIT_MUTEX(copy);
965976
PyObject_GC_Track(copy);
966977
return (PyObject *)copy;
967978
}

0 commit comments

Comments
 (0)