]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 18 Oct 2016 10:23:18 +0000 (13:23 +0300)
committerSerhiy Storchaka <storchaka@gmail.com>
Tue, 18 Oct 2016 10:23:18 +0000 (13:23 +0300)
loss in PyTraceBack_Here().

Misc/NEWS
Python/traceback.c

index 82cf8b04a340538c8842b80a62853f23980387ab..2d50cf6ad53376a504ce3ea7e1d0bb134d794010 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ Release date: TBA
 Core and Builtins
 -----------------
 
+- Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
+  loss in PyTraceBack_Here().
+
 - Issue #28379: Added sanity checks and tests for PyUnicode_CopyCharacters().
   Patch by Xiang Zhang.
 
index 941d1cbbbb4afd739fb4232f262270f72de8af12..9e7fe3b5c61c904593b8b3d082b587fbe34b24c4 100644 (file)
@@ -132,47 +132,53 @@ newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
 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 *