mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
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.
This commit is contained in:
parent
7fdab8331b
commit
ba7a99ddb5
2 changed files with 54 additions and 34 deletions
|
@ -0,0 +1,2 @@
|
|||
Replace :c:func:`Py_FatalError` calls in the compiler with regular
|
||||
:exc:`SystemError` exceptions. Patch by Victor Stinner.
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue