Skip to content

Commit 36fa94e

Browse files
committed
gh-152682: Fix NULL dereference on OOM in symtable_visit_type_param_bound_or_default
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).
1 parent ecdef17 commit 36fa94e

3 files changed

Lines changed: 23 additions & 0 deletions

File tree

Lib/test/test_syntax.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2857,10 +2857,12 @@ def f(x: *b)
28572857

28582858
import re
28592859
import doctest
2860+
import signal
28602861
import textwrap
28612862
import unittest
28622863

28632864
from test import support
2865+
from test.support.script_helper import assert_python_failure
28642866

28652867
class SyntaxWarningTest(unittest.TestCase):
28662868
def check_warning(self, code, errtext, filename="<testcase>", mode="exec"):
@@ -3201,6 +3203,21 @@ class A:
32013203
class B[{name}]: pass
32023204
""", "<testcase>", mode="exec")
32033205

3206+
@support.nomemtest
3207+
def test_disallowed_type_param_names_oom(self):
3208+
# gh-152682: Don't crash on OOM when formatting the SyntaxError message
3209+
# in symtable_visit_type_param_bound_or_default.
3210+
code = textwrap.dedent("""\
3211+
import _testcapi
3212+
_testcapi.set_nomemory(0)
3213+
compile("class A[__classdict__]: pass", "<string>", "exec")
3214+
""")
3215+
rc, _, _ = assert_python_failure("-c", code)
3216+
if support.MS_WINDOWS:
3217+
self.assertNotEqual(rc, 0xC0000005) # STATUS_ACCESS_VIOLATION
3218+
else:
3219+
self.assertNotEqual(rc, -int(signal.SIGSEGV))
3220+
32043221
@support.cpython_only
32053222
def test_nested_named_except_blocks(self):
32063223
code = ""
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix NULL pointer dereference in :func:`compile` when a reserved name (e.g.
2+
``__classdict__``) is used as a type parameter name and memory allocation
3+
fails while formatting the error message.

Python/symtable.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,6 +2678,9 @@ symtable_visit_type_param_bound_or_default(
26782678

26792679
PyObject *error_msg = PyUnicode_FromFormat("reserved name '%U' cannot be "
26802680
"used for type parameter", name);
2681+
if (error_msg == NULL) {
2682+
return 0;
2683+
}
26812684
PyErr_SetObject(PyExc_SyntaxError, error_msg);
26822685
Py_DECREF(error_msg);
26832686
SET_ERROR_LOCATION(st->st_filename, LOCATION(tp));

0 commit comments

Comments
 (0)