Skip to content

Commit a278313

Browse files
authored
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.
1 parent d3a1de2 commit a278313

1 file changed

Lines changed: 46 additions & 26 deletions

File tree

Objects/codeobject.c

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,68 +38,78 @@ all_name_chars(PyObject *o)
3838
return 1;
3939
}
4040

41-
static void
41+
static int
4242
intern_strings(PyObject *tuple)
4343
{
4444
Py_ssize_t i;
4545

4646
for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
4747
PyObject *v = PyTuple_GET_ITEM(tuple, i);
4848
if (v == NULL || !PyUnicode_CheckExact(v)) {
49-
Py_FatalError("non-string found in code slot");
49+
PyErr_SetString(PyExc_SystemError,
50+
"non-string found in code slot");
51+
return -1;
5052
}
5153
PyUnicode_InternInPlace(&_PyTuple_ITEMS(tuple)[i]);
5254
}
55+
return 0;
5356
}
5457

5558
/* Intern selected string constants */
5659
static int
57-
intern_string_constants(PyObject *tuple)
60+
intern_string_constants(PyObject *tuple, int *modified)
5861
{
59-
int modified = 0;
60-
Py_ssize_t i;
61-
62-
for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
62+
for (Py_ssize_t i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
6363
PyObject *v = PyTuple_GET_ITEM(tuple, i);
6464
if (PyUnicode_CheckExact(v)) {
6565
if (PyUnicode_READY(v) == -1) {
66-
PyErr_Clear();
67-
continue;
66+
return -1;
6867
}
68+
6969
if (all_name_chars(v)) {
7070
PyObject *w = v;
7171
PyUnicode_InternInPlace(&v);
7272
if (w != v) {
7373
PyTuple_SET_ITEM(tuple, i, v);
74-
modified = 1;
74+
if (modified) {
75+
*modified = 1;
76+
}
7577
}
7678
}
7779
}
7880
else if (PyTuple_CheckExact(v)) {
79-
intern_string_constants(v);
81+
if (intern_string_constants(v, NULL) < 0) {
82+
return -1;
83+
}
8084
}
8185
else if (PyFrozenSet_CheckExact(v)) {
8286
PyObject *w = v;
8387
PyObject *tmp = PySequence_Tuple(v);
8488
if (tmp == NULL) {
85-
PyErr_Clear();
86-
continue;
89+
return -1;
8790
}
88-
if (intern_string_constants(tmp)) {
91+
int tmp_modified = 0;
92+
if (intern_string_constants(tmp, &tmp_modified) < 0) {
93+
Py_DECREF(tmp);
94+
return -1;
95+
}
96+
if (tmp_modified) {
8997
v = PyFrozenSet_New(tmp);
9098
if (v == NULL) {
91-
PyErr_Clear();
99+
Py_DECREF(tmp);
100+
return -1;
92101
}
93-
else {
94-
PyTuple_SET_ITEM(tuple, i, v);
95-
Py_DECREF(w);
96-
modified = 1;
102+
103+
PyTuple_SET_ITEM(tuple, i, v);
104+
Py_DECREF(w);
105+
if (modified) {
106+
*modified = 1;
97107
}
98108
}
99109
Py_DECREF(tmp);
100110
}
101111
}
102-
return modified;
112+
return 0;
103113
}
104114

105115
PyCodeObject *
@@ -139,11 +149,21 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
139149
return NULL;
140150
}
141151

142-
intern_strings(names);
143-
intern_strings(varnames);
144-
intern_strings(freevars);
145-
intern_strings(cellvars);
146-
intern_string_constants(consts);
152+
if (intern_strings(names) < 0) {
153+
return NULL;
154+
}
155+
if (intern_strings(varnames) < 0) {
156+
return NULL;
157+
}
158+
if (intern_strings(freevars) < 0) {
159+
return NULL;
160+
}
161+
if (intern_strings(cellvars) < 0) {
162+
return NULL;
163+
}
164+
if (intern_string_constants(consts, NULL) < 0) {
165+
return NULL;
166+
}
147167

148168
/* Check for any inner or outer closure references */
149169
n_cellvars = PyTuple_GET_SIZE(cellvars);
@@ -513,7 +533,7 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
513533
ourvarnames, ourfreevars,
514534
ourcellvars, filename,
515535
name, firstlineno, lnotab);
516-
cleanup:
536+
cleanup:
517537
Py_XDECREF(ournames);
518538
Py_XDECREF(ourvarnames);
519539
Py_XDECREF(ourfreevars);

0 commit comments

Comments
 (0)