Mailing List Archive

bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711)
https://github.com/python/cpython/commit/4d6c0c0cce05befa06e0cad7351b1303ac048277
commit: 4d6c0c0cce05befa06e0cad7351b1303ac048277
branch: main
author: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
committer: markshannon <mark@hotpy.org>
date: 2021-11-22T16:56:23Z
summary:

bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711)

files:
M Lib/test/test_exceptions.py
M Python/ceval.c

diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 4c18a59f6e92c..eee178c8ca2af 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -2401,6 +2401,21 @@ def test_incorrect_constructor(self):
self.assertRaises(TypeError, SyntaxError, "bad bad", args)


+class TestInvalidExceptionMatcher(unittest.TestCase):
+ def test_except_star_invalid_exception_type(self):
+ with self.assertRaises(TypeError):
+ try:
+ raise ValueError
+ except 42:
+ pass
+
+ with self.assertRaises(TypeError):
+ try:
+ raise ValueError
+ except (ValueError, 42):
+ pass
+
+
class PEP626Tests(unittest.TestCase):

def lineno_after_raise(self, f, *expected):
diff --git a/Python/ceval.c b/Python/ceval.c
index 9e56b50ee844b..1d69708576fa4 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -93,6 +93,7 @@ static int import_all_from(PyThreadState *, PyObject *, PyObject *);
static void format_exc_check_arg(PyThreadState *, PyObject *, const char *, PyObject *);
static void format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg);
static int check_args_iterable(PyThreadState *, PyObject *func, PyObject *vararg);
+static int check_except_type_valid(PyThreadState *tstate, PyObject* right);
static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs);
static void format_awaitable_error(PyThreadState *, PyTypeObject *, int, int);
static int get_exception_handler(PyCodeObject *, int, int*, int*, int*);
@@ -3715,31 +3716,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
}

TARGET(JUMP_IF_NOT_EXC_MATCH) {
- const char *cannot_catch_msg = "catching classes that do not "
- "inherit from BaseException is not "
- "allowed";
PyObject *right = POP();
PyObject *left = TOP();
- if (PyTuple_Check(right)) {
- Py_ssize_t i, length;
- length = PyTuple_GET_SIZE(right);
- for (i = 0; i < length; i++) {
- PyObject *exc = PyTuple_GET_ITEM(right, i);
- if (!PyExceptionClass_Check(exc)) {
- _PyErr_SetString(tstate, PyExc_TypeError,
- cannot_catch_msg);
- Py_DECREF(right);
- goto error;
- }
- }
- }
- else {
- if (!PyExceptionClass_Check(right)) {
- _PyErr_SetString(tstate, PyExc_TypeError,
- cannot_catch_msg);
- Py_DECREF(right);
- goto error;
- }
+ if (check_except_type_valid(tstate, right) < 0) {
+ Py_DECREF(right);
+ goto error;
}
int res = PyErr_GivenExceptionMatches(left, right);
Py_DECREF(right);
@@ -6892,6 +6873,35 @@ import_all_from(PyThreadState *tstate, PyObject *locals, PyObject *v)
return err;
}

+
+#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
+ "BaseException is not allowed"
+
+static int
+check_except_type_valid(PyThreadState *tstate, PyObject* right)
+{
+ if (PyTuple_Check(right)) {
+ Py_ssize_t i, length;
+ length = PyTuple_GET_SIZE(right);
+ for (i = 0; i < length; i++) {
+ PyObject *exc = PyTuple_GET_ITEM(right, i);
+ if (!PyExceptionClass_Check(exc)) {
+ _PyErr_SetString(tstate, PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ return -1;
+ }
+ }
+ }
+ else {
+ if (!PyExceptionClass_Check(right)) {
+ _PyErr_SetString(tstate, PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ return -1;
+ }
+ }
+ return 0;
+}
+
static int
check_args_iterable(PyThreadState *tstate, PyObject *func, PyObject *args)
{

_______________________________________________
Python-checkins mailing list
Python-checkins@python.org
https://mail.python.org/mailman/listinfo/python-checkins