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
symtable_visit_type_param_bound_or_defaultinPython/symtable.ccallsPyUnicode_FromFormat()to build aSyntaxErrormessage when a type parameter is named__classdict__. The return value is not checked for NULL before being passed toPyErr_SetObject()andPy_DECREF().If
PyUnicode_FromFormat()fails due to memory exhaustion,error_msgis NULL. The subsequentPy_DECREF(NULL)is undefined behavior and crashes the interpreter in a release build (NDEBUG).Affected code (introduced by commit
891c61c,gh-128632):Trigger condition:
PyUnicode_FromFormat()returns NULL while compiling Python source that contains a type parameter named__classdict__(e.g. typeT[__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:
MemoryErroris propagated cleanly.Actual behavior:
Py_DECREF(NULL)-->SIGSEGVin 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
symtable_visit_type_param_bound_or_default(GH-152684) #152695symtable_visit_type_param_bound_or_default(GH-152684) #152696symtable_visit_type_param_bound_or_default(GH-152684) #152697