Skip to content

Commit 82ab9e6

Browse files
gh-99553: fix bug where an ExceptionGroup subclass can wrap a BaseException (GH-99572)
(cherry picked from commit c8c6113) Co-authored-by: Irit Katriel <[email protected]>
1 parent bbac9a8 commit 82ab9e6

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
@@ -79,16 +79,30 @@ def test_BEG_wraps_BaseException__creates_BEG(self):
7979
beg = BaseExceptionGroup("beg", [ValueError(1), KeyboardInterrupt(2)])
8080
self.assertIs(type(beg), BaseExceptionGroup)
8181

82-
def test_EG_subclass_wraps_anything(self):
82+
def test_EG_subclass_wraps_non_base_exceptions(self):
8383
class MyEG(ExceptionGroup):
8484
pass
8585

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

93107
def test_BEG_subclass_wraps_anything(self):
94108
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
@@ -774,7 +774,19 @@ BaseExceptionGroup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
774774
}
775775
}
776776
else {
777-
/* Do nothing - we don't interfere with subclasses */
777+
/* user-defined subclass */
778+
if (nested_base_exceptions) {
779+
int nonbase = PyObject_IsSubclass((PyObject*)cls, PyExc_Exception);
780+
if (nonbase == -1) {
781+
goto error;
782+
}
783+
else if (nonbase == 1) {
784+
PyErr_Format(PyExc_TypeError,
785+
"Cannot nest BaseExceptions in '%.200s'",
786+
cls->tp_name);
787+
goto error;
788+
}
789+
}
778790
}
779791

780792
if (!cls) {

0 commit comments

Comments
 (0)