symtable_visit_type_param_bound_or_default in Python/symtable.c calls PyUnicode_FromFormat() to build a SyntaxError message when a type parameter is named __classdict__. The return value is not checked for NULL before being passed to PyErr_SetObject() and Py_DECREF().
If PyUnicode_FromFormat() fails due to memory exhaustion, error_msg is NULL. The subsequent Py_DECREF(NULL) is undefined behavior and crashes the interpreter in a release build (NDEBUG).
Affected code (introduced by commit 891c61c, gh-128632):
// Python/symtable.c
PyObject *error_msg = PyUnicode_FromFormat("reserved name '%U' cannot be "
"used for type parameter", name);
PyErr_SetObject(PyExc_SyntaxError, error_msg); // UB if error_msg is NULL
Py_DECREF(error_msg); // crash if error_msg is NULL
Trigger condition: PyUnicode_FromFormat() returns NULL while compiling Python source that contains a type parameter named __classdict__ (e.g. type T[__classdict__: int] = None). In normal conditions this requires an OOM event at exactly that point; in constrained environments this is reproducible with ulimit or fault injection.
Expected behavior: MemoryError is propagated cleanly.
Actual behavior: Py_DECREF(NULL) --> SIGSEGV in release builds; assertion failure in debug builds.
CPython versions tested on: 3.13 (main, 3.13 branch)
Operating systems tested on: Linux Fedora 43
Linked PRs
- gh-152682: Fix NULL dereference on OOM in symtable_visit_type_param_bound_or_default #152684
- [3.15] gh-152682: Fix NULL dereference on OOM in
symtable_visit_type_param_bound_or_default(GH-152684) #152695 - [3.14] gh-152682: Fix NULL dereference on OOM in
symtable_visit_type_param_bound_or_default(GH-152684) #152696 - [3.13] gh-152682: Fix NULL dereference on OOM in
symtable_visit_type_param_bound_or_default(GH-152684) #152697 - gh-152682: Remove useless
test_syntax.test_disallowed_type_param_names_oom#152770