]> granicus.if.org Git - python/commitdiff
bpo-29849: fix a memory leak in import_from (GH-712)
authorXiang Zhang <angwerzx@126.com>
Tue, 21 Mar 2017 03:13:42 +0000 (11:13 +0800)
committerGitHub <noreply@github.com>
Tue, 21 Mar 2017 03:13:42 +0000 (11:13 +0800)
Misc/NEWS
Python/ceval.c

index d8ea4c91e54e1adb9d7bfe9f63f7d67a6c64e083..b86e5c96f25a40550d128c6b15d72447c5cfaf8b 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.7.0 alpha 1?
 Core and Builtins
 -----------------
 
+- bpo-29849: Fix a memory leak when an ImportError is raised during from import.
+
 - bpo-28856: Fix an oversight that %b format for bytes should support objects
   follow the buffer protocol.
 
index 8ee58f5d30b529ff29522f02fcb9357db86dac02..fd60b7344a2c3edee8dfc8567ac10a0db70b26ae 100644 (file)
@@ -5024,7 +5024,7 @@ import_from(PyObject *v, PyObject *name)
 {
     PyObject *x;
     _Py_IDENTIFIER(__name__);
-    PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown;
+    PyObject *fullmodname, *pkgname, *pkgpath, *pkgname_or_unknown, *errmsg;
 
     x = PyObject_GetAttr(v, name);
     if (x != NULL || !PyErr_ExceptionMatches(PyExc_AttributeError))
@@ -5039,6 +5039,7 @@ import_from(PyObject *v, PyObject *name)
     }
     fullmodname = PyUnicode_FromFormat("%U.%U", pkgname, name);
     if (fullmodname == NULL) {
+        Py_DECREF(pkgname);
         return NULL;
     }
     x = PyDict_GetItem(PyImport_GetModuleDict(), fullmodname);
@@ -5063,17 +5064,23 @@ import_from(PyObject *v, PyObject *name)
 
     if (pkgpath == NULL || !PyUnicode_Check(pkgpath)) {
         PyErr_Clear();
-        PyErr_SetImportError(
-            PyUnicode_FromFormat("cannot import name %R from %R (unknown location)",
-                name, pkgname_or_unknown),
-            pkgname, NULL);
-    } else {
-        PyErr_SetImportError(
-            PyUnicode_FromFormat("cannot import name %R from %R (%S)",
-                name, pkgname_or_unknown, pkgpath),
-            pkgname, pkgpath);
+        errmsg = PyUnicode_FromFormat(
+            "cannot import name %R from %R (unknown location)",
+            name, pkgname_or_unknown
+        );
+        /* NULL check for errmsg done by PyErr_SetImportError. */
+        PyErr_SetImportError(errmsg, pkgname, NULL);
+    }
+    else {
+        errmsg = PyUnicode_FromFormat(
+            "cannot import name %R from %R (%S)",
+            name, pkgname_or_unknown, pkgpath
+        );
+        /* NULL check for errmsg done by PyErr_SetImportError. */
+        PyErr_SetImportError(errmsg, pkgname, pkgpath);
     }
 
+    Py_XDECREF(errmsg);
     Py_XDECREF(pkgname_or_unknown);
     Py_XDECREF(pkgpath);
     return NULL;