Issue #18408: PyEval_EvalFrameEx() and PyEval_CallObjectWithKeywords() now fail
with an assertion error if they are called with an exception set (PyErr_Occurred()). If these functions are called with an exception set, the exception may be cleared and so the caller looses its exception. Add also assertions to PyEval_CallObjectWithKeywords() and call_function() to check if the function succeed with no exception set, or the function failed with an exception set.
This commit is contained in:
parent
e9af4cface
commit
ace47d7efd
@ -663,6 +663,11 @@ static void
|
|||||||
_set_BlockingIOError(char *msg, Py_ssize_t written)
|
_set_BlockingIOError(char *msg, Py_ssize_t written)
|
||||||
{
|
{
|
||||||
PyObject *err;
|
PyObject *err;
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* in debug mode, PyEval_EvalFrameEx() fails with an assertion error
|
||||||
|
if an exception is set when it is called */
|
||||||
|
PyErr_Clear();
|
||||||
|
#endif
|
||||||
err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
|
err = PyObject_CallFunction(PyExc_BlockingIOError, "isn",
|
||||||
errno, msg, written);
|
errno, msg, written);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -1203,6 +1203,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||||||
if (throwflag) /* support for generator.throw() */
|
if (throwflag) /* support for generator.throw() */
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* PyEval_EvalFrameEx() must not be called with an exception set,
|
||||||
|
because it may clear it (directly or indirectly) and so the
|
||||||
|
caller looses its exception */
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
#endif
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
#ifdef WITH_TSC
|
#ifdef WITH_TSC
|
||||||
if (inst1 == 0) {
|
if (inst1 == 0) {
|
||||||
@ -1223,6 +1230,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||||||
#endif
|
#endif
|
||||||
assert(stack_pointer >= f->f_valuestack); /* else underflow */
|
assert(stack_pointer >= f->f_valuestack); /* else underflow */
|
||||||
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
|
assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
|
||||||
/* Do periodic things. Doing this every time through
|
/* Do periodic things. Doing this every time through
|
||||||
the loop would add too much overhead, so we do it
|
the loop would add too much overhead, so we do it
|
||||||
@ -3125,6 +3133,8 @@ fast_block_end:
|
|||||||
break;
|
break;
|
||||||
READ_TIMESTAMP(loop1);
|
READ_TIMESTAMP(loop1);
|
||||||
|
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
|
||||||
} /* main loop */
|
} /* main loop */
|
||||||
|
|
||||||
assert(why != WHY_YIELD);
|
assert(why != WHY_YIELD);
|
||||||
@ -3137,6 +3147,9 @@ fast_block_end:
|
|||||||
if (why != WHY_RETURN)
|
if (why != WHY_RETURN)
|
||||||
retval = NULL;
|
retval = NULL;
|
||||||
|
|
||||||
|
assert((retval != NULL && !PyErr_Occurred())
|
||||||
|
|| (retval == NULL && PyErr_Occurred()));
|
||||||
|
|
||||||
fast_yield:
|
fast_yield:
|
||||||
if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) {
|
if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) {
|
||||||
/* The purpose of this block is to put aside the generator's exception
|
/* The purpose of this block is to put aside the generator's exception
|
||||||
@ -4044,6 +4057,13 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
|
|||||||
{
|
{
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* PyEval_CallObjectWithKeywords() must not be called with an exception
|
||||||
|
set, because it may clear it (directly or indirectly)
|
||||||
|
and so the caller looses its exception */
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (arg == NULL) {
|
if (arg == NULL) {
|
||||||
arg = PyTuple_New(0);
|
arg = PyTuple_New(0);
|
||||||
if (arg == NULL)
|
if (arg == NULL)
|
||||||
@ -4066,6 +4086,9 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
|
|||||||
|
|
||||||
result = PyObject_Call(func, arg, kw);
|
result = PyObject_Call(func, arg, kw);
|
||||||
Py_DECREF(arg);
|
Py_DECREF(arg);
|
||||||
|
|
||||||
|
assert((result != NULL && !PyErr_Occurred())
|
||||||
|
|| (result == NULL && PyErr_Occurred()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4228,6 +4251,9 @@ call_function(PyObject ***pp_stack, int oparg
|
|||||||
Py_DECREF(w);
|
Py_DECREF(w);
|
||||||
PCALL(PCALL_POP);
|
PCALL(PCALL_POP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert((x != NULL && !PyErr_Occurred())
|
||||||
|
|| (x == NULL && PyErr_Occurred()));
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,11 @@ PyErr_SetObject(PyObject *exception, PyObject *value)
|
|||||||
if (value == NULL || !PyExceptionInstance_Check(value)) {
|
if (value == NULL || !PyExceptionInstance_Check(value)) {
|
||||||
/* We must normalize the value right now */
|
/* We must normalize the value right now */
|
||||||
PyObject *args, *fixed_value;
|
PyObject *args, *fixed_value;
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* in debug mode, PyEval_EvalFrameEx() fails with an assertion
|
||||||
|
error if an exception is set when it is called */
|
||||||
|
PyErr_Clear();
|
||||||
|
#endif
|
||||||
if (value == NULL || value == Py_None)
|
if (value == NULL || value == Py_None)
|
||||||
args = PyTuple_New(0);
|
args = PyTuple_New(0);
|
||||||
else if (PyTuple_Check(value)) {
|
else if (PyTuple_Check(value)) {
|
||||||
@ -707,6 +712,12 @@ PyErr_Format(PyObject *exception, const char *format, ...)
|
|||||||
va_start(vargs);
|
va_start(vargs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Py_DEBUG
|
||||||
|
/* in debug mode, PyEval_EvalFrameEx() fails with an assertion error
|
||||||
|
if an exception is set when it is called */
|
||||||
|
PyErr_Clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
string = PyUnicode_FromFormatV(format, vargs);
|
string = PyUnicode_FromFormatV(format, vargs);
|
||||||
PyErr_SetObject(exception, string);
|
PyErr_SetObject(exception, string);
|
||||||
Py_XDECREF(string);
|
Py_XDECREF(string);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user