diff -r 16ea07d420b8 Lib/ctypes/test/test_structures.py
--- a/Lib/ctypes/test/test_structures.py Fri Oct 28 12:17:17 2016 +0300
+++ b/Lib/ctypes/test/test_structures.py Fri Oct 28 12:37:10 2016 +0300
@@ -321,13 +321,13 @@ class StructureTestCase(unittest.TestCas
cls, msg = self.get_except(Person, b"Someone", (1, 2))
self.assertEqual(cls, RuntimeError)
self.assertEqual(msg,
- "(Phone) : "
+ "(Phone) TypeError: "
"expected bytes, int found")
cls, msg = self.get_except(Person, b"Someone", (b"a", b"b", b"c"))
self.assertEqual(cls, RuntimeError)
self.assertEqual(msg,
- "(Phone) : too many initializers")
+ "(Phone) TypeError: too many initializers")
def test_huge_field_name(self):
# issue12881: segfault with large structure field names
diff -r 16ea07d420b8 Modules/_ctypes/callproc.c
--- a/Modules/_ctypes/callproc.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Modules/_ctypes/callproc.c Fri Oct 28 12:37:10 2016 +0300
@@ -929,24 +929,22 @@ static PyObject *GetResult(PyObject *res
void _ctypes_extend_error(PyObject *exc_class, const char *fmt, ...)
{
va_list vargs;
- PyObject *tp, *v, *tb, *s, *cls_str, *msg_str;
+ PyObject *tp, *v, *tb, *s, *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);
- PyUnicode_AppendAndDel(&s, PyUnicode_FromString(": "));
- if (s == NULL)
- goto error;
- } else
- PyErr_Clear();
+ Py_SETREF(s, PyUnicode_FromFormat("%U%.200s: ",
+ s, ((PyTypeObject*)tp)->tp_name));
+ if (s == NULL)
+ goto error;
msg_str = PyObject_Str(v);
if (msg_str)
PyUnicode_AppendAndDel(&s, msg_str);
@@ -957,11 +955,9 @@ void _ctypes_extend_error(PyObject *exc_
if (s == NULL)
goto error;
PyErr_SetObject(exc_class, s);
+ return;
error:
- Py_XDECREF(tp);
- Py_XDECREF(v);
- Py_XDECREF(tb);
- Py_XDECREF(s);
+ _PyErr_ChainExceptions(tp, v, tb);
}
diff -r 16ea07d420b8 Modules/atexitmodule.c
--- a/Modules/atexitmodule.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Modules/atexitmodule.c Fri Oct 28 12:37:10 2016 +0300
@@ -97,7 +97,7 @@ atexit_callfuncs(void)
Py_XDECREF(exc_tb);
}
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
- if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
+ if (!PyErr_GivenExceptionMatches(exc_type, PyExc_SystemExit)) {
PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
PyErr_Display(exc_type, exc_value, exc_tb);
diff -r 16ea07d420b8 Objects/exceptions.c
--- a/Objects/exceptions.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Objects/exceptions.c Fri Oct 28 12:37:10 2016 +0300
@@ -2784,7 +2784,7 @@ PyObject *
return NULL;
}
- PyErr_Format(exc, "%U (%s: %S)",
+ PyErr_Format(exc, "%U (%.100s: %S)",
msg_prefix, Py_TYPE(val)->tp_name, val);
Py_DECREF(exc);
Py_DECREF(msg_prefix);
diff -r 16ea07d420b8 Objects/genobject.c
--- a/Objects/genobject.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Objects/genobject.c Fri Oct 28 12:37:10 2016 +0300
@@ -265,9 +265,7 @@ gen_send_ex(PyGenObject *gen, PyObject *
"generator '%.50S' raised StopIteration",
gen->gi_qualname)) {
/* Warning was converted to an error. */
- Py_XDECREF(exc);
- Py_XDECREF(val);
- Py_XDECREF(tb);
+ _PyErr_ChainExceptions(exc, val, tb);
}
else {
PyErr_Restore(exc, val, tb);
@@ -597,8 +595,8 @@ int
Py_INCREF(value);
Py_DECREF(ev);
}
+ Py_DECREF(et);
}
- Py_XDECREF(et);
Py_XDECREF(tb);
} else if (PyErr_Occurred()) {
return -1;
diff -r 16ea07d420b8 Python/ceval.c
--- a/Python/ceval.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Python/ceval.c Fri Oct 28 12:37:10 2016 +0300
@@ -4422,6 +4422,7 @@ call_exc_trace(Py_tracefunc func, PyObje
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);
@@ -4437,11 +4438,8 @@ call_exc_trace(Py_tracefunc func, PyObje
Py_DECREF(arg);
if (err == 0)
PyErr_Restore(type, value, orig_traceback);
- else {
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(orig_traceback);
- }
+ else
+ _PyErr_ChainExceptions(type, value, orig_traceback);
}
static int
@@ -4459,9 +4457,7 @@ call_trace_protected(Py_tracefunc func,
return 0;
}
else {
- Py_XDECREF(type);
- Py_XDECREF(value);
- Py_XDECREF(traceback);
+ _PyErr_ChainExceptions(type, value, traceback);
return -1;
}
}
diff -r 16ea07d420b8 Python/errors.c
--- a/Python/errors.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Python/errors.c Fri Oct 28 12:37:10 2016 +0300
@@ -37,6 +37,13 @@ PyErr_Restore(PyObject *type, PyObject *
traceback = NULL;
}
+#ifdef Py_DEBUG
+ if (type == NULL) {
+ assert(value == NULL);
+ assert(traceback == NULL);
+ }
+#endif
+
/* Save these in locals to safeguard against recursive
invocation through Py_XDECREF */
oldtype = tstate->curexc_type;
@@ -226,17 +233,18 @@ PyErr_ExceptionMatches(PyObject *exc)
void
PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
{
- PyObject *type = *exc;
- PyObject *value = *val;
- PyObject *inclass = NULL;
- PyObject *initial_tb = NULL;
- PyThreadState *tstate = NULL;
+ int recursion_depth = 0;
+ PyObject *type, *value, *initial_tb;
+ PyThreadState *tstate;
+restart:
+ type = *exc;
if (type == NULL) {
/* There was no exception, so nothing to do. */
return;
}
+ value = *val;
/* If PyErr_SetNone() was used, the value will have been actually
set to NULL.
*/
@@ -245,14 +253,18 @@ PyErr_NormalizeException(PyObject **exc,
Py_INCREF(value);
}
- if (PyExceptionInstance_Check(value))
- inclass = PyExceptionInstance_Class(value);
-
/* Normalize the exception so that if the type is a class, the
value will be an instance.
*/
if (PyExceptionClass_Check(type)) {
+ PyObject *inclass;
int is_subclass;
+
+ if (PyExceptionInstance_Check(value))
+ inclass = PyExceptionInstance_Class(value);
+ else
+ inclass = NULL;
+
if (inclass) {
is_subclass = PyObject_IsSubclass(inclass, type);
if (is_subclass < 0)
@@ -266,7 +278,7 @@ PyErr_NormalizeException(PyObject **exc,
value as an argument to instantiation of the type
class.
*/
- if (!inclass || !is_subclass) {
+ if (!is_subclass) {
PyObject *fixed_value;
fixed_value = _PyErr_CreateException(type, value);
@@ -289,6 +301,7 @@ PyErr_NormalizeException(PyObject **exc,
*exc = type;
*val = value;
return;
+
finally:
Py_DECREF(type);
Py_DECREF(value);
@@ -298,6 +311,7 @@ finally:
*/
initial_tb = *tb;
PyErr_Fetch(exc, val, tb);
+ assert(*exc != NULL);
if (initial_tb != NULL) {
if (*tb == NULL)
*tb = initial_tb;
@@ -306,18 +320,17 @@ finally:
}
/* normalize recursively */
tstate = PyThreadState_GET();
- if (++tstate->recursion_depth > Py_GetRecursionLimit()) {
- --tstate->recursion_depth;
+ if (++recursion_depth > Py_GetRecursionLimit() - tstate->recursion_depth) {
/* throw away the old exception and use the recursion error instead */
Py_INCREF(PyExc_RecursionError);
Py_SETREF(*exc, PyExc_RecursionError);
Py_INCREF(PyExc_RecursionErrorInst);
- Py_SETREF(*val, PyExc_RecursionErrorInst);
+ Py_XSETREF(*val, PyExc_RecursionErrorInst);
/* just keeping the old traceback */
return;
}
- PyErr_NormalizeException(exc, val, tb);
- --tstate->recursion_depth;
+ /* eliminate tail recursion */
+ goto restart;
}
@@ -333,6 +346,13 @@ PyErr_Fetch(PyObject **p_type, PyObject
tstate->curexc_type = NULL;
tstate->curexc_value = NULL;
tstate->curexc_traceback = NULL;
+
+#ifdef Py_DEBUG
+ if (*p_type == NULL) {
+ assert(*p_value == NULL);
+ assert(*p_traceback == NULL);
+ }
+#endif
}
void
diff -r 16ea07d420b8 Python/pylifecycle.c
--- a/Python/pylifecycle.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Python/pylifecycle.c Fri Oct 28 12:37:10 2016 +0300
@@ -1378,14 +1378,16 @@ static int
PyException_SetTraceback(v, tb);
if (exception == NULL) {
/* PyErr_NormalizeException() failed */
+ Py_XDECREF(v);
+ Py_DECREF(tb);
return 0;
}
has_tb = (tb != Py_None);
PyErr_Display(exception, v, tb);
- Py_XDECREF(exception);
- Py_XDECREF(v);
- Py_XDECREF(tb);
+ Py_DECREF(exception);
+ Py_DECREF(v);
+ Py_DECREF(tb);
/* sys.stderr may be buffered: call sys.stderr.flush() */
res = _PyObject_CallMethodId(ferr, &PyId_flush, NULL);
diff -r 16ea07d420b8 Python/pythonrun.c
--- a/Python/pythonrun.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Python/pythonrun.c Fri Oct 28 12:37:10 2016 +0300
@@ -620,8 +620,7 @@ PyErr_PrintEx(int set_sys_last_vars)
Py_INCREF(tb);
}
PyException_SetTraceback(v, tb);
- if (exception == NULL)
- return;
+ assert(exception != NULL);
/* Now we know v != NULL too */
if (set_sys_last_vars) {
_PySys_SetObjectId(&PyId_last_type, exception);
@@ -630,13 +629,8 @@ PyErr_PrintEx(int set_sys_last_vars)
}
hook = _PySys_GetObjectId(&PyId_excepthook);
if (hook) {
- PyObject* stack[3];
- PyObject *result;
-
- stack[0] = exception;
- stack[1] = v;
- stack[2] = tb;
- result = _PyObject_FastCall(hook, stack, 3);
+ PyObject *stack[3] = {exception, v, tb};
+ PyObject *result = _PyObject_FastCall(hook, stack, 3);
if (result == NULL) {
PyObject *exception2, *v2, *tb2;
if (PyErr_ExceptionMatches(PyExc_SystemExit)) {
@@ -663,15 +657,15 @@ PyErr_PrintEx(int set_sys_last_vars)
Py_DECREF(exception2);
Py_DECREF(v2);
Py_XDECREF(tb2);
+ Py_DECREF(result);
}
- Py_XDECREF(result);
} else {
PySys_WriteStderr("sys.excepthook is missing\n");
PyErr_Display(exception, v, tb);
}
- Py_XDECREF(exception);
- Py_XDECREF(v);
- Py_XDECREF(tb);
+ Py_DECREF(exception);
+ Py_DECREF(v);
+ Py_DECREF(tb);
}
static void
diff -r 16ea07d420b8 Python/traceback.c
--- a/Python/traceback.c Fri Oct 28 12:17:17 2016 +0300
+++ b/Python/traceback.c Fri Oct 28 12:37:10 2016 +0300
@@ -485,22 +485,16 @@ PyTraceBack_Print(PyObject *v, PyObject
}
limitv = PySys_GetObject("tracebacklimit");
if (limitv) {
+ int overflow;
PyObject *exc_type, *exc_value, *exc_tb;
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
- limit = PyLong_AsLong(limitv);
+ limit = PyLong_AsLongAndOverflow(limitv, &overflow);
if (limit == -1 && PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
- limit = PyTraceBack_LIMIT;
- }
- else {
- Py_XDECREF(exc_type);
- Py_XDECREF(exc_value);
- Py_XDECREF(exc_tb);
- return 0;
- }
+ _PyErr_ChainExceptions(exc_type, exc_value, exc_tb);
+ return 0;
}
- else if (limit <= 0) {
+ else if (limit <= 0) { /* negative or overflows */
limit = PyTraceBack_LIMIT;
}
PyErr_Restore(exc_type, exc_value, exc_tb);