Skip to content

Commit

Permalink
[3.8] bpo-41993: Fix possible issues in remove_module() (pythonGH-22631)
Browse files Browse the repository at this point in the history
* PyMapping_HasKey() is not safe because it silences all exceptions and can return incorrect result.
* Informative exceptions from PyMapping_DelItem() are overridden with RuntimeError and
  the original exception raised before calling remove_module() is lost.
* There is a race condition between PyMapping_HasKey() and PyMapping_DelItem()..
(cherry picked from commit 8287aad)

Co-authored-by: Serhiy Storchaka <[email protected]>
  • Loading branch information
serhiy-storchaka committed Oct 11, 2020
1 parent ff6870f commit 6c58859
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fixed potential issues with removing not completely initialized module from
``sys.modules`` when import fails.
25 changes: 16 additions & 9 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,22 +845,29 @@ PyImport_AddModule(const char *name)
}


/* Remove name from sys.modules, if it's there. */
/* Remove name from sys.modules, if it's there.
* Can be called with an exception raised.
* If fail to remove name a new exception will be chained with the old
* exception, otherwise the old exception is preserved.
*/
static void
remove_module(PyObject *name)
{
PyObject *type, *value, *traceback;
PyErr_Fetch(&type, &value, &traceback);
PyObject *modules = PyImport_GetModuleDict();
if (!PyMapping_HasKey(modules, name)) {
goto out;

PyObject *modules = tstate->interp->modules;
if (PyDict_CheckExact(modules)) {
PyObject *mod = _PyDict_Pop(modules, name, Py_None);
Py_XDECREF(mod);
}
if (PyMapping_DelItem(modules, name) < 0) {
Py_FatalError("import: deleting existing key in "
"sys.modules failed");
else if (PyMapping_DelItem(modules, name) < 0) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) {
PyErr_Clear();
}
}
out:
PyErr_Restore(type, value, traceback);

_PyErr_ChainExceptions(type, value, traceback);
}


Expand Down

0 comments on commit 6c58859

Please sign in to comment.