mirror of https://github.com/python/cpython.git
[3.13] gh-128049: Fix type confusion bug with the return value of a custom ExceptionGroup split function (GH-128079) (#128139)
gh-128049: Fix type confusion bug with the return value of a custom ExceptionGroup split function (GH-128079)
(cherry picked from commit 3879ca0100
)
Co-authored-by: Nico-Posada <102486290+Nico-Posada@users.noreply.github.com>
This commit is contained in:
parent
43586a4804
commit
09d15aa9a8
|
@ -952,6 +952,49 @@ def derive(self, excs):
|
||||||
self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)]))
|
self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)]))
|
||||||
self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)]))
|
self.assertExceptionIsLike(ves, FalsyEG("eg", [ValueError(2)]))
|
||||||
|
|
||||||
|
def test_exception_group_subclass_with_bad_split_func(self):
|
||||||
|
# see gh-128049.
|
||||||
|
class BadEG1(ExceptionGroup):
|
||||||
|
def split(self, *args):
|
||||||
|
return "NOT A 2-TUPLE!"
|
||||||
|
|
||||||
|
class BadEG2(ExceptionGroup):
|
||||||
|
def split(self, *args):
|
||||||
|
return ("NOT A 2-TUPLE!",)
|
||||||
|
|
||||||
|
eg_list = [
|
||||||
|
(BadEG1("eg", [OSError(123), ValueError(456)]),
|
||||||
|
r"split must return a tuple, not str"),
|
||||||
|
(BadEG2("eg", [OSError(123), ValueError(456)]),
|
||||||
|
r"split must return a 2-tuple, got tuple of size 1")
|
||||||
|
]
|
||||||
|
|
||||||
|
for eg_class, msg in eg_list:
|
||||||
|
with self.assertRaisesRegex(TypeError, msg) as m:
|
||||||
|
try:
|
||||||
|
raise eg_class
|
||||||
|
except* ValueError:
|
||||||
|
pass
|
||||||
|
except* OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.assertExceptionIsLike(m.exception.__context__, eg_class)
|
||||||
|
|
||||||
|
# we allow tuples of length > 2 for backwards compatibility
|
||||||
|
class WeirdEG(ExceptionGroup):
|
||||||
|
def split(self, *args):
|
||||||
|
return super().split(*args) + ("anything", 123456, None)
|
||||||
|
|
||||||
|
try:
|
||||||
|
raise WeirdEG("eg", [OSError(123), ValueError(456)])
|
||||||
|
except* OSError as e:
|
||||||
|
oeg = e
|
||||||
|
except* ValueError as e:
|
||||||
|
veg = e
|
||||||
|
|
||||||
|
self.assertExceptionIsLike(oeg, WeirdEG("eg", [OSError(123)]))
|
||||||
|
self.assertExceptionIsLike(veg, WeirdEG("eg", [ValueError(456)]))
|
||||||
|
|
||||||
|
|
||||||
class TestExceptStarCleanup(ExceptStarTest):
|
class TestExceptStarCleanup(ExceptStarTest):
|
||||||
def test_sys_exception_restored(self):
|
def test_sys_exception_restored(self):
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
Fix a bug where :keyword:`except* <except_star>` does not properly check the
|
||||||
|
return value of an :exc:`ExceptionGroup`'s :meth:`~BaseExceptionGroup.split`
|
||||||
|
function, leading to a crash in some cases. Now when :meth:`~BaseExceptionGroup.split`
|
||||||
|
returns an invalid object, :keyword:`except* <except_star>` raises a :exc:`TypeError`
|
||||||
|
with the original raised :exc:`ExceptionGroup` object chained to it.
|
|
@ -2029,8 +2029,25 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value, PyObject *match_type,
|
||||||
if (pair == NULL) {
|
if (pair == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
assert(PyTuple_CheckExact(pair));
|
|
||||||
assert(PyTuple_GET_SIZE(pair) == 2);
|
if (!PyTuple_CheckExact(pair)) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.200s.split must return a tuple, not %.200s",
|
||||||
|
Py_TYPE(exc_value)->tp_name, Py_TYPE(pair)->tp_name);
|
||||||
|
Py_DECREF(pair);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow tuples of length > 2 for backwards compatibility
|
||||||
|
if (PyTuple_GET_SIZE(pair) < 2) {
|
||||||
|
PyErr_Format(PyExc_TypeError,
|
||||||
|
"%.200s.split must return a 2-tuple, "
|
||||||
|
"got tuple of size %zd",
|
||||||
|
Py_TYPE(exc_value)->tp_name, PyTuple_GET_SIZE(pair));
|
||||||
|
Py_DECREF(pair);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*match = Py_NewRef(PyTuple_GET_ITEM(pair, 0));
|
*match = Py_NewRef(PyTuple_GET_ITEM(pair, 0));
|
||||||
*rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1));
|
*rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1));
|
||||||
Py_DECREF(pair);
|
Py_DECREF(pair);
|
||||||
|
|
Loading…
Reference in New Issue