[Python-checkins] gh-102056: Fix a few bugs in error handling of exception printing code (#102078)

iritkatriel webhook-mailer at python.org
Mon Feb 20 17:16:26 EST 2023


https://github.com/python/cpython/commit/022b44f2546c44183e4df7b67e3e64502fae9143
commit: 022b44f2546c44183e4df7b67e3e64502fae9143
branch: main
author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com>
date: 2023-02-20T22:16:09Z
summary:

gh-102056: Fix a few bugs in error handling of exception printing code (#102078)

files:
A Misc/NEWS.d/next/Core and Builtins/2023-02-20-15-18-33.gh-issue-102056.uHKuwH.rst
M Lib/test/test_threading.py
M Python/pythonrun.c

diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 7fea2d38673e..a39a267b403d 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -1523,6 +1523,37 @@ def run():
         self.assertEqual(out, b'')
         self.assertNotIn("Unhandled exception", err.decode())
 
+    def test_print_exception_gh_102056(self):
+        # This used to crash. See gh-102056.
+        script = r"""if True:
+            import time
+            import threading
+            import _thread
+
+            def f():
+                try:
+                    f()
+                except RecursionError:
+                    f()
+
+            def g():
+                try:
+                    raise ValueError()
+                except* ValueError:
+                    f()
+
+            def h():
+                time.sleep(1)
+                _thread.interrupt_main()
+
+            t = threading.Thread(target=h)
+            t.start()
+            g()
+            t.join()
+            """
+
+        assert_python_failure("-c", script)
+
     def test_bare_raise_in_brand_new_thread(self):
         def bare_raise():
             raise
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-02-20-15-18-33.gh-issue-102056.uHKuwH.rst b/Misc/NEWS.d/next/Core and Builtins/2023-02-20-15-18-33.gh-issue-102056.uHKuwH.rst
new file mode 100644
index 000000000000..78cd525b365f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2023-02-20-15-18-33.gh-issue-102056.uHKuwH.rst	
@@ -0,0 +1 @@
+Fix error handling bugs in interpreter's exception printing code, which could cause a crash on infinite recursion.
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ce993ea8796c..34a44dd92847 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1246,8 +1246,7 @@ print_chained(struct exception_print_context* ctx, PyObject *value,
               const char * message, const char *tag)
 {
     PyObject *f = ctx->file;
-
-    if (_Py_EnterRecursiveCall(" in print_chained") < 0) {
+    if (_Py_EnterRecursiveCall(" in print_chained")) {
         return -1;
     }
     bool need_close = ctx->need_close;
@@ -1374,7 +1373,9 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
     if (ctx->exception_group_depth == 0) {
         ctx->exception_group_depth += 1;
     }
-    print_exception(ctx, value);
+    if (print_exception(ctx, value) < 0) {
+        return -1;
+    }
 
     PyObject *excs = ((PyBaseExceptionGroupObject *)value)->excs;
     assert(excs && PyTuple_Check(excs));
@@ -1424,7 +1425,7 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
         PyObject *exc = PyTuple_GET_ITEM(excs, i);
 
         if (!truncated) {
-            if (_Py_EnterRecursiveCall(" in print_exception_group") != 0) {
+            if (_Py_EnterRecursiveCall(" in print_exception_group")) {
                 return -1;
             }
             int res = print_exception_recursive(ctx, exc);
@@ -1477,22 +1478,30 @@ print_exception_group(struct exception_print_context *ctx, PyObject *value)
 static int
 print_exception_recursive(struct exception_print_context *ctx, PyObject *value)
 {
+    if (_Py_EnterRecursiveCall(" in print_exception_recursive")) {
+        return -1;
+    }
     if (ctx->seen != NULL) {
         /* Exception chaining */
         if (print_exception_cause_and_context(ctx, value) < 0) {
-            return -1;
+            goto error;
         }
     }
     if (!_PyBaseExceptionGroup_Check(value)) {
         if (print_exception(ctx, value) < 0) {
-            return -1;
+            goto error;
         }
     }
     else if (print_exception_group(ctx, value) < 0) {
-        return -1;
+        goto error;
     }
     assert(!PyErr_Occurred());
+
+    _Py_LeaveRecursiveCall();
     return 0;
+error:
+    _Py_LeaveRecursiveCall();
+    return -1;
 }
 
 #define PyErr_MAX_GROUP_WIDTH 15



More information about the Python-checkins mailing list