bpo-38631: Avoid Py_FatalError() in PyCode_New() (GH-18215)

intern_strings() now raises a SystemError, rather than calling
Py_FatalError().

intern_string_constants() now reports exceptions to the caller,
rather than ignoring silently exceptions.
This commit is contained in:
Victor Stinner 2020-01-27 23:24:13 +01:00 committed by GitHub
parent d3a1de2270
commit a278313518
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 46 additions and 26 deletions

View File

@ -38,7 +38,7 @@ all_name_chars(PyObject *o)
return 1; return 1;
} }
static void static int
intern_strings(PyObject *tuple) intern_strings(PyObject *tuple)
{ {
Py_ssize_t i; Py_ssize_t i;
@ -46,60 +46,70 @@ intern_strings(PyObject *tuple)
for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) { for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
PyObject *v = PyTuple_GET_ITEM(tuple, i); PyObject *v = PyTuple_GET_ITEM(tuple, i);
if (v == NULL || !PyUnicode_CheckExact(v)) { if (v == NULL || !PyUnicode_CheckExact(v)) {
Py_FatalError("non-string found in code slot"); PyErr_SetString(PyExc_SystemError,
"non-string found in code slot");
return -1;
} }
PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]); PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]);
} }
return 0;
} }
/* Intern selected string constants */ /* Intern selected string constants */
static int static int
intern_string_constants(PyObject *tuple) intern_string_constants(PyObject *tuple, int *modified)
{ {
int modified = 0; for (Py_ssize_t i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
Py_ssize_t i;
for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
PyObject *v = PyTuple_GET_ITEM(tuple, i); PyObject *v = PyTuple_GET_ITEM(tuple, i);
if (PyUnicode_CheckExact(v)) { if (PyUnicode_CheckExact(v)) {
if (PyUnicode_READY(v) == -1) { if (PyUnicode_READY(v) == -1) {
PyErr_Clear(); return -1;
continue;
} }
if (all_name_chars(v)) { if (all_name_chars(v)) {
PyObject *w = v; PyObject *w = v;
PyUnicode_InternInPlace(&v); PyUnicode_InternInPlace(&v);
if (w != v) { if (w != v) {
PyTuple_SET_ITEM(tuple, i, v); PyTuple_SET_ITEM(tuple, i, v);
modified = 1; if (modified) {
*modified = 1;
}
} }
} }
} }
else if (PyTuple_CheckExact(v)) { else if (PyTuple_CheckExact(v)) {
intern_string_constants(v); if (intern_string_constants(v, NULL) < 0) {
return -1;
}
} }
else if (PyFrozenSet_CheckExact(v)) { else if (PyFrozenSet_CheckExact(v)) {
PyObject *w = v; PyObject *w = v;
PyObject *tmp = PySequence_Tuple(v); PyObject *tmp = PySequence_Tuple(v);
if (tmp == NULL) { if (tmp == NULL) {
PyErr_Clear(); return -1;
continue;
} }
if (intern_string_constants(tmp)) { int tmp_modified = 0;
if (intern_string_constants(tmp, &tmp_modified) < 0) {
Py_DECREF(tmp);
return -1;
}
if (tmp_modified) {
v = PyFrozenSet_New(tmp); v = PyFrozenSet_New(tmp);
if (v == NULL) { if (v == NULL) {
PyErr_Clear(); Py_DECREF(tmp);
return -1;
} }
else {
PyTuple_SET_ITEM(tuple, i, v); PyTuple_SET_ITEM(tuple, i, v);
Py_DECREF(w); Py_DECREF(w);
modified = 1; if (modified) {
*modified = 1;
} }
} }
Py_DECREF(tmp); Py_DECREF(tmp);
} }
} }
return modified; return 0;
} }
PyCodeObject * PyCodeObject *
@ -139,11 +149,21 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
return NULL; return NULL;
} }
intern_strings(names); if (intern_strings(names) < 0) {
intern_strings(varnames); return NULL;
intern_strings(freevars); }
intern_strings(cellvars); if (intern_strings(varnames) < 0) {
intern_string_constants(consts); return NULL;
}
if (intern_strings(freevars) < 0) {
return NULL;
}
if (intern_strings(cellvars) < 0) {
return NULL;
}
if (intern_string_constants(consts, NULL) < 0) {
return NULL;
}
/* Check for any inner or outer closure references */ /* Check for any inner or outer closure references */
n_cellvars = PyTuple_GET_SIZE(cellvars); n_cellvars = PyTuple_GET_SIZE(cellvars);