From 47d3e2ed930a9f3d228aed4f62133737dae74cf7 Mon Sep 17 00:00:00 2001 From: Radislav Chugunov <52372310+chgnrdv@users.noreply.github.com> Date: Tue, 24 Oct 2023 02:06:59 +0300 Subject: [PATCH] gh-109894: Fix initialization of static `MemoryError` in subinterpreter (gh-110911) Fixes #109894 * set `interp.static_objects.last_resort_memory_error.args` to empty tuple to avoid crash on `PyErr_Display()` call * allow `_PyExc_InitGlobalObjects()` to be called on subinterpreter init --------- Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> --- Include/internal/pycore_runtime_init.h | 1 + Lib/test/test_exceptions.py | 14 ++++++++++++++ .../2023-10-15-22-18-45.gh-issue-109894.UAmo06.rst | 1 + Objects/exceptions.c | 4 ---- 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-10-15-22-18-45.gh-issue-109894.UAmo06.rst diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h index 574a3c1a9db66c..4a48907d9ee2f6 100644 --- a/Include/internal/pycore_runtime_init.h +++ b/Include/internal/pycore_runtime_init.h @@ -177,6 +177,7 @@ extern PyTypeObject _PyExc_MemoryError; }, \ .last_resort_memory_error = { \ _PyObject_HEAD_INIT(&_PyExc_MemoryError) \ + .args = (PyObject*)&_Py_SINGLETON(tuple_empty) \ }, \ }, \ }, \ diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 4031c5ca76c705..7f1d5ee9322b45 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -1791,6 +1791,20 @@ class TestException(MemoryError): gc_collect() + def test_memory_error_in_subinterp(self): + # gh-109894: subinterpreters shouldn't count on last resort memory error + # when MemoryError is raised through PyErr_NoMemory() call, + # and should preallocate memory errors as does the main interpreter. + # interp.static_objects.last_resort_memory_error.args + # should be initialized to empty tuple to avoid crash on attempt to print it. + code = f"""if 1: + import _testcapi + _testcapi.run_in_subinterp(\"[0]*{sys.maxsize}\") + exit(0) + """ + rc, _, err = script_helper.assert_python_ok("-c", code) + self.assertIn(b'MemoryError', err) + class NameErrorTests(unittest.TestCase): def test_name_error_has_name(self): diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-15-22-18-45.gh-issue-109894.UAmo06.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-15-22-18-45.gh-issue-109894.UAmo06.rst new file mode 100644 index 00000000000000..214853660c5a57 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-15-22-18-45.gh-issue-109894.UAmo06.rst @@ -0,0 +1 @@ +Fixed crash due to improperly initialized static :exc:`MemoryError` in subinterpreter. diff --git a/Objects/exceptions.c b/Objects/exceptions.c index 48623451c0d2cd..e3e8e02861d775 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -3700,10 +3700,6 @@ _PyExc_FiniTypes(PyInterpreterState *interp) PyStatus _PyExc_InitGlobalObjects(PyInterpreterState *interp) { - if (!_Py_IsMainInterpreter(interp)) { - return _PyStatus_OK(); - } - if (preallocate_memerrors() < 0) { return _PyStatus_NO_MEMORY(); }