summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2020-10-11 13:51:07 (GMT)
committerGitHub <noreply@github.com>2020-10-11 13:51:07 (GMT)
commit8287aadb75f6bd0154996424819334cd3839707c (patch)
treea8c1bdba620f33bd02e9558fe2a8bae6df69d37b /Python
parentfa1d83db62a545580d9a1a585b2c1fb55961a5c3 (diff)
downloadcpython-8287aadb75f6bd0154996424819334cd3839707c.zip
cpython-8287aadb75f6bd0154996424819334cd3839707c.tar.gz
cpython-8287aadb75f6bd0154996424819334cd3839707c.tar.bz2
bpo-41993: Fix possible issues in remove_module() (GH-22631)
* 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().
Diffstat (limited to 'Python')
-rw-r--r--Python/import.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/Python/import.c b/Python/import.c
index 5056884..26b80f3 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -902,7 +902,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)
{
@@ -910,18 +914,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);
}