Skip to content

Commit cdc1472

Browse files
authored
[3.13] gh-151763: Fix OOM-0013 crash when the parser or compiler fails to allocate (GH-151968) (#152840)
1 parent e5d70d9 commit cdc1472

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
@@ -894,6 +894,11 @@ _PyPegen_run_parser(Parser *p)
894894
{
895895
void *res = _PyPegen_parse(p);
896896
assert(p->level == 0);
897+
if (res != NULL && PyErr_Occurred()) {
898+
// Discard a result returned with an exception still pending
899+
// (e.g. a MemoryError from a recovered-from allocation failure).
900+
return NULL;
901+
}
897902
if (res == NULL) {
898903
if ((p->flags & PyPARSE_ALLOW_INCOMPLETE_INPUT) && _is_end_of_source(p)) {
899904
PyErr_Clear();
@@ -944,7 +949,10 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena
944949
if (tok == NULL) {
945950
if (PyErr_Occurred()) {
946951
_PyPegen_raise_tokenizer_init_error(filename_ob);
947-
return NULL;
952+
}
953+
else {
954+
// The only silent tokenizer init failure is a failed allocation.
955+
PyErr_NoMemory();
948956
}
949957
return NULL;
950958
}
@@ -998,6 +1006,10 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
9981006
if (PyErr_Occurred()) {
9991007
_PyPegen_raise_tokenizer_init_error(filename_ob);
10001008
}
1009+
else {
1010+
// The only silent tokenizer init failure is a failed allocation.
1011+
PyErr_NoMemory();
1012+
}
10011013
return NULL;
10021014
}
10031015
// This transfers the ownership to the tokenizer

Python/compile.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
430430
{
431431
struct compiler *c = PyMem_Calloc(1, sizeof(struct compiler));
432432
if (c == NULL) {
433+
PyErr_NoMemory();
433434
return NULL;
434435
}
435436
if (compiler_setup(c, mod, filename, pflags, optimize, arena) < 0) {

0 commit comments

Comments
 (0)