https://github.com/python/cpython/commit/ced64605be2bcc4e4a3064aaed0ca569308458a0
commit: ced64605be2bcc4e4a3064aaed0ca569308458a0
branch: main
author: Sergey Miryanov <[email protected]>
committer: iritkatriel <[email protected]>
date: 2026-03-19T11:25:15Z
summary:

GH-146096: Fix segfault in BaseExceptionGroup repr (#146141)

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst
M Lib/test/test_exception_group.py
M Objects/exceptions.c

diff --git a/Lib/test/test_exception_group.py b/Lib/test/test_exception_group.py
index ace7ec72917934..35ffc9a0a4cf30 100644
--- a/Lib/test/test_exception_group.py
+++ b/Lib/test/test_exception_group.py
@@ -234,6 +234,18 @@ class MyEG(ExceptionGroup):
             "ExceptionGroup('test', deque([ValueError(1), TypeError(2)]))"
         )
 
+    def test_repr_small_size_args(self):
+        eg = ExceptionGroup("msg", [ValueError()])
+        eg.args = ()
+        # repr of the ExceptionGroup with empty args should not crash
+        self.assertEqual(repr(eg), "ExceptionGroup('msg', (ValueError(),))")
+
+        eg.args = (1,)
+        # repr of the ExceptionGroup with 1-size args should not crash
+        self.assertEqual(repr(eg), "ExceptionGroup('msg', (ValueError(),))")
+
+
+
     def test_repr_raises(self):
         class MySeq(collections.abc.Sequence):
             def __init__(self, raises):
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst
new file mode 100644
index 00000000000000..8d7e177c6140a7
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-19-01-19-34.gh-issue-146096.R9tkJX.rst
@@ -0,0 +1,2 @@
+Fixed segmentation fault when called repr for BaseExceptionGroup with empty
+or 1-size tuple args.
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 4e090e5dd863f1..32b0fcec6c4542 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -1091,7 +1091,8 @@ BaseExceptionGroup_repr(PyObject *op)
          * value of self.args[1]; but this can be mutable and go out-of-sync
          * with self.exceptions. Instead, use self.exceptions for accuracy,
          * making it look like self.args[1] for backwards compatibility. */
-        if (PyList_Check(PyTuple_GET_ITEM(self->args, 1))) {
+        assert(PyTuple_Check(self->args));
+        if (PyTuple_GET_SIZE(self->args) == 2 && 
PyList_Check(PyTuple_GET_ITEM(self->args, 1))) {
             PyObject *exceptions_list = PySequence_List(self->excs);
             if (!exceptions_list) {
                 return NULL;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to