summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-02-10 10:28:06 +0200
committerSerhiy Storchaka <storchaka@gmail.com>2016-02-10 10:28:06 +0200
commit1c496178d2c863f135bd4a43e32e0f099480cd06 (patch)
treed3db8cca9df26eb21cfcf6eabbc9cd67a64e35b2
parent53ae0ba6e308b383c63476177aa185a4b6f6e216 (diff)
downloadcpython-git-1c496178d2c863f135bd4a43e32e0f099480cd06.tar.gz
Issue #25698: Importing module if the stack is too deep no longer replaces
imported module with the empty one.
-rw-r--r--Include/dictobject.h1
-rw-r--r--Misc/NEWS3
-rw-r--r--Objects/dictobject.c30
-rw-r--r--Python/import.c32
4 files changed, 59 insertions, 7 deletions
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)