--- /dev/null
+:c:func:`PyImport_GetImporter` now sets RuntimeError if it fails to get
+:data:`sys.path_hooks` or :data:`sys.path_importer_cache` or they are not
+list and dict correspondingly. Previously it could return NULL without
+setting error in obscure cases, crash or raise SystemError if these
+attributes have wrong type.
PyObject *importer;
Py_ssize_t j, nhooks;
- /* These conditions are the caller's responsibility: */
- assert(PyList_Check(path_hooks));
- assert(PyDict_Check(path_importer_cache));
+ if (!PyList_Check(path_hooks)) {
+ PyErr_SetString(PyExc_RuntimeError, "sys.path_hooks is not a list");
+ return NULL;
+ }
+ if (!PyDict_Check(path_importer_cache)) {
+ PyErr_SetString(PyExc_RuntimeError, "sys.path_importer_cache is not a dict");
+ return NULL;
+ }
nhooks = PyList_Size(path_hooks);
if (nhooks < 0)
{
PyThreadState *tstate = _PyThreadState_GET();
PyObject *path_importer_cache = PySys_GetObject("path_importer_cache");
+ if (path_importer_cache == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "lost sys.path_importer_cache");
+ return NULL;
+ }
+ Py_INCREF(path_importer_cache);
PyObject *path_hooks = PySys_GetObject("path_hooks");
- if (path_importer_cache == NULL || path_hooks == NULL) {
+ if (path_hooks == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "lost sys.path_hooks");
+ Py_DECREF(path_importer_cache);
return NULL;
}
- return get_path_importer(tstate, path_importer_cache, path_hooks, path);
+ Py_INCREF(path_hooks);
+ PyObject *importer = get_path_importer(tstate, path_importer_cache, path_hooks, path);
+ Py_DECREF(path_hooks);
+ Py_DECREF(path_importer_cache);
+ return importer;
}