Skip to content

Commit ba7a99d

Browse files
authored
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.
1 parent 7fdab83 commit ba7a99d

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Replace :c:func:`Py_FatalError` calls in the compiler with regular
2+
:exc:`SystemError` exceptions. Patch by Victor Stinner.

Python/compile.c

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
*/
2323

2424
#include "Python.h"
25+
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
2526
#include "pycore_long.h" // _PyLong_GetZero()
2627

2728
#include "Python-ast.h"
@@ -520,9 +521,7 @@ compiler_unit_check(struct compiler_unit *u)
520521
{
521522
basicblock *block;
522523
for (block = u->u_blocks; block != NULL; block = block->b_list) {
523-
assert((uintptr_t)block != 0xcbcbcbcbU);
524-
assert((uintptr_t)block != 0xfbfbfbfbU);
525-
assert((uintptr_t)block != 0xdbdbdbdbU);
524+
assert(!_PyMem_IsPtrFreed(block));
526525
if (block->b_instr != NULL) {
527526
assert(block->b_ialloc > 0);
528527
assert(block->b_iused >= 0);
@@ -681,7 +680,8 @@ compiler_exit_scope(struct compiler *c)
681680
assert(c->u);
682681
/* we are deleting from a list so this really shouldn't fail */
683682
if (PySequence_DelItem(c->c_stack, n) < 0) {
684-
Py_FatalError("PySequence_DelItem failed");
683+
_PyErr_WriteUnraisableMsg("on removing the last compiler "
684+
"stack item", NULL);
685685
}
686686
compiler_unit_check(c->u);
687687
}
@@ -1898,17 +1898,15 @@ get_ref_type(struct compiler *c, PyObject *name)
18981898
return CELL;
18991899
scope = PyST_GetScope(c->u->u_ste, name);
19001900
if (scope == 0) {
1901-
_Py_FatalErrorFormat(__func__,
1902-
"unknown scope for %.100s in %.100s(%s)\n"
1903-
"symbols: %s\nlocals: %s\nglobals: %s",
1904-
PyUnicode_AsUTF8(name),
1905-
PyUnicode_AsUTF8(c->u->u_name),
1906-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
1907-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
1908-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
1909-
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)));
1901+
PyErr_Format(PyExc_SystemError,
1902+
"PyST_GetScope(name=%R) failed: "
1903+
"unknown scope in unit %S (%R); "
1904+
"symbols: %R; locals: %R; globals: %R",
1905+
name,
1906+
c->u->u_name, c->u->u_ste->ste_id,
1907+
c->u->u_ste->ste_symbols, c->u->u_varnames, c->u->u_names);
1908+
return -1;
19101909
}
1911-
19121910
return scope;
19131911
}
19141912

@@ -1923,7 +1921,8 @@ compiler_lookup_arg(PyObject *dict, PyObject *name)
19231921
}
19241922

