gh-94673: Ensure Builtin Static Types are Readied Properly by ericsnowcurrently · Pull Request #103940 · python/cpython (original) (raw)

This causes a regression for some users of PyModule_AddType. Previously, you could do something like

PyTypeObject MyType = { PyObject_HEAD_INIT(NULL) /* ... */ };

int MyType_Add(PyObject *m) { int err; PyObject *obj = PyLong_FromDouble(1.0);

if (!obj)
    return -1;

MyType.tp_dict = PyDict_New();
if (!type->tp_dict) {
    Py_DECREF(obj);
    return -1;
}

err = PyDict_SetItemString(MyType.tp_dict, "foo", obj);
Py_DECREF(obj);
if (err)
    return err;

if (PyModule_AddType(m, &MyType))
    return -1;

return 0;

}

but now this will now segfault, as PyModule_AddType will never call PyType_Ready since tp_dict is initialized. The documentation for PyModule_AddType says:

Add a type object to module. The type object is finalized by calling internally PyType_Ready().

with no mention of tp_dict. On the subject of when to call PyType_Ready, the documentation for PyObject.ob_type says:

Therefore, the convention is to pass NULL to the PyObject_HEAD_INIT macro and to initialize this field explicitly at the start of the module’s initialization function, before doing anything else...

This should be done before any instances of the type are created.

PyTypeObject.tp_dict may also be initialized before calling PyType_Ready:

This field should normally be initialized to NULL before PyType_Ready is called; it may also be initialized to a dictionary containing initial attributes for the type.

As PyModule_AddType is part of the stable ABI, I believe that using _PyType_IsReady in PyModule_AddType should be reverted.