summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2016-10-18 10:23:18 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2016-10-18 10:23:18 (GMT)
commit04eb7772794a11bdb7ed7cd132adebb2ae527191 (patch)
tree0d1701ac0b6310593bd2f8a124c5c19056c509a3
parente5b0bd1ba2687a582bbb7e47580e6507ed2a9253 (diff)
downloadcpython-04eb7772794a11bdb7ed7cd132adebb2ae527191.zip
cpython-04eb7772794a11bdb7ed7cd132adebb2ae527191.tar.gz
cpython-04eb7772794a11bdb7ed7cd132adebb2ae527191.tar.bz2
Issue #23782: Fixed possible memory leak in _PyTraceback_Add() and exception
loss in PyTraceBack_Here().
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/traceback.c46
2 files changed, 29 insertions, 20 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 82cf8b0..2d50cf6 100644
--- 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.
diff --git a/Python/traceback.c b/Python/traceback.c
index 941d1cb..9e7fe3b 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -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 *