https://github.com/python/cpython/commit/3879ca0100942ae15a09ac22889cbe3e46d424eb
commit: 3879ca0100942ae15a09ac22889cbe3e46d424eb
branch: main
author: Nico-Posada <[email protected]>
committer: iritkatriel <[email protected]>
date: 2024-12-20T19:20:31Z
summary:
gh-128049: Fix type confusion bug with the return value of a custom
ExceptionGroup split function (#128079)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2024-12-18-14-22-48.gh-issue-128079.SUD5le.rst
M Lib/test/test_except_star.py
M Python/ceval.c
diff --git a/Lib/test/test_except_star.py b/Lib/test/test_except_star.py
index c49c6008e08e8c..284907f61213f8 100644
--- a/Lib/test/test_except_star.py
+++ b/Lib/test/test_except_star.py
@@ -952,6 +952,49 @@ def derive(self, excs):
self.assertExceptionIsLike(tes, FalsyEG("eg", [TypeError(1)]))
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):
def test_sys_exception_restored(self):
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2024-12-18-14-22-48.gh-issue-128079.SUD5le.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-18-14-22-48.gh-issue-128079.SUD5le.rst
new file mode 100644
index 00000000000000..8da4e677f068a3
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2024-12-18-14-22-48.gh-issue-128079.SUD5le.rst
@@ -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.
diff --git a/Python/ceval.c b/Python/ceval.c
index 3cf11b663c571b..e92a11b16cec81 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -2134,8 +2134,25 @@ _PyEval_ExceptionGroupMatch(PyObject* exc_value,
PyObject *match_type,
if (pair == NULL) {
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));
*rest = Py_NewRef(PyTuple_GET_ITEM(pair, 1));
Py_DECREF(pair);
_______________________________________________
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]