[Python-checkins] cpython (2.7): Issue #25698: Importing module if the stack is too deep no longer replaces

serhiy.storchaka python-checkins at python.org
Wed Feb 10 03:33:36 EST 2016


https://hg.python.org/cpython/rev/81dba6e392c3
changeset:   100214:81dba6e392c3
branch:      2.7
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Wed Feb 10 10:28:06 2016 +0200
summary:
  Issue #25698: Importing module if the stack is too deep no longer replaces
imported module with the empty one.

files:
  Include/dictobject.h |   1 +
  Misc/NEWS            |   3 ++
  Objects/dictobject.c |  30 ++++++++++++++++++++
  Python/import.c      |  48 ++++++++++++++++++++++----------
  4 files changed, 67 insertions(+), 15 deletions(-)


diff --git a/Include/dictobject.h b/Include/dictobject.h
--- a/Include/dictobject.h
+++ b/Include/dictobject.h
@@ -108,6 +108,7 @@
 
 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
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -50,6 +50,9 @@
 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
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -749,6 +749,36 @@
     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
--- a/Python/import.c
+++ b/Python/import.c
@@ -632,25 +632,43 @@
    Because the former action is most common, THIS DOES NOT RETURN A
    'NEW' REFERENCE! */
 
+static PyObject *
+_PyImport_AddModuleObject(PyObject *name)
+{
+    PyObject *modules = PyImport_GetModuleDict();
+    PyObject *m;
+
+    if ((m = _PyDict_GetItemWithError(modules, name)) != NULL &&
+        PyModule_Check(m)) {
+        return m;
+    }
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
+    m = PyModule_New(PyString_AS_STRING(name));
+    if (m == NULL) {
+        return NULL;
+    }
+    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 *modules = PyImport_GetModuleDict();
-    PyObject *m;
-
-    if ((m = PyDict_GetItemString(modules, name)) != NULL &&
-        PyModule_Check(m))
-        return m;
-    m = PyModule_New(name);
-    if (m == NULL)
+    PyObject *nameobj, *module;
+    nameobj = PyString_FromString(name);
+    if (nameobj == NULL)
         return NULL;
-    if (PyDict_SetItemString(modules, name, m) != 0) {
-        Py_DECREF(m);
-        return NULL;
-    }
-    Py_DECREF(m); /* Yes, it still exists, in modules! */
-
-    return m;
+    module = _PyImport_AddModuleObject(nameobj);
+    Py_DECREF(nameobj);
+    return module;
 }
 
 /* Remove name from sys.modules, if it's there. */

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list