Skip to content

Commit 74c8d5c

Browse files
[3.14] gh-151763: Fix OOM-0013 crash when the parser or compiler fails to allocate (GH-151968) (#152837)
1 parent 86e5a6e commit 74c8d5c

3 files changed

Lines changed: 17 additions & 1 deletion

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a potential crash in :func:`compile`, :func:`exec`, :func:`eval` and
2+
:func:`ast.parse` when an allocation fails: the parser or compiler could
3+
return without setting an exception.

Parser/pegen.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,11 @@ _PyPegen_run_parser(Parser *p)
949949
{
950950
void *res = _PyPegen_parse(p);
951951
assert(p->level == 0);
952+
if (res != NULL && PyErr_Occurred()) {
953+
// Discard a result returned with an exception still pending
954+
// (e.g. a MemoryError from a recovered-from allocation failure).
955+
return NULL;
956+
}
952957
if (res == NULL) {
953958
if ((p->flags & PyPARSE_ALLOW_INCOMPLETE_INPUT) && _is_end_of_source(p)) {
954959
PyErr_Clear();
@@ -1004,7 +1009,10 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena
10041009
if (tok == NULL) {
10051010
if (PyErr_Occurred()) {
10061011
_PyTokenizer_raise_init_error(filename_ob);
1007-
return NULL;
1012+
}
1013+
else {
1014+
// The only silent tokenizer init failure is a failed allocation.
1015+
PyErr_NoMemory();
10081016
}
10091017
return NULL;
10101018
}
@@ -1058,6 +1066,10 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
10581066
if (PyErr_Occurred()) {
10591067
_PyTokenizer_raise_init_error(filename_ob);
10601068
}
1069+
else {
1070+
// The only silent tokenizer init failure is a failed allocation.
1071+
PyErr_NoMemory();
1072+
}
10611073
return NULL;
10621074
}
10631075
// This transfers the ownership to the tokenizer

Python/compile.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
167167
{
168168
compiler *c = PyMem_Calloc(1, sizeof(compiler));
169169
if (c == NULL) {
170+
PyErr_NoMemory();
170171
return NULL;
171172
}
172173
if (compiler_setup(c, mod, filename, pflags, optimize, arena) < 0) {

0 commit comments

Comments
 (0)