Skip to content

Commit 63f102f

Browse files
authored
bpo-1635741: Port _sha1, _sha512, _md5 to multiphase init (GH-21818)
Port the _sha1, _sha512, and _md5 extension modules to multi-phase initialization API (PEP 489).
1 parent 5371a46 commit 63f102f

File tree

7 files changed

+359
-251
lines changed

7 files changed

+359
-251
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Port the :mod:`_sha1`, :mod:`_sha512`, and :mod:`_md5` extension modules
2+
to multi-phase initialization API (:pep:`489`).

Modules/clinic/md5module.c.h

Lines changed: 16 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/clinic/sha1module.c.h

Lines changed: 16 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/clinic/sha512module.c.h

Lines changed: 16 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/md5module.c

Lines changed: 89 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,32 @@ md5_done(struct md5_state *md5, unsigned char *out)
318318
* ------------------------------------------------------------------------
319319
*/
320320

321-
static PyTypeObject MD5type;
321+
typedef struct {
322+
PyTypeObject* md5_type;
323+
} MD5State;
322324

325+
static inline MD5State*
326+
md5_get_state(PyObject *module)
327+
{
328+
void *state = PyModule_GetState(module);
329+
assert(state != NULL);
330+
return (MD5State *)state;
331+
}
323332

324333
static MD5object *
325-
newMD5object(void)
334+
newMD5object(MD5State * st)
326335
{
327-
return (MD5object *)PyObject_New(MD5object, &MD5type);
336+
return (MD5object *)PyObject_New(MD5object, st->md5_type);
328337
}
329338

330-
331339
/* Internal methods for a hash object */
332340

333341
static void
334342
MD5_dealloc(PyObject *ptr)
335343
{
344+
PyTypeObject *tp = Py_TYPE(ptr);
336345
PyObject_Del(ptr);
346+
Py_DECREF(tp);
337347
}
338348

339349

@@ -342,16 +352,19 @@ MD5_dealloc(PyObject *ptr)
342352
/*[clinic input]
343353
MD5Type.copy
344354
355+
cls: defining_class
356+
345357
Return a copy of the hash object.
346358
[clinic start generated code]*/
347359

348360
static PyObject *
349-
MD5Type_copy_impl(MD5object *self)
350-
/*[clinic end generated code: output=596eb36852f02071 input=2c09e6d2493f3079]*/
361+
MD5Type_copy_impl(MD5object *self, PyTypeObject *cls)
362+
/*[clinic end generated code: output=bf055e08244bf5ee input=d89087dcfb2a8620]*/
351363
{
352-
MD5object *newobj;
364+
MD5State *st = PyType_GetModuleState(cls);
353365

354-
if ((newobj = newMD5object())==NULL)
366+
MD5object *newobj;
367+
if ((newobj = newMD5object(st))==NULL)
355368
return NULL;
356369

357370
newobj->hash_state = self->hash_state;
@@ -445,7 +458,6 @@ md5_get_digest_size(PyObject *self, void *closure)
445458
return PyLong_FromLong(MD5_DIGESTSIZE);
446459
}
447460

