From 52b802819c67a8d9496919243c76de61a40211f3 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 23 May 2018 11:04:28 +0200 Subject: [PATCH] bpo-33330: PyImport_Cleanup check for exc leaks * Add "assert(!PyErr_Occurred());" assertions to PyImport_Cleanup() and _PyGC_CollectNoFail() to make sure that these functions don't leak exceptions. * Replace also PyImport_GetModuleDict() call with interp->modules to prevent a fatal error if modules is already NULL. --- Modules/gcmodule.c | 2 ++ Python/import.c | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index 09c73569360e67..aeff3f0e12240b 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -1595,6 +1595,7 @@ _PyGC_CollectNoFail(void) during interpreter shutdown (and then never finish it). See http://bugs.python.org/issue8713#msg195178 for an example. */ + assert(!PyErr_Occurred()); if (_PyRuntime.gc.collecting) n = 0; else { @@ -1602,6 +1603,7 @@ _PyGC_CollectNoFail(void) n = collect(NUM_GENERATIONS - 1, NULL, NULL, 1); _PyRuntime.gc.collecting = 0; } + assert(!PyErr_Occurred()); return n; } diff --git a/Python/import.c b/Python/import.c index 3a591836654b31..2fcfa25a8e1771 100644 --- a/Python/import.c +++ b/Python/import.c @@ -396,15 +396,18 @@ static const char * const sys_files[] = { void PyImport_Cleanup(void) { + assert(!PyErr_Occurred()); + Py_ssize_t pos; PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; - PyObject *modules = PyImport_GetModuleDict(); PyObject *weaklist = NULL; const char * const *p; - if (modules == NULL) + PyObject *modules = interp->modules; + if (modules == NULL) { return; /* Already done */ + } /* Delete some special variables first. These are common places where user values hide and people complain when their @@ -437,6 +440,7 @@ PyImport_Cleanup(void) PyErr_WriteUnraisable(NULL); } } + assert(!PyErr_Occurred()); /* We prepare a list which will receive (name, weakref) tuples of modules when they are removed from sys.modules. The name is used @@ -477,6 +481,7 @@ PyImport_Cleanup(void) if (PyDict_CheckExact(modules)) { pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { + assert(!PyErr_Occurred()); CLEAR_MODULE(key, value); } } @@ -492,6 +497,7 @@ PyImport_Cleanup(void) PyErr_WriteUnraisable(NULL); continue; } + assert(!PyErr_Occurred()); CLEAR_MODULE(key, value); Py_DECREF(value); Py_DECREF(key); @@ -502,6 +508,7 @@ PyImport_Cleanup(void) Py_DECREF(iterator); } } + assert(!PyErr_Occurred()); /* Clear the modules dict. */ if (PyDict_CheckExact(modules)) { @@ -524,6 +531,8 @@ PyImport_Cleanup(void) PyErr_Clear(); } Py_XDECREF(dict); + assert(!PyErr_Occurred()); + /* Clear module dict copies stored in the interpreter state */ _PyState_ClearModules(); /* Collect references */ @@ -543,6 +552,7 @@ PyImport_Cleanup(void) references left to it), we need to delete the "builtins" module last. Likewise, we don't delete sys until the very end because it is implicitly referenced (e.g. by print). */ + assert(!PyErr_Occurred()); if (weaklist != NULL) { Py_ssize_t i, n; n = PyList_GET_SIZE(weaklist); @@ -559,6 +569,7 @@ PyImport_Cleanup(void) Py_INCREF(mod); if (Py_VerboseFlag && PyUnicode_Check(name)) PySys_FormatStderr("# cleanup[3] wiping %U\n", name); + assert(!PyErr_Occurred()); _PyModule_Clear(mod); Py_DECREF(mod); }