Skip to content

Commit 910bd27

Browse files
committed
[3.13] gh-116946: fully implement GC protocol for _hashlib objects (GH-138289)
(cherry picked from commit 6f1dd95) Co-authored-by: Bénédikt Tran <[email protected]>
1 parent aebf072 commit 910bd27

File tree

1 file changed

+68
-23
lines changed

1 file changed

+68
-23
lines changed

Modules/_hashopenssl.c

Lines changed: 68 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,8 @@ typedef struct {
282282
PyMutex mutex; /* OpenSSL context lock */
283283
} EVPobject;
284284

285+
#define EVPobject_CAST(op) ((EVPobject *)(op))
286+
285287
typedef struct {
286288
PyObject_HEAD
287289
HMAC_CTX *ctx; /* OpenSSL hmac context */
@@ -290,6 +292,8 @@ typedef struct {
290292
PyMutex mutex; /* HMAC context lock */
291293
} HMACobject;
292294

295+
#define HMACobject_CAST(op) ((HMACobject *)(op))
296+
293297
#include "clinic/_hashopenssl.c.h"
294298
/*[clinic input]
295299
module _hashlib
@@ -497,7 +501,9 @@ py_digest_by_digestmod(PyObject *module, PyObject *digestmod, enum Py_hash_type
497501
static EVPobject *
498502
newEVPobject(PyTypeObject *type)
499503
{
500-
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, type);
504+
assert(type != NULL);
505+
assert(type->tp_alloc != NULL);
506+
EVPobject *retval = (EVPobject *)type->tp_alloc(type, 0);
501507
if (retval == NULL) {
502508
return NULL;
503509
}
@@ -536,14 +542,23 @@ EVP_hash(EVPobject *self, const void *vp, Py_ssize_t len)
536542
/* Internal methods for a hash object */
537543

538544
static void
539-
EVP_dealloc(EVPobject *self)
545+
EVP_dealloc(PyObject *op)
540546
{
541-
PyTypeObject *tp = Py_TYPE(self);
547+
PyTypeObject *tp = Py_TYPE(op);
548+
PyObject_GC_UnTrack(op);
549+
EVPobject *self = EVPobject_CAST(op);
542550
EVP_MD_CTX_free(self->ctx);
543-
PyObject_Free(self);
551+
tp->tp_free(self);
544552
Py_DECREF(tp);
545553
}
546554

555+
static int
556+
EVP_traverse(PyObject *op, visitproc visit, void *arg)
557+
{
558+
Py_VISIT(Py_TYPE(op));
559+
return 0;
560+
}
561+
547562
static int
548563
locked_EVP_MD_CTX_copy(EVP_MD_CTX *new_ctx_p, EVPobject *self)
549564
{
@@ -781,6 +796,7 @@ PyDoc_STRVAR(hashtype_doc,
781796

782797
static PyType_Slot EVPtype_slots[] = {
783798
{Py_tp_dealloc, EVP_dealloc},
799+
{Py_tp_traverse, EVP_traverse},
784800
{Py_tp_repr, EVP_repr},
785801
{Py_tp_doc, (char *)hashtype_doc},
786802
{Py_tp_methods, EVP_methods},
@@ -789,11 +805,16 @@ static PyType_Slot EVPtype_slots[] = {
789805
};
790806

791807
static PyType_Spec EVPtype_spec = {
792-
"_hashlib.HASH", /*tp_name*/
793-
sizeof(EVPobject), /*tp_basicsize*/
794-
0, /*tp_itemsize*/
795-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
796-
EVPtype_slots
808+
.name = "_hashlib.HASH",
809+
.basicsize = sizeof(EVPobject),
810+
.flags = (
811+
Py_TPFLAGS_DEFAULT
812+
| Py_TPFLAGS_BASETYPE
813+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
814+
| Py_TPFLAGS_IMMUTABLETYPE
815+
| Py_TPFLAGS_HAVE_GC
816+
),
817+
.slots = EVPtype_slots
797818
};
798819

799820
#ifdef PY_OPENSSL_HAS_SHAKE
@@ -934,18 +955,25 @@ PyDoc_STRVAR(hashxoftype_doc,
934955
"digest_size -- number of bytes in this hashes output");
935956

936957
static PyType_Slot EVPXOFtype_slots[] = {
958+
{Py_tp_dealloc, EVP_dealloc},
959+
{Py_tp_traverse, EVP_traverse},
937960
{Py_tp_doc, (char *)hashxoftype_doc},
938961
{Py_tp_methods, EVPXOF_methods},
939962
{Py_tp_getset, EVPXOF_getseters},
940963
{0, 0},
941964
};
942965

943966
static PyType_Spec EVPXOFtype_spec = {
944-
"_hashlib.HASHXOF", /*tp_name*/
945-
sizeof(EVPobject), /*tp_basicsize*/
946-
0, /*tp_itemsize*/
947-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
948-
EVPXOFtype_slots
967+
.name = "_hashlib.HASHXOF",
968+
.basicsize = sizeof(EVPobject),
969+
.flags = (
970+
Py_TPFLAGS_DEFAULT
971+
| Py_TPFLAGS_BASETYPE
972+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
973+
| Py_TPFLAGS_IMMUTABLETYPE
974+
| Py_TPFLAGS_HAVE_GC
975+
),
976+
.slots = EVPXOFtype_slots
949977
};
950978

951979

@@ -1659,7 +1687,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
16591687
}
16601688

16611689
_hashlibstate *state = get_hashlib_state(module);
1662-
self = PyObject_New(HMACobject, state->HMACtype);
1690+
assert(state->HMACtype != NULL);
1691+
self = (HMACobject *)state->HMACtype->tp_alloc(state->HMACtype, 0);
16631692
if (self == NULL) {
16641693
goto error;
16651694
}
@@ -1764,7 +1793,8 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
17641793
return NULL;
17651794
}
17661795

1767-
retval = PyObject_New(HMACobject, Py_TYPE(self));
1796+
PyTypeObject *type = Py_TYPE(self);
1797+
retval = (HMACobject *)type->tp_alloc(type, 0);
17681798
if (retval == NULL) {
17691799
HMAC_CTX_free(ctx);
17701800
return NULL;
@@ -1776,17 +1806,26 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
17761806
}
17771807

17781808
static void
1779-
_hmac_dealloc(HMACobject *self)
1809+
_hmac_dealloc(PyObject *op)
17801810
{
1781-
PyTypeObject *tp = Py_TYPE(self);
1811+
PyTypeObject *tp = Py_TYPE(op);
1812+
PyObject_GC_UnTrack(op);
1813+
HMACobject *self = HMACobject_CAST(op);
17821814
if (self->ctx != NULL) {
17831815
HMAC_CTX_free(self->ctx);
17841816
self->ctx = NULL;
17851817
}
1786-
PyObject_Free(self);
1818+
tp->tp_free(self);
17871819
Py_DECREF(tp);
17881820
}
17891821

1822+
static int
1823+
_hmac_traverse(PyObject *op, visitproc visit, void *arg)
1824+
{
1825+
Py_VISIT(Py_TYPE(op));
1826+
return 0;
1827+
}
1828+
17901829
static PyObject *
17911830
_hmac_repr(HMACobject *self)
17921831
{
@@ -1954,16 +1993,22 @@ digest_size -- number of bytes in digest() output\n");
19541993
static PyType_Slot HMACtype_slots[] = {
19551994
{Py_tp_doc, (char *)hmactype_doc},
19561995
{Py_tp_repr, (reprfunc)_hmac_repr},
1957-
{Py_tp_dealloc,(destructor)_hmac_dealloc},
1996+
{Py_tp_dealloc, _hmac_dealloc},
1997+
{Py_tp_traverse, _hmac_traverse},
19581998
{Py_tp_methods, HMAC_methods},
19591999
{Py_tp_getset, HMAC_getset},
19602000
{0, NULL}
19612001
};
19622002

19632003
PyType_Spec HMACtype_spec = {
1964-
"_hashlib.HMAC", /* name */
1965-
sizeof(HMACobject), /* basicsize */
1966-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
2004+
.name = "_hashlib.HMAC",
2005+
.basicsize = sizeof(HMACobject),
2006+
.flags = (
2007+
Py_TPFLAGS_DEFAULT
2008+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
2009+
| Py_TPFLAGS_IMMUTABLETYPE
2010+
| Py_TPFLAGS_HAVE_GC
2011+
),
19672012
.slots = HMACtype_slots,
19682013
};
19692014

0 commit comments

Comments
 (0)