Index: Python/errors.c =================================================================== --- Python/errors.c (revision 65931) +++ Python/errors.c (working copy) @@ -65,6 +65,11 @@ Py_XINCREF(value); if (tstate->exc_value != NULL && tstate->exc_value != Py_None) { /* Implicit exception chaining */ + + /* Save the current value, as code below may (incorrectly) modify it. */ + PyObject *exc_value = tstate->exc_value; + Py_INCREF(exc_value); + if (value == NULL || !PyExceptionInstance_Check(value)) { /* We must normalize the value right now */ PyObject *args, *fixed_value; @@ -88,8 +93,8 @@ This is O(chain length) but context chains are usually very short. Sensitive readers may try to inline the call to PyException_GetContext. */ - if (tstate->exc_value != value) { - PyObject *o = tstate->exc_value, *context; + if (exc_value != value) { + PyObject *o = exc_value, *context; while ((context = PyException_GetContext(o))) { Py_DECREF(context); if (context == value) { @@ -98,9 +103,12 @@ } o = context; } - Py_INCREF(tstate->exc_value); - PyException_SetContext(value, tstate->exc_value); + /* This will steal our reference to exc_value */ + PyException_SetContext(value, exc_value); } + else { + Py_DECREF(exc_value); + } } if (value != NULL && PyExceptionInstance_Check(value)) tb = PyException_GetTraceback(value);