bpo-35943: Prevent PyImport_GetModule() from returning a partially-initialized module (GH-15057)
This commit is contained in:
parent
60bba83b5d
commit
37c2220698
|
@ -0,0 +1,2 @@
|
||||||
|
The function :c:func:`PyImport_GetModule` now ensures any module it returns is fully initialized.
|
||||||
|
Patch by Joannah Nanjekye.
|
|
@ -387,11 +387,33 @@ import_get_module(PyThreadState *tstate, PyObject *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *
|
static int
|
||||||
PyImport_GetModule(PyObject *name)
|
import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyInterpreterState *interp = tstate->interp;
|
||||||
return import_get_module(tstate, name);
|
PyObject *spec;
|
||||||
|
|
||||||
|
_Py_IDENTIFIER(__spec__);
|
||||||
|
_Py_IDENTIFIER(_lock_unlock_module);
|
||||||
|
|
||||||
|
/* Optimization: only call _bootstrap._lock_unlock_module() if
|
||||||
|
__spec__._initializing is true.
|
||||||
|
NOTE: because of this, initializing must be set *before*
|
||||||
|
stuffing the new module in sys.modules.
|
||||||
|
*/
|
||||||
|
spec = _PyObject_GetAttrId(mod, &PyId___spec__);
|
||||||
|
int busy = _PyModuleSpec_IsInitializing(spec);
|
||||||
|
Py_XDECREF(spec);
|
||||||
|
if (busy) {
|
||||||
|
/* Wait until module is done importing. */
|
||||||
|
PyObject *value = _PyObject_CallMethodIdOneArg(
|
||||||
|
interp->importlib, &PyId__lock_unlock_module, name);
|
||||||
|
if (value == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1461,6 +1483,7 @@ PyImport_ImportModule(const char *name)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Import a module without blocking
|
/* Import a module without blocking
|
||||||
*
|
*
|
||||||
* At first it tries to fetch the module from sys.modules. If the module was
|
* At first it tries to fetch the module from sys.modules. If the module was
|
||||||
|
@ -1762,6 +1785,23 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name)
|
||||||
return mod;
|
return mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *
|
||||||
|
PyImport_GetModule(PyObject *name)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
PyObject *mod;
|
||||||
|
|
||||||
|
mod = import_get_module(tstate, name);
|
||||||
|
if (mod != NULL && mod != Py_None) {
|
||||||
|
if (import_ensure_initialized(tstate, mod, name) < 0) {
|
||||||
|
Py_DECREF(mod);
|
||||||
|
remove_importlib_frames(tstate);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
PyObject *locals, PyObject *fromlist,
|
PyObject *locals, PyObject *fromlist,
|
||||||
|
@ -1817,26 +1857,9 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod != NULL && mod != Py_None) {
|
if (mod != NULL && mod != Py_None) {
|
||||||
_Py_IDENTIFIER(__spec__);
|
if (import_ensure_initialized(tstate, mod, name) < 0) {
|
||||||
_Py_IDENTIFIER(_lock_unlock_module);
|
goto error;
|
||||||
PyObject *spec;
|
|
||||||
|
|
||||||
/* Optimization: only call _bootstrap._lock_unlock_module() if
|
|
||||||
__spec__._initializing is true.
|
|
||||||
NOTE: because of this, initializing must be set *before*
|
|
||||||
stuffing the new module in sys.modules.
|
|
||||||
*/
|
|
||||||
spec = _PyObject_GetAttrId(mod, &PyId___spec__);
|
|
||||||
if (_PyModuleSpec_IsInitializing(spec)) {
|
|
||||||
PyObject *value = _PyObject_CallMethodIdOneArg(
|
|
||||||
interp->importlib, &PyId__lock_unlock_module, abs_name);
|
|
||||||
if (value == NULL) {
|
|
||||||
Py_DECREF(spec);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
Py_DECREF(value);
|
|
||||||
}
|
}
|
||||||
Py_XDECREF(spec);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Py_XDECREF(mod);
|
Py_XDECREF(mod);
|
||||||
|
|
Loading…
Reference in New Issue