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;