Skip to content

Commit bce70a2

Browse files
committed
bpo-38142: Updated _hashopenssl.c to be PEP 384 compliant
Signed-off-by: Christian Heimes <[email protected]>
1 parent 15ccc4f commit bce70a2

File tree

2 files changed

+71
-52
lines changed

2 files changed

+71
-52
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The _hashlib OpenSSL wrapper extension module is now PEP-384 compliant.

Modules/_hashopenssl.c

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@
3434

3535
#define MUNCH_SIZE INT_MAX
3636

37+
<<<<<<< HEAD
3738
#ifdef NID_sha3_224
39+
=======
40+
<<<<<<< HEAD
41+
#if defined(NID_sha3_224) && defined(EVP_MD_FLAG_XOF)
42+
>>>>>>> bpo-38142: Updated _hashopenssl.c to be PEP 384 compliant
3843
#define PY_OPENSSL_HAS_SHA3 1
3944
#endif
4045

@@ -45,6 +50,17 @@
4550
#ifdef NID_blake2b512
4651
#define PY_OPENSSL_HAS_BLAKE2 1
4752
#endif
53+
=======
54+
static PyModuleDef _hashlibmodule;
55+
56+
typedef struct {
57+
PyTypeObject *EVPtype;
58+
} _hashlibstate;
59+
60+
#define _hashlibstate(o) ((_hashlibstate *)PyModule_GetState(o))
61+
#define _hashlibstate_global ((_hashlibstate *)PyModule_GetState(PyState_FindModule(&_hashlibmodule)))
62+
63+
>>>>>>> bpo-38142: Updated _hashopenssl.c to be PEP 384 compliant
4864

4965
typedef struct {
5066
PyObject_HEAD
@@ -53,8 +69,6 @@ typedef struct {
5369
} EVPobject;
5470

5571

56-
static PyTypeObject EVPtype;
57-
5872
#include "clinic/_hashopenssl.c.h"
5973
/*[clinic input]
6074
module _hashlib
@@ -231,7 +245,9 @@ py_digest_by_name(const char *name)
231245
static EVPobject *
232246
newEVPobject(void)
233247
{
234-
EVPobject *retval = (EVPobject *)PyObject_New(EVPobject, &EVPtype);
248+
EVPobject *retval = (EVPobject *)PyObject_New(
249+
EVPobject, _hashlibstate_global->EVPtype
250+
);
235251
if (retval == NULL) {
236252
return NULL;
237253
}
@@ -501,46 +517,23 @@ PyDoc_STRVAR(hashtype_doc,
501517
"name -- the hash algorithm being used by this object\n"
502518
"digest_size -- number of bytes in this hashes output");
503519

504-
static PyTypeObject EVPtype = {
505-
PyVarObject_HEAD_INIT(NULL, 0)
520+
static PyType_Slot EVPtype_slots[] = {
521+
{Py_tp_dealloc, EVP_dealloc},
522+
{Py_tp_repr, EVP_repr},
523+
{Py_tp_doc, (char *)hashtype_doc},
524+
{Py_tp_methods, EVP_methods},
525+
{Py_tp_getset, EVP_getseters},
526+
{0, 0},
527+
};
528+
529+
static PyType_Spec EVPtype_spec = {
506530
"_hashlib.HASH", /*tp_name*/
507531
sizeof(EVPobject), /*tp_basicsize*/
508532
0, /*tp_itemsize*/
509-
/* methods */
510-
(destructor)EVP_dealloc, /*tp_dealloc*/
511-
0, /*tp_vectorcall_offset*/
512-
0, /*tp_getattr*/
513-
0, /*tp_setattr*/
514-
0, /*tp_as_async*/
515-
(reprfunc)EVP_repr, /*tp_repr*/
516-
0, /*tp_as_number*/
517-
0, /*tp_as_sequence*/
518-
0, /*tp_as_mapping*/
519-
0, /*tp_hash*/
520-
0, /*tp_call*/
521-
0, /*tp_str*/
522-
0, /*tp_getattro*/
523-
0, /*tp_setattro*/
524-
0, /*tp_as_buffer*/
525-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
526-
hashtype_doc, /*tp_doc*/
527-
0, /*tp_traverse*/
528-
0, /*tp_clear*/
529-
0, /*tp_richcompare*/
530-
0, /*tp_weaklistoffset*/
531-
0, /*tp_iter*/
532-
0, /*tp_iternext*/
533-
EVP_methods, /* tp_methods */
534-
NULL, /* tp_members */
535-
EVP_getseters, /* tp_getset */
536-
0, /* tp_base */
537-
0, /* tp_dict */
538-
0, /* tp_descr_get */
539-
0, /* tp_descr_set */
540-
0, /* tp_dictoffset */
533+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
534+
EVPtype_slots
541535
};
542536

