bpo-32374: m_traverse may be called with m_state=NULL (GH-5140)

Multi-phase initialized modules allow m_traverse to be called while the
module is still being initialized, so module authors may need to account
for that.
This commit is contained in:
Marcel Plch 2018-03-17 06:41:20 +01:00 committed by Nick Coghlan
parent d6e1404661
commit c2b0b12d1a
5 changed files with 96 additions and 7 deletions

View file

@ -21,6 +21,17 @@ static PyMemberDef module_members[] = {
{0}
};
/* Helper for sanity check for traverse not handling m_state == NULL
* Issue #32374 */
#ifdef Py_DEBUG
static int
bad_traverse_test(PyObject *self, void *arg) {
assert(self != NULL);
return 0;
}
#endif
PyTypeObject PyModuleDef_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"moduledef", /* tp_name */
@ -345,6 +356,16 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api
}
}
/* Sanity check for traverse not handling m_state == NULL
* This doesn't catch all possible cases, but in many cases it should
* make many cases of invalid code crash or raise Valgrind issues
* sooner than they would otherwise.
* Issue #32374 */
#ifdef Py_DEBUG
if (def->m_traverse != NULL) {
def->m_traverse(m, bad_traverse_test, NULL);
}
#endif
Py_DECREF(nameobj);
return m;