]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-41993: Fix possible issues in remove_module() (GH-22631) (GH-22647)
authorMiss Skeleton (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 14 Oct 2020 09:09:44 +0000 (02:09 -0700)
committerGitHub <noreply@github.com>
Wed, 14 Oct 2020 09:09:44 +0000 (12:09 +0300)
* 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 8287aadb75f6bd0154996424819334cd3839707c)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Misc/NEWS.d/next/Core and Builtins/2020-10-10-13-53-52.bpo-41993.YMzixQ.rst [new file with mode: 0644]
Python/import.c

diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-10-10-13-53-52.bpo-41993.YMzixQ.rst b/Misc/NEWS.d/next/Core and Builtins/2020-10-10-13-53-52.bpo-41993.YMzixQ.rst
new file mode 100644 (file)
index 0000000..3669cf1
--- /dev/null
@@ -0,0 +1,2 @@
+Fixed potential issues with removing not completely initialized module from
+``sys.modules`` when import fails.
index 0e2e7c370868fa13bb3cff2d18b3eae4bb31c818..5e39a2fb9a02e587fcdaf21d3d61feda105be67d 100644 (file)
@@ -905,7 +905,11 @@ 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(PyThreadState *tstate, PyObject *name)
 {
@@ -913,18 +917,17 @@ remove_module(PyThreadState *tstate, PyObject *name)
     _PyErr_Fetch(tstate, &type, &value, &traceback);
 
     PyObject *modules = tstate->interp->modules;
-    if (!PyMapping_HasKey(modules, name)) {
-        goto out;
+    if (PyDict_CheckExact(modules)) {
+        PyObject *mod = _PyDict_Pop(modules, name, Py_None);
+        Py_XDECREF(mod);
     }
-    if (PyMapping_DelItem(modules, name) < 0) {
-        _PyErr_SetString(tstate, PyExc_RuntimeError,
-                         "deleting key in sys.modules failed");
-        _PyErr_ChainExceptions(type, value, traceback);
-        return;
+    else if (PyMapping_DelItem(modules, name) < 0) {
+        if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
+            _PyErr_Clear(tstate);
+        }
     }
 
-out:
-    _PyErr_Restore(tstate, type, value, traceback);
+    _PyErr_ChainExceptions(type, value, traceback);
 }