[Python-checkins] cpython (merge 3.5 -> 3.6): Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception

serhiy.storchaka python-checkins at python.org
Tue Oct 18 06:28:35 EDT 2016


https://hg.python.org/cpython/rev/2d352bf2b228
changeset:   104530:2d352bf2b228
branch:      3.6
parent:      104527:d32ec6591c49
parent:      104529:6b3be9f38f2a
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Tue Oct 18 13:26:25 2016 +0300
summary:
  Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
loss in PyTraceBack_Here().

files:
  Misc/NEWS          |   3 ++
  Python/traceback.c |  46 +++++++++++++++++++--------------
  2 files changed, 29 insertions(+), 20 deletions(-)


diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
+  loss in PyTraceBack_Here().
+
 Library
 -------
 
diff --git a/Python/traceback.c b/Python/traceback.c
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -132,47 +132,53 @@
 int
 PyTraceBack_Here(PyFrameObject *frame)
 {
-    PyThreadState *tstate = PyThreadState_GET();
-    PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
-    PyTracebackObject *tb = newtracebackobject(oldtb, frame);
-    if (tb == NULL)
+    PyObject *exc, *val, *tb, *newtb;
+    PyErr_Fetch(&exc, &val, &tb);
+    newtb = (PyObject *)newtracebackobject((PyTracebackObject *)tb, frame);
+    if (newtb == NULL) {
+        _PyErr_ChainExceptions(exc, val, tb);
         return -1;
-    tstate->curexc_traceback = (PyObject *)tb;
-    Py_XDECREF(oldtb);
+    }
+    PyErr_Restore(exc, val, newtb);
+    Py_XDECREF(tb);
     return 0;
 }
 
 /* Insert a frame into the traceback for (funcname, filename, lineno). */
 void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
 {
-    PyObject *globals = NULL;
-    PyCodeObject *code = NULL;
-    PyFrameObject *frame = NULL;
-    PyObject *exception, *value, *tb;
+    PyObject *globals;
+    PyCodeObject *code;
+    PyFrameObject *frame;
+    PyObject *exc, *val, *tb;
 
     /* Save and clear the current exception. Python functions must not be
        called with an exception set. Calling Python functions happens when
        the codec of the filesystem encoding is implemented in pure Python. */
-    PyErr_Fetch(&exception, &value, &tb);
+    PyErr_Fetch(&exc, &val, &tb);
 
     globals = PyDict_New();
     if (!globals)
-        goto done;
+        goto error;
     code = PyCode_NewEmpty(filename, funcname, lineno);
-    if (!code)
-        goto done;
+    if (!code) {
+        Py_DECREF(globals);
+        goto error;
+    }
     frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
+    Py_DECREF(globals);
+    Py_DECREF(code);
     if (!frame)
-        goto done;
+        goto error;
     frame->f_lineno = lineno;
 
-    PyErr_Restore(exception, value, tb);
+    PyErr_Restore(exc, val, tb);
     PyTraceBack_Here(frame);
+    Py_DECREF(frame);
+    return;
 
-done:
-    Py_XDECREF(globals);
-    Py_XDECREF(code);
-    Py_XDECREF(frame);
+error:
+    _PyErr_ChainExceptions(exc, val, tb);
 }
 
 static PyObject *

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


More information about the Python-checkins mailing list