448-
449461
static PyGetSetDef MD5_getseters[] = {
450462
{"block_size",
451463
(getter)MD5_get_block_size, NULL,
@@ -462,40 +474,19 @@ static PyGetSetDef MD5_getseters[] = {
462474
{NULL} /* Sentinel */
463475
};
464476

465-
static PyTypeObject MD5type = {
466-
PyVarObject_HEAD_INIT(NULL, 0)
467-
"_md5.md5", /*tp_name*/
468-
sizeof(MD5object), /*tp_basicsize*/
469-
0, /*tp_itemsize*/
470-
/* methods */
471-
MD5_dealloc, /*tp_dealloc*/
472-
0, /*tp_vectorcall_offset*/
473-
0, /*tp_getattr*/
474-
0, /*tp_setattr*/
475-
0, /*tp_as_async*/
476-
0, /*tp_repr*/
477-
0, /*tp_as_number*/
478-
0, /*tp_as_sequence*/
479-
0, /*tp_as_mapping*/
480-
0, /*tp_hash*/
481-
0, /*tp_call*/
482-
0, /*tp_str*/
483-
0, /*tp_getattro*/
484-
0, /*tp_setattro*/
485-
0, /*tp_as_buffer*/
486-
Py_TPFLAGS_DEFAULT, /*tp_flags*/
487-
0, /*tp_doc*/
488-
0, /*tp_traverse*/
489-
0, /*tp_clear*/
490-
0, /*tp_richcompare*/
491-
0, /*tp_weaklistoffset*/
492-
0, /*tp_iter*/
493-
0, /*tp_iternext*/
494-
MD5_methods, /* tp_methods */
495-
NULL, /* tp_members */
496-
MD5_getseters, /* tp_getset */
477+
static PyType_Slot md5_type_slots[] = {
478+
{Py_tp_dealloc, MD5_dealloc},
479+
{Py_tp_methods, MD5_methods},
480+
{Py_tp_getset, MD5_getseters},
481+
{0,0}
497482
};
498483

484+
static PyType_Spec md5_type_spec = {
485+
.name = "_md5.md5",
486+
.basicsize = sizeof(MD5object),
487+
.flags = Py_TPFLAGS_DEFAULT,
488+
.slots = md5_type_slots
489+
};
499490

500491
/* The single module-level function: new() */
501492

@@ -519,7 +510,8 @@ _md5_md5_impl(PyObject *module, PyObject *string, int usedforsecurity)
519510
if (string)
520511
GET_BUFFER_VIEW_OR_ERROUT(string, &buf);
521512

522-
if ((new = newMD5object()) == NULL) {
513+
MD5State *st = md5_get_state(module);
514+
if ((new = newMD5object(st)) == NULL) {
523515
if (string)
524516
PyBuffer_Release(&buf);
525517
return NULL;
@@ -549,37 +541,69 @@ static struct PyMethodDef MD5_functions[] = {
549541
{NULL, NULL} /* Sentinel */
550542
};
551543

544+
static int
545+
_md5_traverse(PyObject *module, visitproc visit, void *arg)
546+
{
547+
MD5State *state = md5_get_state(module);
548+
Py_VISIT(state->md5_type);
549+
return 0;
550+
}
551+
552+
static int
553+
_md5_clear(PyObject *module)
554+
{
555+
MD5State *state = md5_get_state(module);
556+
Py_CLEAR(state->md5_type);
557+
return 0;
558+
}
559+
560+
static void
561+
_md5_free(void *module)
562+
{
563+
_md5_clear((PyObject *)module);
564+
}
552565

553566
/* Initialize this module. */
567+
static int
568+
md5_exec(PyObject *m)
569+
{
570+
MD5State *st = md5_get_state(m);
571+
572+
st->md5_type = (PyTypeObject *)PyType_FromModuleAndSpec(
573+
m, &md5_type_spec, NULL);
574+
575+
if (st->md5_type == NULL) {
576+
return -1;
577+
}
578+
579+
Py_INCREF((PyObject *)st->md5_type);
580+
if (PyModule_AddObject(m, "MD5Type", (PyObject *)st->md5_type) < 0) {
581+
Py_DECREF(st->md5_type);
582+
return -1;
583+
}
584+
585+
return 0;
586+
}
587+
588+
static PyModuleDef_Slot _md5_slots[] = {
589+
{Py_mod_exec, md5_exec},
590+
{0, NULL}
591+
};
592+
554593

555594
static struct PyModuleDef _md5module = {
556595
PyModuleDef_HEAD_INIT,
557-
"_md5",
558-
NULL,
559-
-1,
560-
MD5_functions,
561-
NULL,
562-
NULL,
563-
NULL,
564-
NULL
596+
.m_name = "_md5",
597+
.m_size = sizeof(MD5State),
598+
.m_methods = MD5_functions,
599+
.m_slots = _md5_slots,
600+
.m_traverse = _md5_traverse,
601+
.m_clear = _md5_clear,
602+
.m_free = _md5_free,
565603
};
566604

567605
PyMODINIT_FUNC
568606
PyInit__md5(void)
569607
{
570-
PyObject *m;
571-
572-
Py_SET_TYPE(&MD5type, &PyType_Type);
573-
if (PyType_Ready(&MD5type) < 0) {
574-
return NULL;
575-
}
576-
577-
m = PyModule_Create(&_md5module);
578-
if (m == NULL) {
579-
return NULL;
580-
}
581-
582-
Py_INCREF((PyObject *)&MD5type);
583-
PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type);
584-
return m;
608+
return PyModuleDef_Init(&_md5module);
585609
}

0 commit comments

Comments
 (0)