Skip to content

Commit 669299b

Browse files
authored
gh-151763: Fix OOM-0013 crash when the parser or compiler fails to allocate (#151968)
1 parent be449b1 commit 669299b

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
@@ -940,6 +940,11 @@ _PyPegen_run_parser(Parser *p)
940940
{
941941
void *res = _PyPegen_parse(p);
942942
assert(p->level == 0);
943+
if (res != NULL && PyErr_Occurred()) {
944+
// Discard a result returned with an exception still pending
945+
// (e.g. a MemoryError from a recovered-from allocation failure).
946+
return NULL;
947+
}
943948
if (res == NULL) {
944949
if ((p->flags & PyPARSE_ALLOW_INCOMPLETE_INPUT) && _is_end_of_source(p)) {
945950
PyErr_Clear();
@@ -995,7 +1000,10 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena
9951000
if (tok == NULL) {
9961001
if (PyErr_Occurred()) {
9971002
_PyTokenizer_raise_init_error(filename_ob);
998-
return NULL;
1003+
}
1004+
else {
1005+
// The only silent tokenizer init failure is a failed allocation.
1006+
PyErr_NoMemory();
9991007
}
10001008
return NULL;
10011009
}
@@ -1054,6 +1062,10 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
10541062
if (PyErr_Occurred()) {
10551063
_PyTokenizer_raise_init_error(filename_ob);
10561064
}
1065+
else {
1066+
// The only silent tokenizer init failure is a failed allocation.
1067+
PyErr_NoMemory();
1068+
}
10571069
return NULL;
10581070
}
10591071
// This transfers the ownership to the tokenizer

Python/compile.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
174174
{
175175
compiler *c = PyMem_Calloc(1, sizeof(compiler));
176176
if (c == NULL) {
177+
PyErr_NoMemory();
177178
return NULL;
178179
}
179180
if (compiler_setup(c, mod, filename, pflags, optimize, arena, module) < 0) {

0 commit comments

Comments
 (0)