]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-152682: Fix NULL dereference on OOM in `symtable_visit_type_param_bound_or_default...
authorPetr Vaganov <petrvaganoff@gmail.com>
Tue, 30 Jun 2026 14:45:25 +0000 (21:45 +0700)
committerGitHub <noreply@github.com>
Tue, 30 Jun 2026 14:45:25 +0000 (14:45 +0000)
In `symtable_visit_type_param_bound_or_default()`, when a reserved name
(e.g. `__classdict__`) is used as a type parameter, `PyUnicode_FromFormat()`
is called to build the SyntaxError message. If the allocation fails and
returns NULL, the subsequent `PyErr_SetObject()` and `Py_DECREF()` calls
would dereference NULL, causing a segfault.

Fix by returning 0 immediately when `PyUnicode_FromFormat()` returns NULL.
This propagates the MemoryError set by `PyUnicode_FromFormat()`.

The bug was introduced in gh-128632 (commit 891c61c).

Lib/test/test_syntax.py
Misc/NEWS.d/next/Core_and_Builtins/2026-06-30-14-00-00.gh-issue-152682.yId7e5.rst [new file with mode: 0644]
Python/symtable.c

index 04e60c74ce1bea600578e600386071b44e951c94..80577cf5c84fac24e5bec1e9346f2b2524b6fb17 100644 (file)
@@ -2861,6 +2861,7 @@ import textwrap
 import unittest
 
 from test import support
+from test.support.script_helper import assert_python_ok
 
 class SyntaxWarningTest(unittest.TestCase):
     def check_warning(self, code, errtext, filename="<testcase>", mode="exec"):
@@ -3201,6 +3202,22 @@ class A:
     class B[{name}]: pass
                 """, "<testcase>", mode="exec")
 
+    @support.nomemtest
+    def test_disallowed_type_param_names_oom(self):
+        # gh-152682: Don't crash on OOM when formatting the SyntaxError message
+        # in symtable_visit_type_param_bound_or_default.
+        code = textwrap.dedent("""\
+            import _testcapi
+            _testcapi.set_nomemory(0)
+            try:
+                compile("class A[__classdict__]: pass", "<string>", "exec")
+            except MemoryError:
+                pass
+            else:
+                raise RuntimeError('MemoryError not raised')
+        """)
+        assert_python_ok("-c", code)
+
     @support.cpython_only
     def test_nested_named_except_blocks(self):
         code = ""
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-30-14-00-00.gh-issue-152682.yId7e5.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-30-14-00-00.gh-issue-152682.yId7e5.rst
new file mode 100644 (file)
index 0000000..aba0b59
--- /dev/null
@@ -0,0 +1,3 @@
+Fix NULL pointer dereference in :func:`compile` when a reserved name (e.g.
+``__classdict__``) is used as a type parameter name and memory allocation
+fails while formatting the error message.
index 00ac510fe76b97204fd00afc3344b41ab2dc2042..e3e89ab403a607eb27002a919c14ade389310f4e 100644 (file)
@@ -2678,6 +2678,9 @@ symtable_visit_type_param_bound_or_default(
 
         PyObject *error_msg = PyUnicode_FromFormat("reserved name '%U' cannot be "
                                                    "used for type parameter", name);
+        if (error_msg == NULL) {
+            return 0;
+        }
         PyErr_SetObject(PyExc_SyntaxError, error_msg);
         Py_DECREF(error_msg);
         SET_ERROR_LOCATION(st->st_filename, LOCATION(tp));