543-
\
544537
static PyObject *
545538
EVPnew(const EVP_MD *digest,
546539
const unsigned char *cp, Py_ssize_t len, int usedforsecurity)
@@ -1120,17 +1113,39 @@ static struct PyMethodDef EVP_functions[] = {
11201113

11211114
/* Initialize this module. */
11221115

1116+
static int
1117+
hashlib_traverse(PyObject *m, visitproc visit, void *arg)
1118+
{
1119+
_hashlibstate *state = _hashlibstate(m);
1120+
Py_VISIT(state->EVPtype);
1121+
return 0;
1122+
}
1123+
1124+
static int
1125+
hashlib_clear(PyObject *m)
1126+
{
1127+
_hashlibstate *state = _hashlibstate(m);
1128+
Py_CLEAR(state->EVPtype);
1129+
return 0;
1130+
}
1131+
1132+
static void
1133+
hashlib_free(void *m)
1134+
{
1135+
hashlib_clear((PyObject *)m);
1136+
}
1137+
11231138

11241139
static struct PyModuleDef _hashlibmodule = {
11251140
PyModuleDef_HEAD_INIT,
11261141
"_hashlib",
11271142
NULL,
1128-
-1,
1143+
sizeof(_hashlibstate),
11291144
EVP_functions,
11301145
NULL,
1131-
NULL,
1132-
NULL,
1133-
NULL
1146+
hashlib_traverse,
1147+
hashlib_clear,
1148+
hashlib_free
11341149
};
11351150

11361151
PyMODINIT_FUNC
@@ -1144,19 +1159,21 @@ PyInit__hashlib(void)
11441159
ERR_load_crypto_strings();
11451160
#endif
11461161

1147-
/* TODO build EVP_functions openssl_* entries dynamically based
1148-
* on what hashes are supported rather than listing many
1149-
* but having some be unsupported. Only init appropriate
1150-
* constants. */
1151-
1152-
Py_TYPE(&EVPtype) = &PyType_Type;
1153-
if (PyType_Ready(&EVPtype) < 0)
1154-
return NULL;
1162+
m = PyState_FindModule(&_hashlibmodule);
1163+
if (m != NULL) {
1164+
Py_INCREF(m);
1165+
return m;
1166+
}
11551167

11561168
m = PyModule_Create(&_hashlibmodule);
11571169
if (m == NULL)
11581170
return NULL;
11591171

1172+
PyTypeObject *EVPtype = (PyTypeObject *)PyType_FromSpec(&EVPtype_spec);
1173+
if (EVPtype == NULL)
1174+
return NULL;
1175+
_hashlibstate(m)->EVPtype = EVPtype;
1176+
11601177
openssl_md_meth_names = generate_hash_name_list();
11611178
if (openssl_md_meth_names == NULL) {
11621179
Py_DECREF(m);
@@ -1167,8 +1184,9 @@ PyInit__hashlib(void)
11671184
return NULL;
11681185
}
11691186

1170-
Py_INCREF((PyObject *)&EVPtype);
1171-
PyModule_AddObject(m, "HASH", (PyObject *)&EVPtype);
1187+
Py_INCREF((PyObject *)_hashlibstate(m)->EVPtype);
1188+
PyModule_AddObject(m, "HASH", (PyObject *)_hashlibstate(m)->EVPtype);
11721189

1190+
PyState_AddModule(m, &_hashlibmodule);
11731191
return m;
11741192
}

0 commit comments

Comments
 (0)