From 09668664af1fe3f828c20ffd859d3a7c08b0527f Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 10 Jun 2017 09:56:01 +0300 Subject: [PATCH 1/2] bpo-28994: Chain exceptions rather than dropping the old exception. --- Modules/_ctypes/callproc.c | 18 +++++++++++------- Objects/genobject.c | 16 +++++----------- Python/ceval.c | 31 +++++++------------------------ Python/traceback.c | 4 +--- 4 files changed, 24 insertions(+), 45 deletions(-) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 3a6ad86e87e79d..1189a1d9ad457f 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -924,14 +924,17 @@ void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...) va_list vargs; PyObject *tp, *v, *tb, *s, *cls_str, *msg_str; + PyErr_Fetch(&tp, &v, &tb); + assert(tp != NULL); + PyErr_NormalizeException(&tp, &v, &tb); + va_start(vargs, fmt); s = PyUnicode_FromFormatV(fmt, vargs); va_end(vargs); - if (!s) - return; + if (s == NULL) { + goto error; + } - PyErr_Fetch(&tp, &v, &tb); - PyErr_NormalizeException(&tp, &v, &tb); cls_str = PyObject_Str(tp); if (cls_str) { PyUnicode_AppendAndDel(&s, cls_str); @@ -950,10 +953,11 @@ void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...) if (s == NULL) goto error; PyErr_SetObject(exc_class, s); + Py_DECREF(s); + return; + error: - Py_XDECREF(tp); - Py_XDECREF(v); - Py_XDECREF(tb); + _PyErr_ChainExceptions(tp, v, tb); Py_XDECREF(s); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 7793a54fb3d682..ec9544af1b34df 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -284,17 +284,11 @@ gen_send_ex(PyGenObject *gen, PyObject *arg, int exc, int closing) /* Pop the exception before issuing a warning. */ PyErr_Fetch(&exc, &val, &tb); - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "generator '%.50S' raised StopIteration", - gen->gi_qualname)) { - /* Warning was converted to an error. */ - Py_XDECREF(exc); - Py_XDECREF(val); - Py_XDECREF(tb); - } - else { - PyErr_Restore(exc, val, tb); - } + (void)PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "generator '%.50S' raised StopIteration", + gen->gi_qualname); + /* Warning can be converted to an error. */ + _PyErr_ChainExceptions(exc, val, tb); } } else if (PyAsyncGen_CheckExact(gen) && !result && diff --git a/Python/ceval.c b/Python/ceval.c index f6519cff590fe1..dc17276632177d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4224,8 +4224,8 @@ call_exc_trace(Py_tracefunc func, PyObject *self, PyThreadState *tstate, PyFrameObject *f) { PyObject *type, *value, *traceback, *orig_traceback, *arg; - int err; PyErr_Fetch(&type, &value, &orig_traceback); + assert(type != NULL); if (value == NULL) { value = Py_None; Py_INCREF(value); @@ -4233,19 +4233,11 @@ call_exc_trace(Py_tracefunc func, PyObject *self, PyErr_NormalizeException(&type, &value, &orig_traceback); traceback = (orig_traceback != NULL) ? orig_traceback : Py_None; arg = PyTuple_Pack(3, type, value, traceback); - if (arg == NULL) { - PyErr_Restore(type, value, orig_traceback); - return; - } - err = call_trace(func, self, tstate, f, PyTrace_EXCEPTION, arg); - Py_DECREF(arg); - if (err == 0) - PyErr_Restore(type, value, orig_traceback); - else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(orig_traceback); + if (arg != NULL) { + (void)call_trace(func, self, tstate, f, PyTrace_EXCEPTION, arg); + Py_DECREF(arg); } + _PyErr_ChainExceptions(type, value, orig_traceback); } static int @@ -4257,17 +4249,8 @@ call_trace_protected(Py_tracefunc func, PyObject *obj, int err; PyErr_Fetch(&type, &value, &traceback); err = call_trace(func, obj, tstate, frame, what, arg); - if (err == 0) - { - PyErr_Restore(type, value, traceback); - return 0; - } - else { - Py_XDECREF(type); - Py_XDECREF(value); - Py_XDECREF(traceback); - return -1; - } + _PyErr_ChainExceptions(type, value, traceback); + return err; } static int diff --git a/Python/traceback.c b/Python/traceback.c index 21b36b1471935c..36094d95de9cef 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -495,9 +495,7 @@ PyTraceBack_Print(PyObject *v, PyObject *f) limit = PyTraceBack_LIMIT; } else { - Py_XDECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); + _PyErr_ChainExceptions(exc_type, exc_value, exc_tb); return 0; } } From d69a99622e1c5b515cca6bb9da8bbdf760606dec Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 6 Nov 2017 18:39:06 +0200 Subject: [PATCH 2/2] Withdraw changes in Python/traceback.c. --- Python/traceback.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Python/traceback.c b/Python/traceback.c index 36094d95de9cef..21b36b1471935c 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -495,7 +495,9 @@ PyTraceBack_Print(PyObject *v, PyObject *f) limit = PyTraceBack_LIMIT; } else { - _PyErr_ChainExceptions(exc_type, exc_value, exc_tb); + Py_XDECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); return 0; } }