https://github.com/python/cpython/commit/5d9a691b1c0cb01e88cad22df753e68e305070a3
commit: 5d9a691b1c0cb01e88cad22df753e68e305070a3
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: picnixz <[email protected]>
date: 2026-10-19T23:00:13Z
summary:

[3.14] gh-155833: GC-untrack MD5/SHA* objects before freeing the HACL* state 
(GH-155834) (#159790)

gh-155833: GC-untrack MD5/SHA* objects before freeing the HACL* state 
(GH-155834)
(cherry picked from commit 29fd3b8b0988d540e5b679667947523f6039da6c)

Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-08-15-12-08-33.gh-issue-155833.Pi2Yjp.rst
M Modules/md5module.c
M Modules/sha1module.c
M Modules/sha2module.c
M Modules/sha3module.c

diff --git 
a/Misc/NEWS.d/next/Library/2026-08-15-12-08-33.gh-issue-155833.Pi2Yjp.rst 
b/Misc/NEWS.d/next/Library/2026-08-15-12-08-33.gh-issue-155833.Pi2Yjp.rst
new file mode 100644
index 00000000000000..96bf5de44bd836
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-15-12-08-33.gh-issue-155833.Pi2Yjp.rst
@@ -0,0 +1,2 @@
+Ensure that MD5 and SHA* objects are properly GC-untracked before freeing
+their internal HACL* state. Patch by Bénédikt Tran.
diff --git a/Modules/md5module.c b/Modules/md5module.c
index f3855ec3f37faa..e920e5895ca750 100644
--- a/Modules/md5module.c
+++ b/Modules/md5module.c
@@ -70,6 +70,7 @@ newMD5object(MD5State * st)
         return NULL;
     }
     HASHLIB_INIT_MUTEX(md5);
+    md5->hash_state = NULL; // PyObject_GC_New() does not zero memory
 
     PyObject_GC_Track(md5);
     return md5;
@@ -86,13 +87,13 @@ MD5_traverse(PyObject *ptr, visitproc visit, void *arg)
 static void
 MD5_dealloc(PyObject *op)
 {
+    PyTypeObject *tp = Py_TYPE(op);
+    PyObject_GC_UnTrack(op);
     MD5object *ptr = _MD5object_CAST(op);
     if (ptr->hash_state != NULL) {
         Hacl_Hash_MD5_free(ptr->hash_state);
         ptr->hash_state = NULL;
     }
-    PyTypeObject *tp = Py_TYPE(op);
-    PyObject_GC_UnTrack(ptr);
     PyObject_GC_Del(ptr);
     Py_DECREF(tp);
 }
diff --git a/Modules/sha1module.c b/Modules/sha1module.c
index a746bf74f8d4c1..e00f697a19b728 100644
--- a/Modules/sha1module.c
+++ b/Modules/sha1module.c
@@ -71,6 +71,7 @@ newSHA1object(SHA1State *st)
         return NULL;
     }
     HASHLIB_INIT_MUTEX(sha);
+    sha->hash_state = NULL; // PyObject_GC_New() does not zero memory
 
     PyObject_GC_Track(sha);
     return sha;
@@ -88,13 +89,13 @@ SHA1_traverse(PyObject *ptr, visitproc visit, void *arg)
 static void
 SHA1_dealloc(PyObject *op)
 {
+    PyTypeObject *tp = Py_TYPE(op);
+    PyObject_GC_UnTrack(op);
     SHA1object *ptr = _SHA1object_CAST(op);
     if (ptr->hash_state != NULL) {
         Hacl_Hash_SHA1_free(ptr->hash_state);
         ptr->hash_state = NULL;
     }
-    PyTypeObject *tp = Py_TYPE(ptr);
-    PyObject_GC_UnTrack(ptr);
     PyObject_GC_Del(ptr);
     Py_DECREF(tp);
 }
diff --git a/Modules/sha2module.c b/Modules/sha2module.c
index 72931910c5d720..ccc83a010dca10 100644
--- a/Modules/sha2module.c
+++ b/Modules/sha2module.c
@@ -147,6 +147,7 @@ newSHA384object(sha2_state *state)
         return NULL;
     }
     HASHLIB_INIT_MUTEX(sha);
+    sha->state = NULL; // PyObject_GC_New() does not zero memory
 
     PyObject_GC_Track(sha);
     return sha;
@@ -160,6 +161,7 @@ newSHA512object(sha2_state *state)
         return NULL;
     }
     HASHLIB_INIT_MUTEX(sha);
+    sha->state = NULL; // PyObject_GC_New() does not zero memory
 
     PyObject_GC_Track(sha);
     return sha;
@@ -177,13 +179,13 @@ SHA2_traverse(PyObject *ptr, visitproc visit, void *arg)
 static void
 SHA256_dealloc(PyObject *op)
 {
+    PyTypeObject *tp = Py_TYPE(op);
+    PyObject_GC_UnTrack(op);
     SHA256object *ptr = _SHA256object_CAST(op);
     if (ptr->state != NULL) {
         Hacl_Hash_SHA2_free_256(ptr->state);
         ptr->state = NULL;
     }
-    PyTypeObject *tp = Py_TYPE(ptr);
-    PyObject_GC_UnTrack(ptr);
     PyObject_GC_Del(ptr);
     Py_DECREF(tp);
 }
@@ -191,13 +193,13 @@ SHA256_dealloc(PyObject *op)
 static void
 SHA512_dealloc(PyObject *op)
 {
+    PyTypeObject *tp = Py_TYPE(op);
+    PyObject_GC_UnTrack(op);
     SHA512object *ptr = _SHA512object_CAST(op);
     if (ptr->state != NULL) {
         Hacl_Hash_SHA2_free_512(ptr->state);
         ptr->state = NULL;
     }
-    PyTypeObject *tp = Py_TYPE(ptr);
-    PyObject_GC_UnTrack(ptr);
     PyObject_GC_Del(ptr);
     Py_DECREF(tp);
 }
diff --git a/Modules/sha3module.c b/Modules/sha3module.c
index 1c48a83c99db2c..8c6cef9fd34921 100644
--- a/Modules/sha3module.c
+++ b/Modules/sha3module.c
@@ -84,6 +84,7 @@ newSHA3object(PyTypeObject *type)
         return NULL;
     }
     HASHLIB_INIT_MUTEX(newobj);
+    newobj->hash_state = NULL; // PyObject_GC_New() does not zero memory
     newobj->digest_size = newobj->block_size = 0;
     PyObject_GC_Track(newobj);
     return newobj;
@@ -220,7 +221,7 @@ SHA3_dealloc(PyObject *self)
     PyTypeObject *tp = Py_TYPE(self);
     PyObject_GC_UnTrack(self);
     (void)SHA3_clear(self);
-    tp->tp_free(self);
+    PyObject_GC_Del(self);
     Py_DECREF(tp);
 }
 

_______________________________________________
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