From: Serhiy Storchaka Date: Wed, 10 Feb 2016 08:28:06 +0000 (+0200) Subject: Issue #25698: Importing module if the stack is too deep no longer replaces X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1c496178d2c863f135bd4a43e32e0f099480cd06;p=python Issue #25698: Importing module if the stack is too deep no longer replaces imported module with the empty one. --- diff --git a/Include/dictobject.h b/Include/dictobject.h index ece01c64d6..ef524a4040 100644 --- a/Include/dictobject.h +++ b/Include/dictobject.h @@ -108,6 +108,7 @@ PyAPI_DATA(PyTypeObject) PyDictValues_Type; PyAPI_FUNC(PyObject *) PyDict_New(void); PyAPI_FUNC(PyObject *) PyDict_GetItem(PyObject *mp, PyObject *key); +PyAPI_FUNC(PyObject *) _PyDict_GetItemWithError(PyObject *mp, PyObject *key); PyAPI_FUNC(int) PyDict_SetItem(PyObject *mp, PyObject *key, PyObject *item); PyAPI_FUNC(int) PyDict_DelItem(PyObject *mp, PyObject *key); PyAPI_FUNC(void) PyDict_Clear(PyObject *mp); diff --git a/Misc/NEWS b/Misc/NEWS index a917523cdd..659d7cada1 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -50,6 +50,9 @@ Core and Builtins Library ------- +- Issue #25698: Importing module if the stack is too deep no longer replaces + imported module with the empty one. + - Issue #12923: Reset FancyURLopener's redirect counter even if there is an exception. Based on patches by Brian Brazil and Daniel Rocco. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index b281948be8..3e1c5830ec 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -749,6 +749,36 @@ PyDict_GetItem(PyObject *op, PyObject *key) return ep->me_value; } +/* Variant of PyDict_GetItem() that doesn't suppress exceptions. + This returns NULL *with* an exception set if an exception occurred. + It returns NULL *without* an exception set if the key wasn't present. +*/ +PyObject * +_PyDict_GetItemWithError(PyObject *op, PyObject *key) +{ + long hash; + PyDictObject *mp = (PyDictObject *)op; + PyDictEntry *ep; + if (!PyDict_Check(op)) { + PyErr_BadInternalCall(); + return NULL; + } + if (!PyString_CheckExact(key) || + (hash = ((PyStringObject *) key)->ob_shash) == -1) + { + hash = PyObject_Hash(key); + if (hash == -1) { + return NULL; + } + } + + ep = (mp->ma_lookup)(mp, key, hash); + if (ep == NULL) { + return NULL; + } + return ep->me_value; +} + static int dict_set_item_by_hash_or_entry(register PyObject *op, PyObject *key, long hash, PyDictEntry *ep, PyObject *value) diff --git a/Python/import.c b/Python/import.c index e47ce633ca..96f7d47544 100644 --- a/Python/import.c +++ b/Python/import.c @@ -632,27 +632,45 @@ _PyImport_FindExtension(char *name, char *filename) Because the former action is most common, THIS DOES NOT RETURN A 'NEW' REFERENCE! */ -PyObject * -PyImport_AddModule(const char *name) +static PyObject * +_PyImport_AddModuleObject(PyObject *name) { PyObject *modules = PyImport_GetModuleDict(); PyObject *m; - if ((m = PyDict_GetItemString(modules, name)) != NULL && - PyModule_Check(m)) + if ((m = _PyDict_GetItemWithError(modules, name)) != NULL && + PyModule_Check(m)) { return m; - m = PyModule_New(name); - if (m == NULL) + } + if (PyErr_Occurred()) { + return NULL; + } + m = PyModule_New(PyString_AS_STRING(name)); + if (m == NULL) { return NULL; - if (PyDict_SetItemString(modules, name, m) != 0) { + } + if (PyDict_SetItem(modules, name, m) != 0) { Py_DECREF(m); return NULL; } + assert(Py_REFCNT(m) > 1); Py_DECREF(m); /* Yes, it still exists, in modules! */ return m; } +PyObject * +PyImport_AddModule(const char *name) +{ + PyObject *nameobj, *module; + nameobj = PyString_FromString(name); + if (nameobj == NULL) + return NULL; + module = _PyImport_AddModuleObject(nameobj); + Py_DECREF(nameobj); + return module; +} + /* Remove name from sys.modules, if it's there. */ static void remove_module(const char *name)