aboutsummaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-01-29 16:53:03 +0100
committerGitHub <noreply@github.com>2021-01-29 16:53:03 +0100
commita6192635f1e62af2bb8a435487ebb51800edd671 (patch)
treea1c012c74a7d78b53300300c217428710da5477b /Python
parentbpo-42990: Introduce 'frame constructor' struct to simplify API for PyEval_Co... (diff)
downloadcpython-a6192635f1e62af2bb8a435487ebb51800edd671.tar.gz
cpython-a6192635f1e62af2bb8a435487ebb51800edd671.tar.bz2
cpython-a6192635f1e62af2bb8a435487ebb51800edd671.zip
bpo-42979: Use _Py_CheckSlotResult() to check slots result (GH-24356)
When Python is built in debug mode (with C assertions), calling a type slot like sq_length (__len__() in Python) now fails with a fatal error if the slot succeeded with an exception set, or failed with no exception set. The error message contains the slot, the type name, and the current exception (if an exception is set). * Check the result of all slots using _Py_CheckSlotResult(). * No longer pass op_name to ternary_op() in release mode. * Replace operator with dunder Python method name in error messages. For example, replace "*" with "__mul__". * Fix compiler_exit_scope() when an exception is set. * Fix bytearray.extend() when an exception is set: don't call bytearray_setslice() with an exception set.
Diffstat (limited to 'Python')
-rw-r--r--Python/compile.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 223c63637ff..d8fea9d047d 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -667,25 +667,29 @@ compiler_enter_scope(struct compiler *c, identifier name,
static void
compiler_exit_scope(struct compiler *c)
{
- Py_ssize_t n;
- PyObject *capsule;
+ // Don't call PySequence_DelItem() with an exception raised
+ PyObject *exc_type, *exc_val, *exc_tb;
+ PyErr_Fetch(&exc_type, &exc_val, &exc_tb);
c->c_nestlevel--;
compiler_unit_free(c->u);
/* Restore c->u to the parent unit. */
- n = PyList_GET_SIZE(c->c_stack) - 1;
+ Py_ssize_t n = PyList_GET_SIZE(c->c_stack) - 1;
if (n >= 0) {
- capsule = PyList_GET_ITEM(c->c_stack, n);
+ PyObject *capsule = PyList_GET_ITEM(c->c_stack, n);
c->u = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
assert(c->u);
/* we are deleting from a list so this really shouldn't fail */
- if (PySequence_DelItem(c->c_stack, n) < 0)
- Py_FatalError("compiler_exit_scope()");
+ if (PySequence_DelItem(c->c_stack, n) < 0) {
+ Py_FatalError("PySequence_DelItem failed");
+ }
compiler_unit_check(c->u);
}
- else
+ else {
c->u = NULL;
+ }
+ PyErr_Restore(exc_type, exc_val, exc_tb);
}
static int