Skip to content

Commit c8c6113

Browse files
authored
gh-99553: fix bug where an ExceptionGroup subclass can wrap a BaseException (GH-99572)
1 parent a220c6d commit c8c6113

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

Doc/library/exceptions.rst

+4
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,10 @@ their subgroups based on the types of the contained exceptions.
965965
def derive(self, excs):
966966
return Errors(excs, self.exit_code)
967967

968+
Like :exc:`ExceptionGroup`, any subclass of :exc:`BaseExceptionGroup` which
969+
is also a subclass of :exc:`Exception` can only wrap instances of
970+
:exc:`Exception`.
971+
968972
.. versionadded:: 3.11
969973

970974

Lib/test/test_exception_group.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,30 @@ def test_BEG_wraps_BaseException__creates_BEG(self):
7878
beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
7979
self.assertIs(type(beg), BaseExceptionGroup)
8080

81-
def test_EG_subclass_wraps_anything(self):
81+
def test_EG_subclass_wraps_non_base_exceptions(self):
8282
class MyEG(ExceptionGroup):
8383
pass
8484

8585
self.assertIs(
8686
type(MyEG("eg", [ValueError(12), TypeError(42)])),
8787
MyEG)
88-
self.assertIs(
89-
type(MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])),
90-
MyEG)
88+
89+
def test_EG_subclass_does_not_wrap_base_exceptions(self):
90+
class MyEG(ExceptionGroup):
91+
pass
92+
93+
msg = "Cannot nest BaseExceptions in 'MyEG'"
94+
with self.assertRaisesRegex(TypeError, msg):
95+
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])
96+
97+
def test_BEG_and_E_subclass_does_not_wrap_base_exceptions(self):
98+
class MyEG(BaseExceptionGroup, ValueError):
99+
pass
100+
101+
msg = "Cannot nest BaseExceptions in 'MyEG'"
102+
with self.assertRaisesRegex(TypeError, msg):
103+
MyEG("eg", [ValueError(12), KeyboardInterrupt(42)])
104+
91105

92106
def test_BEG_subclass_wraps_anything(self):
93107
class MyBEG(BaseExceptionGroup):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix bug where an :exc:`ExceptionGroup` subclass can wrap a
2+
:exc:`BaseException`.

Objects/exceptions.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,19 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
753753
}
754754
}
755755
else {
756-
/* Do nothing - we don't interfere with subclasses */
756+
/* user-defined subclass */
757+
if (nested_base_exceptions) {
758+
int nonbase = PyObject_IsSubclass((PyObject*)cls, PyExc_Exception);
759+
if (nonbase == -1) {
760+
goto error;
761+
}
762+
else if (nonbase == 1) {
763+
PyErr_Format(PyExc_TypeError,
764+
"Cannot nest BaseExceptions in '%.200s'",
765+
cls->tp_name);
766+
goto error;
767+
}
768+
}
757769
}
758770

759771
if (!cls) {

0 commit comments

Comments
 (0)