]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-151763: Fix OOM-0013 crash when the parser or compiler fails to allocate (#151968)
authortonghuaroot (童话) <tonghuaroot@gmail.com>
Thu, 2 Jul 2026 00:34:16 +0000 (08:34 +0800)
committerGitHub <noreply@github.com>
Thu, 2 Jul 2026 00:34:16 +0000 (01:34 +0100)
Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-12-03-55.gh-issue-151763.K7QfWG.rst [new file with mode: 0644]
Parser/pegen.c
Python/compile.c

diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-12-03-55.gh-issue-151763.K7QfWG.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-23-12-03-55.gh-issue-151763.K7QfWG.rst
new file mode 100644 (file)
index 0000000..64d0146
--- /dev/null
@@ -0,0 +1,3 @@
+Fix a potential crash in :func:`compile`, :func:`exec`, :func:`eval` and
+:func:`ast.parse` when an allocation fails: the parser or compiler could
+return without setting an exception.
index bb222b50fc095f20b8cc96b605c6c7d7a575dca6..165dcb9f9950955ee898e8b11de42b4e060e2fa9 100644 (file)
@@ -940,6 +940,11 @@ _PyPegen_run_parser(Parser *p)
 {
     void *res = _PyPegen_parse(p);
     assert(p->level == 0);
+    if (res != NULL && PyErr_Occurred()) {
+        // Discard a result returned with an exception still pending
+        // (e.g. a MemoryError from a recovered-from allocation failure).
+        return NULL;
+    }
     if (res == NULL) {
         if ((p->flags & PyPARSE_ALLOW_INCOMPLETE_INPUT) &&  _is_end_of_source(p)) {
             PyErr_Clear();
@@ -995,7 +1000,10 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena
     if (tok == NULL) {
         if (PyErr_Occurred()) {
             _PyTokenizer_raise_init_error(filename_ob);
-            return NULL;
+        }
+        else {
+            // The only silent tokenizer init failure is a failed allocation.
+            PyErr_NoMemory();
         }
         return NULL;
     }
@@ -1054,6 +1062,10 @@ _PyPegen_run_parser_from_string(const char *str, int start_rule, PyObject *filen
         if (PyErr_Occurred()) {
             _PyTokenizer_raise_init_error(filename_ob);
         }
+        else {
+            // The only silent tokenizer init failure is a failed allocation.
+            PyErr_NoMemory();
+        }
         return NULL;
     }
     // This transfers the ownership to the tokenizer
index e223ef42a42e22b6bce39be3ad90f5bc0be6e93e..f2c1de5e0c07c6378facd2982efa49ac77d97be3 100644 (file)
@@ -174,6 +174,7 @@ new_compiler(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
 {
     compiler *c = PyMem_Calloc(1, sizeof(compiler));
     if (c == NULL) {
+        PyErr_NoMemory();
         return NULL;
     }
     if (compiler_setup(c, mod, filename, pflags, optimize, arena, module) < 0) {