aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-01-30 01:46:44 +0100
committerGitHub <noreply@github.com>2021-01-30 01:46:44 +0100
commitba7a99ddb52a45c8dec1f7e9f1648add0ace82ab (patch)
tree5a7b09325e6c2038ecc0a67e9354baf3ad7bc044
parentFix a reference leak in the compiler for compiler_lambda() (GH-24382) (diff)
downloadcpython-ba7a99ddb52a45c8dec1f7e9f1648add0ace82ab.tar.gz
cpython-ba7a99ddb52a45c8dec1f7e9f1648add0ace82ab.tar.bz2
cpython-ba7a99ddb52a45c8dec1f7e9f1648add0ace82ab.zip
bpo-38631: Replace compiler fatal errors with exceptions (GH-24369)
* Replace Py_FatalError() calls with regular SystemError exceptions. * compiler_exit_scope() calls _PyErr_WriteUnraisableMsg() to log the PySequence_DelItem() failure. * compiler_unit_check() uses _PyMem_IsPtrFreed(). * compiler_make_closure(): remove "(reftype == FREE)" comment since reftype can also be LOCAL or GLOBAL_EXPLICIT.
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-01-29-17-48-44.bpo-38631.jR-3kC.rst2
-rw-r--r--Python/compile.c86
2 files changed, 54 insertions, 34 deletions
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-01-29-17-48-44.bpo-38631.jR-3kC.rst b/Misc/NEWS.d/next/Core and Builtins/2021-01-29-17-48-44.bpo-38631.jR-3kC.rst
new file mode 100644
index 00000000000..485607e6612
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-01-29-17-48-44.bpo-38631.jR-3kC.rst
@@ -0,0 +1,2 @@
+Replace :c:func:`Py_FatalError` calls in the compiler with regular
+:exc:`SystemError` exceptions. Patch by Victor Stinner.
diff --git a/Python/compile.c b/Python/compile.c
index 5d06a8342d3..8abb5bb5dc6 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -22,6 +22,7 @@
*/
#include "Python.h"
+#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
#include "pycore_long.h" // _PyLong_GetZero()
#include "Python-ast.h"
@@ -520,9 +521,7 @@ compiler_unit_check(struct compiler_unit *u)
{
basicblock *block;
for (block = u->u_blocks; block != NULL; block = block->b_list) {
- assert((uintptr_t)block != 0xcbcbcbcbU);
- assert((uintptr_t)block != 0xfbfbfbfbU);
- assert((uintptr_t)block != 0xdbdbdbdbU);
+ assert(!_PyMem_IsPtrFreed(block));
if (block->b_instr != NULL) {
assert(block->b_ialloc > 0);
assert(block->b_iused >= 0);
@@ -681,7 +680,8 @@ compiler_exit_scope(struct compiler *c)
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("PySequence_DelItem failed");
+ _PyErr_WriteUnraisableMsg("on removing the last compiler "
+ "stack item", NULL);
}
compiler_unit_check(c->u);
}
@@ -1898,17 +1898,15 @@ get_ref_type(struct compiler *c, PyObject *name)
return CELL;
scope = PyST_GetScope(c->u->u_ste, name);
if (scope == 0) {
- _Py_FatalErrorFormat(__func__,
- "unknown scope for %.100s in %.100s(%s)\n"
- "symbols: %s\nlocals: %s\nglobals: %s",
- PyUnicode_AsUTF8(name),
- PyUnicode_AsUTF8(c->u->u_name),
- PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
- PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
- PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
- PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)));
+ PyErr_Format(PyExc_SystemError,
+ "PyST_GetScope(name=%R) failed: "
+ "unknown scope in unit %S (%R); "
+ "symbols: %R; locals: %R; globals: %R",
+ name,
+ c->u->u_name, c->u->u_ste->ste_id,
+ c->u->u_ste->ste_symbols, c->u->u_varnames, c->u->u_names);
+ return -1;
}
-
return scope;
}
@@ -1923,7 +1921,8 @@ compiler_lookup_arg(PyObject *dict, PyObject *name)
}
static int
-compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, PyObject *qualname)
+compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
+ PyObject *qualname)
{
Py_ssize_t i, free = PyCode_GetNumFree(co);
if (qualname == NULL)
@@ -1935,7 +1934,6 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
- int arg, reftype;
/* Special case: If a class contains a method with a
free variable that has the same name as a method,
@@ -1943,20 +1941,27 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
class. It should be handled by the closure, as
well as by the normal name lookup logic.
*/
- reftype = get_ref_type(c, name);
- if (reftype == CELL)
+ int reftype = get_ref_type(c, name);
+ if (reftype == -1) {
+ return 0;
+ }
+ int arg;
+ if (reftype == CELL) {
arg = compiler_lookup_arg(c->u->u_cellvars, name);
- else /* (reftype == FREE) */
+ }
+ else {
arg = compiler_lookup_arg(c->u->u_freevars, name);
+ }
if (arg == -1) {
- _Py_FatalErrorFormat(__func__,
- "lookup %s in %s %d %d\n"
- "freevars of %s: %s\n",
- PyUnicode_AsUTF8(PyObject_Repr(name)),
- PyUnicode_AsUTF8(c->u->u_name),
- reftype, arg,
- PyUnicode_AsUTF8(co->co_name),
- PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars)));
+ PyErr_Format(PyExc_SystemError,
+ "compiler_lookup_arg(name=%R) with reftype=%d failed in %S; "
+ "freevars of code %S: %R",
+ name,
+ reftype,
+ c->u->u_name,
+ co->co_name,
+ co->co_freevars);
+ return 0;
}
ADDOP_I(c, LOAD_CLOSURE, arg);
}
@@ -2294,7 +2299,11 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
return 0;
}
- compiler_make_closure(c, co, funcflags, qualname);
+ if (!compiler_make_closure(c, co, funcflags, qualname)) {
+ Py_DECREF(qualname);
+ Py_DECREF(co);
+ return 0;
+ }
Py_DECREF(qualname);
Py_DECREF(co);
@@ -2419,7 +2428,10 @@ compiler_class(struct compiler *c, stmt_ty s)
ADDOP(c, LOAD_BUILD_CLASS);
/* 3. load a function (or closure) made from the code object */
- compiler_make_closure(c, co, 0, NULL);
+ if (!compiler_make_closure(c, co, 0, NULL)) {
+ Py_DECREF(co);
+ return 0;
+ }
Py_DECREF(co);
/* 4. load class name */
@@ -2697,7 +2709,11 @@ compiler_lambda(struct compiler *c, expr_ty e)
return 0;
}
- compiler_make_closure(c, co, funcflags, qualname);
+ if (!compiler_make_closure(c, co, funcflags, qualname)) {
+ Py_DECREF(qualname);
+ Py_DECREF(co);
+ return 0;
+ }
Py_DECREF(qualname);
Py_DECREF(co);
@@ -4660,8 +4676,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
if (co == NULL)
goto error;
- if (!compiler_make_closure(c, co, 0, qualname))
+ if (!compiler_make_closure(c, co, 0, qualname)) {
goto error;
+ }
Py_DECREF(qualname);
Py_DECREF(co);
@@ -5468,8 +5485,10 @@ stackdepth(struct compiler *c)
struct instr *instr = &b->b_instr[i];
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
if (effect == PY_INVALID_STACK_EFFECT) {
- _Py_FatalErrorFormat(__func__,
- "opcode = %d", instr->i_opcode);
+ PyErr_Format(PyExc_SystemError,
+ "compiler stack_effect(opcode=%d, arg=%i) failed",
+ instr->i_opcode, instr->i_oparg);
+ return -1;
}
int new_depth = depth + effect;
if (new_depth > maxdepth) {
@@ -6675,4 +6694,3 @@ PyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts),
Py_INCREF(code);
return code;
}
-