Skip to content

Commit 0294a0b

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 0294a0b

File tree

1 file changed

+58
-18
lines changed

1 file changed

+58
-18
lines changed

Modules/_hashopenssl.c

Lines changed: 58 additions & 18 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},
@@ -934,18 +950,25 @@ PyDoc_STRVAR(hashxoftype_doc,
934950
"digest_size -- number of bytes in this hashes output");
935951

936952
static PyType_Slot EVPXOFtype_slots[] = {
953+
{Py_tp_dealloc, EVP_dealloc},
954+
{Py_tp_traverse, EVP_traverse},
937955
{Py_tp_doc, (char *)hashxoftype_doc},
938956
{Py_tp_methods, EVPXOF_methods},
939957
{Py_tp_getset, EVPXOF_getseters},
940958
{0, 0},
941959
};
942960

943961
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
962+
.name = "_hashlib.HASHXOF",
963+
.basicsize = sizeof(EVPobject),
964+
.flags = (
965+
Py_TPFLAGS_DEFAULT
966+
| Py_TPFLAGS_BASETYPE
967+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
968+
| Py_TPFLAGS_IMMUTABLETYPE
969+
| Py_TPFLAGS_HAVE_GC
970+
),
971+
.slots = EVPXOFtype_slots
949972
};
950973

951974

@@ -1659,7 +1682,8 @@ _hashlib_hmac_new_impl(PyObject *module, Py_buffer *key, PyObject *msg_obj,
16591682
}
16601683

16611684
_hashlibstate *state = get_hashlib_state(module);
1662-
self = PyObject_New(HMACobject, state->HMACtype);
1685+
assert(state->HMACtype != NULL);
1686+
self = (HMACobject *)state->HMACtype->tp_alloc(state->HMACtype, 0);
16631687
if (self == NULL) {
16641688
goto error;
16651689
}
@@ -1764,7 +1788,8 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
17641788
return NULL;
17651789
}
17661790

1767-
retval = PyObject_New(HMACobject, Py_TYPE(self));
1791+
PyTypeObject *type = Py_TYPE(self);
1792+
retval = (HMACobject *)type->tp_alloc(type, 0);
17681793
if (retval == NULL) {
17691794
HMAC_CTX_free(ctx);
17701795
return NULL;
@@ -1776,17 +1801,26 @@ _hashlib_HMAC_copy_impl(HMACobject *self)
17761801
}
17771802

17781803
static void
1779-
_hmac_dealloc(HMACobject *self)
1804+
_hmac_dealloc(PyObject *op)
17801805
{
1781-
PyTypeObject *tp = Py_TYPE(self);
1806+
PyTypeObject *tp = Py_TYPE(op);
1807+
PyObject_GC_UnTrack(op);
1808+
HMACobject *self = HMACobject_CAST(op);
17821809
if (self->ctx != NULL) {
17831810
HMAC_CTX_free(self->ctx);
17841811
self->ctx = NULL;
17851812
}
1786-
PyObject_Free(self);
1813+
tp->tp_free(self);
17871814
Py_DECREF(tp);
17881815
}
17891816

1817+
static int
1818+
_hmac_traverse(PyObject *op, visitproc visit, void *arg)
1819+
{
1820+
Py_VISIT(Py_TYPE(op));
1821+
return 0;
1822+
}
1823+
17901824
static PyObject *
17911825
_hmac_repr(HMACobject *self)
17921826
{
@@ -1954,16 +1988,22 @@ digest_size -- number of bytes in digest() output\n");
19541988
static PyType_Slot HMACtype_slots[] = {
19551989
{Py_tp_doc, (char *)hmactype_doc},
19561990
{Py_tp_repr, (reprfunc)_hmac_repr},
1957-
{Py_tp_dealloc,(destructor)_hmac_dealloc},
1991+
{Py_tp_dealloc, _hmac_dealloc},
1992+
{Py_tp_traverse, _hmac_traverse},
19581993
{Py_tp_methods, HMAC_methods},
19591994
{Py_tp_getset, HMAC_getset},
19601995
{0, NULL}
19611996
};
19621997

19631998
PyType_Spec HMACtype_spec = {
1964-
"_hashlib.HMAC", /* name */
1965-
sizeof(HMACobject), /* basicsize */
1966-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE,
1999+
.name = "_hashlib.HMAC",
2000+
.basicsize = sizeof(HMACobject),
2001+
.flags = (
2002+
Py_TPFLAGS_DEFAULT
2003+
| Py_TPFLAGS_DISALLOW_INSTANTIATION
2004+
| Py_TPFLAGS_IMMUTABLETYPE
2005+
| Py_TPFLAGS_HAVE_GC
2006+
),
19672007
.slots = HMACtype_slots,
19682008
};
19692009

0 commit comments

Comments
 (0)