summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2021-11-22 16:56:23 (GMT)
committerGitHub <noreply@github.com>2021-11-22 16:56:23 (GMT)
commit4d6c0c0cce05befa06e0cad7351b1303ac048277 (patch)
treea6f2cc0e0428879ffd305c0c38cc4e240086247d
parent0e1c2f3ef84572b79fa7d8498a69bc5a56ff0d8d (diff)
downloadcpython-4d6c0c0cce05befa06e0cad7351b1303ac048277.zip
cpython-4d6c0c0cce05befa06e0cad7351b1303ac048277.tar.gz
cpython-4d6c0c0cce05befa06e0cad7351b1303ac048277.tar.bz2
bpo-45871: Refactor except matcher validation into a separate function so that it can be reused. Add missing unit test. (GH-29711)
-rw-r--r--Lib/test/test_exceptions.py15
-rw-r--r--Python/ceval.c56
2 files changed, 48 insertions, 23 deletions
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 4c18a59..eee178c 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -2401,6 +2401,21 @@ class SyntaxErrorTests(unittest.TestCase):
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 9e56b50..1d69708 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 @@ check_eval_breaker:
}
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)
{