From e01d44b6255f383440f62215d01ebc7cd317883e Mon Sep 17 00:00:00 2001 From: Ijtihed Kilani Date: Sat, 20 Jun 2026 14:19:24 +0300 Subject: [PATCH] gh-151673: Fix crash in warnings.warn() under memory pressure --- Lib/test/test_warnings/__init__.py | 20 ++++++++++++++++++- ...-06-19-21-58-01.gh-issue-151673.Kx9mPq.rst | 3 +++ Python/_warnings.c | 13 +++++++++--- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-06-19-21-58-01.gh-issue-151673.Kx9mPq.rst diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py index bf1bcf8e6ed5d9..0035f73113178a 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -24,7 +24,6 @@ import warnings as original_warnings from warnings import deprecated - py_warnings = import_helper.import_fresh_module('_py_warnings') py_warnings._set_module(py_warnings) @@ -1237,6 +1236,25 @@ def test_issue31566(self): support.swap_item(globals(), '__file__', None): self.assertRaises(UserWarning, self.module.warn, 'bar') + @support.cpython_only + # Python built with Py_TRACE_REFS fail with a fatal error in + # _PyRefchain_Trace() on memory allocation error. + @unittest.skipIf(support.Py_TRACE_REFS, 'cannot test Py_TRACE_REFS build') + def test_issue151673(self): + # Skip this test if the _testcapi module isn't available. + _testcapi = import_helper.import_module('_testcapi') + # warn() shouldn't crash when the "" fallback filename + # can't be allocated under memory pressure. + code = """if 1: + import _testcapi, warnings + warnings.simplefilter("always") + _testcapi.set_nomemory(0) + warnings.warn("boom") + """ + rc, out, err = assert_python_failure("-c", code) + self.assertIn(rc, (1, 120)) + self.assertIn(b'MemoryError', err) + class WarningsDisplayTests(BaseTest): diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-19-21-58-01.gh-issue-151673.Kx9mPq.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-19-21-58-01.gh-issue-151673.Kx9mPq.rst new file mode 100644 index 00000000000000..fe12b20509777c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-19-21-58-01.gh-issue-151673.Kx9mPq.rst @@ -0,0 +1,3 @@ +Fix a crash in :func:`warnings.warn` when the ``""`` fallback filename +could not be allocated under memory pressure: :c:func:`!setup_context` left +the filename ``NULL`` and it was later passed to :c:func:`Py_DECREF`. diff --git a/Python/_warnings.c b/Python/_warnings.c index 4f6de50efa14a8..856fd0a4cd6a55 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -1031,9 +1031,18 @@ setup_context(Py_ssize_t stack_level, } } + /* Initialize the output references so handle_error can Py_XDECREF them + even when we bail out before they are assigned. */ + *filename = NULL; + *registry = NULL; + *module = NULL; + if (f == NULL) { globals = interp->sysdict; *filename = PyUnicode_FromString(""); + if (*filename == NULL) { + goto handle_error; + } *lineno = 0; } else { @@ -1043,8 +1052,6 @@ setup_context(Py_ssize_t stack_level, Py_DECREF(f); } - *module = NULL; - /* Setup registry. */ assert(globals != NULL); assert(PyAnyDict_Check(globals)); @@ -1084,7 +1091,7 @@ setup_context(Py_ssize_t stack_level, handle_error: Py_XDECREF(*registry); Py_XDECREF(*module); - Py_DECREF(*filename); + Py_XDECREF(*filename); return 0; }