diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2013-07-17 23:41:08 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2013-07-17 23:41:08 (GMT) |
commit | ace47d7efd2e2ab708fdc25936e9a8f85e08b6d3 (patch) | |
tree | 6493906040cfe23cb98638bdb712226479730ad7 /Python/ceval.c | |
parent | e9af4cfaced93ea9ec37bb448dd57b8c2014bdaf (diff) | |
download | cpython-ace47d7efd2e2ab708fdc25936e9a8f85e08b6d3.zip cpython-ace47d7efd2e2ab708fdc25936e9a8f85e08b6d3.tar.gz cpython-ace47d7efd2e2ab708fdc25936e9a8f85e08b6d3.tar.bz2 |
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.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 2d84c09..8a732a0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1203,6 +1203,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (throwflag) /* support for generator.throw() */ 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 (;;) { #ifdef WITH_TSC if (inst1 == 0) { @@ -1223,6 +1230,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #endif assert(stack_pointer >= f->f_valuestack); /* else underflow */ assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */ + assert(!PyErr_Occurred()); /* Do periodic things. Doing this every time through the loop would add too much overhead, so we do it @@ -3125,6 +3133,8 @@ fast_block_end: break; READ_TIMESTAMP(loop1); + assert(!PyErr_Occurred()); + } /* main loop */ assert(why != WHY_YIELD); @@ -3137,6 +3147,9 @@ fast_block_end: if (why != WHY_RETURN) retval = NULL; + assert((retval != NULL && !PyErr_Occurred()) + || (retval == NULL && PyErr_Occurred())); + fast_yield: 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 @@ -4044,6 +4057,13 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) { 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) { arg = PyTuple_New(0); if (arg == NULL) @@ -4066,6 +4086,9 @@ PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw) result = PyObject_Call(func, arg, kw); Py_DECREF(arg); + + assert((result != NULL && !PyErr_Occurred()) + || (result == NULL && PyErr_Occurred())); return result; } @@ -4228,6 +4251,9 @@ call_function(PyObject ***pp_stack, int oparg Py_DECREF(w); PCALL(PCALL_POP); } + + assert((x != NULL && !PyErr_Occurred()) + || (x == NULL && PyErr_Occurred())); return x; } |