https://github.com/python/cpython/commit/21b593219ad5cf444553afaebe12ff9137d4d55e
commit: 21b593219ad5cf444553afaebe12ff9137d4d55e
branch: 3.13
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2025-09-01T12:23:28+02:00
summary:
[3.13] gh-116946: fully implement GC protocol for `_hashlib` objects
(GH-138289) (#138326)
(cherry picked from commit 6f1dd9551a69c8c76d066a04e94db6dbc6c7597c)
files:
M Modules/_hashopenssl.c
diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c
index 5e4783395f4f48..ede9ca683adf2f 100644
--- a/Modules/_hashopenssl.c
+++ b/Modules/_hashopenssl.c
@@ -282,6 +282,8 @@ typedef struct {
PyMutex mutex; /* OpenSSL context lock */
} EVPobject;
+#define EVPobject_CAST(op) ((EVPobject *)(op))
+
typedef struct {
PyObject_HEAD
HMAC_CTX *ctx; /* OpenSSL hmac context */
@@ -290,6 +292,8 @@ typedef struct {
PyMutex mutex; /* HMAC context lock */
} HMACobject;
+#define HMACobject_CAST(op) ((HMACobject *)(op))
+
#include "clinic/_hashopenssl.c.h"
/*[clinic input]
module _hashlib
@@ -497,7 +501,9 @@ py_digest_by_digestmod(PyObject *module, PyObject
*digestmod, enum Py_hash_type
static EVPobject *
newEVPobject(PyTypeObject *type)
{
- EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, type);
+ assert(type != NULL);
+ assert(type->tp_alloc != NULL);
+ EVPobject *retval = (EVPobject *)type->tp_alloc(type, 0);
if (retval == NULL) {
return NULL;
}
@@ -536,14 +542,23 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
/* Internal methods for a hash object */
static void
-EVP_dealloc(EVPobject *self)
+EVP_dealloc(PyObject *op)
{
- PyTypeObject *tp = Py_TYPE(self);
+ PyTypeObject *tp = Py_TYPE(op);
+ PyObject_GC_UnTrack(op);
+ EVPobject *self = EVPobject_CAST(op);
EVP_MD_CTX_free(self->ctx);
- PyObject_Free(self);
+ tp->tp_free(self);
Py_DECREF(tp);
}
+static int
+EVP_traverse(PyObject *op, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(op));
+ return 0;
+}
+
static int
locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
{
@@ -781,6 +796,7 @@ PyDoc_STRVAR(hashtype_doc,
static PyType_Slot EVPtype_slots[] = {
{Py_tp_dealloc, EVP_dealloc},
+ {Py_tp_traverse, EVP_traverse},
{Py_tp_repr, EVP_repr},
{Py_tp_doc, (char *)hashtype_doc},
{Py_tp_methods, EVP_methods},
@@ -789,11 +805,16 @@ static PyType_Slot EVPtype_slots[] = {
};
static PyType_Spec EVPtype_spec = {
- "_hashlib.HASH", /*tp_name*/
- sizeof(EVPobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
- EVPtype_slots
+ .name = "_hashlib.HASH",
+ .basicsize = sizeof(EVPobject),
+ .flags = (
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
+ | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC
+ ),
+ .slots = EVPtype_slots
};
#ifdef PY_OPENSSL_HAS_SHAKE
@@ -934,6 +955,8 @@ PyDoc_STRVAR(hashxoftype_doc,
"digest_size -- number of bytes in this hashes output");
static PyType_Slot EVPXOFtype_slots[] = {
+ {Py_tp_dealloc, EVP_dealloc},
+ {Py_tp_traverse, EVP_traverse},
{Py_tp_doc, (char *)hashxoftype_doc},
{Py_tp_methods, EVPXOF_methods},
{Py_tp_getset, EVPXOF_getseters},
@@ -941,11 +964,16 @@ static PyType_Slot EVPXOFtype_slots[] = {
};
static PyType_Spec EVPXOFtype_spec = {
- "_hashlib.HASHXOF", /*tp_name*/
- sizeof(EVPobject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
- EVPXOFtype_slots
+ .name = "_hashlib.HASHXOF",
+ .basicsize = sizeof(EVPobject),
+ .flags = (
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_BASETYPE
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
+ | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC
+ ),
+ .slots = EVPXOFtype_slots
};
@@ -1659,7 +1687,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key,
PyObject *msg_obj,
}
_hashlibstate *state = get_hashlib_state(module);
- self = PyObject_New(HMACobject, state->HMACtype);
+ assert(state->HMACtype != NULL);
+ self = (HMACobject *)state->HMACtype->tp_alloc(state->HMACtype, 0);
if (self == NULL) {
goto error;
}
@@ -1764,7 +1793,8 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
return NULL;
}
- retval = PyObject_New(HMACobject, Py_TYPE(self));
+ PyTypeObject *type = Py_TYPE(self);
+ retval = (HMACobject *)type->tp_alloc(type, 0);
if (retval == NULL) {
HMAC_CTX_free(ctx);
return NULL;
@@ -1776,17 +1806,26 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
}
static void
-_hmac_dealloc(HMACobject *self)
+_hmac_dealloc(PyObject *op)
{
- PyTypeObject *tp = Py_TYPE(self);
+ PyTypeObject *tp = Py_TYPE(op);
+ PyObject_GC_UnTrack(op);
+ HMACobject *self = HMACobject_CAST(op);
if (self->ctx != NULL) {
HMAC_CTX_free(self->ctx);
self->ctx = NULL;
}
- PyObject_Free(self);
+ tp->tp_free(self);
Py_DECREF(tp);
}
+static int
+_hmac_traverse(PyObject *op, visitproc visit, void *arg)
+{
+ Py_VISIT(Py_TYPE(op));
+ return 0;
+}
+
static PyObject *
_hmac_repr(HMACobject *self)
{
@@ -1954,16 +1993,22 @@ digest_size -- number of bytes in digest() output\n");
static PyType_Slot HMACtype_slots[] = {
{Py_tp_doc, (char *)hmactype_doc},
{Py_tp_repr, (reprfunc)_hmac_repr},
- {Py_tp_dealloc,(destructor)_hmac_dealloc},
+ {Py_tp_dealloc, _hmac_dealloc},
+ {Py_tp_traverse, _hmac_traverse},
{Py_tp_methods, HMAC_methods},
{Py_tp_getset, HMAC_getset},
{0, NULL}
};
PyType_Spec HMACtype_spec = {
- "_hashlib.HMAC", /* name */
- sizeof(HMACobject), /* basicsize */
- .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION |
Py_TPFLAGS_IMMUTABLETYPE,
+ .name = "_hashlib.HMAC",
+ .basicsize = sizeof(HMACobject),
+ .flags = (
+ Py_TPFLAGS_DEFAULT
+ | Py_TPFLAGS_DISALLOW_INSTANTIATION
+ | Py_TPFLAGS_IMMUTABLETYPE
+ | Py_TPFLAGS_HAVE_GC
+ ),
.slots = HMACtype_slots,
};
_______________________________________________
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]