summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2013-07-17 23:41:08 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2013-07-17 23:41:08 (GMT)
commitace47d7efd2e2ab708fdc25936e9a8f85e08b6d3 (patch)
tree6493906040cfe23cb98638bdb712226479730ad7 /Python/ceval.c
parente9af4cfaced93ea9ec37bb448dd57b8c2014bdaf (diff)
downloadcpython-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.c26
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;
}