19251923
static int
1926-
compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, PyObject *qualname)
1924+
compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
1925+
PyObject *qualname)
19271926
{
19281927
Py_ssize_t i, free = PyCode_GetNumFree(co);
19291928
if (qualname == NULL)
@@ -1935,28 +1934,34 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
19351934
LOAD_DEREF but LOAD_CLOSURE is needed.
19361935
*/
19371936
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
1938-
int arg, reftype;
19391937

19401938
/* Special case: If a class contains a method with a
19411939
free variable that has the same name as a method,
19421940
the name will be considered free *and* local in the
19431941
class. It should be handled by the closure, as
19441942
well as by the normal name lookup logic.
19451943
*/
1946-
reftype = get_ref_type(c, name);
1947-
if (reftype == CELL)
1944+
int reftype = get_ref_type(c, name);
1945+
if (reftype == -1) {
1946+
return 0;
1947+
}
1948+
int arg;
1949+
if (reftype == CELL) {
19481950
arg = compiler_lookup_arg(c->u->u_cellvars, name);
1949-
else /* (reftype == FREE) */
1951+
}
1952+
else {
19501953
arg = compiler_lookup_arg(c->u->u_freevars, name);
1954+
}
19511955
if (arg == -1) {
1952-
_Py_FatalErrorFormat(__func__,
1953-
"lookup %s in %s %d %d\n"
1954-
"freevars of %s: %s\n",
1955-
PyUnicode_AsUTF8(PyObject_Repr(name)),
1956-
PyUnicode_AsUTF8(c->u->u_name),
1957-
reftype, arg,
1958-
PyUnicode_AsUTF8(co->co_name),
1959-
PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars)));
1956+
PyErr_Format(PyExc_SystemError,
1957+
"compiler_lookup_arg(name=%R) with reftype=%d failed in %S; "
1958+
"freevars of code %S: %R",
1959+
name,
1960+
reftype,
1961+
c->u->u_name,
1962+
co->co_name,
1963+
co->co_freevars);
1964+
return 0;
19601965
}
19611966
ADDOP_I(c, LOAD_CLOSURE, arg);
19621967
}
@@ -2294,7 +2299,11 @@ compiler_function(struct compiler *c, stmt_ty s, int is_async)
22942299
return 0;
22952300
}
22962301

2297-
compiler_make_closure(c, co, funcflags, qualname);
2302+
if (!compiler_make_closure(c, co, funcflags, qualname)) {
2303+
Py_DECREF(qualname);
2304+
Py_DECREF(co);
2305+
return 0;
2306+
}
22982307
Py_DECREF(qualname);
22992308
Py_DECREF(co);
23002309

@@ -2419,7 +2428,10 @@ compiler_class(struct compiler *c, stmt_ty s)
24192428
ADDOP(c, LOAD_BUILD_CLASS);
24202429

24212430
/* 3. load a function (or closure) made from the code object */
2422-
compiler_make_closure(c, co, 0, NULL);
2431+
if (!compiler_make_closure(c, co, 0, NULL)) {
2432+
Py_DECREF(co);
2433+
return 0;
2434+
}
24232435
Py_DECREF(co);
24242436

24252437
/* 4. load class name */
@@ -2697,7 +2709,11 @@ compiler_lambda(struct compiler *c, expr_ty e)
26972709
return 0;
26982710
}
26992711

2700-
compiler_make_closure(c, co, funcflags, qualname);
2712+
if (!compiler_make_closure(c, co, funcflags, qualname)) {
2713+
Py_DECREF(qualname);
2714+
Py_DECREF(co);
2715+
return 0;
2716+
}
27012717
Py_DECREF(qualname);
27022718
Py_DECREF(co);
27032719

@@ -4660,8 +4676,9 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
46604676
if (co == NULL)
46614677
goto error;
46624678

4663-
if (!compiler_make_closure(c, co, 0, qualname))
4679+
if (!compiler_make_closure(c, co, 0, qualname)) {
46644680
goto error;
4681+
}
46654682
Py_DECREF(qualname);
46664683
Py_DECREF(co);
46674684

@@ -5468,8 +5485,10 @@ stackdepth(struct compiler *c)
54685485
struct instr *instr = &b->b_instr[i];
54695486
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
54705487
if (effect == PY_INVALID_STACK_EFFECT) {
5471-
_Py_FatalErrorFormat(__func__,
5472-
"opcode = %d", instr->i_opcode);
5488+
PyErr_Format(PyExc_SystemError,
5489+
"compiler stack_effect(opcode=%d, arg=%i) failed",
5490+
instr->i_opcode, instr->i_oparg);
5491+
return -1;
54735492
}
54745493
int new_depth = depth + effect;
54755494
if (new_depth > maxdepth) {
@@ -6675,4 +6694,3 @@ PyCode_Optimize(PyObject *code, PyObject* Py_UNUSED(consts),
66756694
Py_INCREF(code);
66766695
return code;
66776696
}
6678-

0 commit comments

Comments
 (0)