From e920fbae46612abecbf771ce5c9760735e182786 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 29 Mar 2021 19:51:55 +0100 Subject: [PATCH 1/3] bpo-43660: Fix crash when displaying exceptions with custom values for sys.stderr --- Lib/test/test_sys.py | 16 ++++++++++++++++ .../2021-03-29-19-50-34.bpo-43660.scTgag.rst | 3 +++ Python/pythonrun.c | 3 ++- 3 files changed, 21 insertions(+), 1 deletion(-) 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 5b004c2b52da80..998175bba23686 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1512,6 +1512,22 @@ def test_asyncgen_hooks(self): 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 = """ +if True: + 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, "") + self.assertEqual(err, "") if __name__ == "__main__": unittest.main() 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 00000000000000..98419501d9e7b8 --- /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 b562875f8a4fb8..1715cde49dd688 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1082,8 +1082,9 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb) if (file == Py_None) { return; } - + Py_INCREF(file); _PyErr_Display(file, exception, value, tb); + Py_DECREF(file); } PyObject * From b605f8f89e81c0951c9a1d4132f5da56fa23dd37 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 29 Mar 2021 20:40:00 +0100 Subject: [PATCH 2/3] Update Lib/test/test_sys.py Co-authored-by: Erlend Egeberg Aasland --- Lib/test/test_sys.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 998175bba23686..ca69ccf49b969d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1526,8 +1526,8 @@ def write(self, s): 1/0 """ rc, out, err = assert_python_failure('-c', code) - self.assertEqual(out, "") - self.assertEqual(err, "") + self.assertEqual(out, b"") + self.assertEqual(err, b"") if __name__ == "__main__": unittest.main() From 8690486fab3bd06cefc7d4577f18ab649a0c188e Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Mon, 29 Mar 2021 20:31:02 +0100 Subject: [PATCH 3/3] Add dedent() --- Lib/test/test_sys.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index ca69ccf49b969d..ee39375af3160e 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1516,15 +1516,14 @@ 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 = """ -if True: - import sys - class MyStderr: - def write(self, s): - sys.stderr = None - sys.stderr = MyStderr() - 1/0 -""" + 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"")