From 2f01c562be913004e1d46fc02705c51b81638d67 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Tue, 30 Mar 2021 00:24:17 +0100 Subject: [PATCH] [3.7] bpo-43660: Fix crash when displaying exceptions with custom values for sys.stderr (GH-25075). (GH-25085) (cherry picked from commit 09b90a037d18f5d4acdf1b14082e57bda78e85d3) Co-authored-by: Pablo Galindo --- Lib/test/test_sys.py | 15 +++++++++++++++ .../2021-03-29-19-50-34.bpo-43660.scTgag.rst | 3 +++ Python/pythonrun.c | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-03-29-19-50-34.bpo-43660.scTgag.rst diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 84927a393f17..0478f20cd33b 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1292,6 +1292,21 @@ class SizeofTest(unittest.TestCase): self.assertIsNone(cur.firstiter) self.assertIsNone(cur.finalizer) + def test_changing_sys_stderr_and_removing_reference(self): + # If the default displayhook doesn't take a strong reference + # to sys.stderr the following code can crash. See bpo-43660 + # for more details. + code = textwrap.dedent(''' + import sys + class MyStderr: + def write(self, s): + sys.stderr = None + sys.stderr = MyStderr() + 1/0 + ''') + rc, out, err = assert_python_failure('-c', code) + self.assertEqual(out, b"") + self.assertEqual(err, b"") def test_main(): test.support.run_unittest(SysModuleTest, SizeofTest) diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-03-29-19-50-34.bpo-43660.scTgag.rst b/Misc/NEWS.d/next/Core and Builtins/2021-03-29-19-50-34.bpo-43660.scTgag.rst new file mode 100644 index 000000000000..98419501d9e7 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-03-29-19-50-34.bpo-43660.scTgag.rst @@ -0,0 +1,3 @@ +Fix crash that happens when replacing ``sys.stderr`` with a callable that +can remove the object while an exception is being printed. Patch by Pablo +Galindo. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 4c974cef39c7..b7b77d1f9ee3 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -932,7 +932,9 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) seen = PySet_New(NULL); if (seen == NULL) PyErr_Clear(); + Py_INCREF(f); print_exception_recursive(f, value, seen); + Py_DECREF(f); Py_XDECREF(seen); } } -- 2.47.3