Commit 7f41244d authored by Stefan Behnel's avatar Stefan Behnel

Correct the runtime handling of exception tuples in except clauses.

Closes #2425.
parent 93c7400a
...@@ -12,6 +12,9 @@ Bugs fixed ...@@ -12,6 +12,9 @@ Bugs fixed
generated an invalid C function call to the (non-existent) base type implementation. generated an invalid C function call to the (non-existent) base type implementation.
(Github issue #2309) (Github issue #2309)
* Exception catching based on a non-literal (runtime) tuple could fail to match the
exception. (Github issue #2425)
0.28.3 (2018-05-27) 0.28.3 (2018-05-27)
=================== ===================
......
...@@ -765,15 +765,40 @@ static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, ...@@ -765,15 +765,40 @@ static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err,
// so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument // so far, we only call PyErr_GivenExceptionMatches() with an exception type (not instance) as first argument
// => optimise for that case // => optimise for that case
static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) {
Py_ssize_t i, n;
assert(PyExceptionClass_Check(exc_type));
n = PyTuple_GET_SIZE(tuple);
#if PY_MAJOR_VERSION >= 3
// the tighter subtype checking in Py3 allows faster out-of-order comparison
for (i=0; i<n; i++) {
if (exc_type == PyTuple_GET_ITEM(tuple, i)) return 1;
}
#endif
for (i=0; i<n; i++) {
PyObject *t = PyTuple_GET_ITEM(tuple, i);
#if PY_MAJOR_VERSION < 3
if (likely(exc_type == t)) return 1;
#endif
if (__Pyx_inner_PyErr_GivenExceptionMatches2(exc_type, NULL, t)) return 1;
}
return 0;
}
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) { static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) {
if (likely(err == exc_type)) return 1; if (likely(err == exc_type)) return 1;
if (likely(PyExceptionClass_Check(err))) { if (likely(PyExceptionClass_Check(err))) {
if (unlikely(PyTuple_Check(exc_type))) {
return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type);
}
return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type); return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type);
} }
return PyErr_GivenExceptionMatches(err, exc_type); return PyErr_GivenExceptionMatches(err, exc_type);
} }
static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) { static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) {
assert(PyExceptionClass_Check(exc_type1));
assert(PyExceptionClass_Check(exc_type2));
if (likely(err == exc_type1 || err == exc_type2)) return 1; if (likely(err == exc_type1 || err == exc_type2)) return 1;
if (likely(PyExceptionClass_Check(err))) { if (likely(PyExceptionClass_Check(err))) {
return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2); return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2);
......
...@@ -58,6 +58,36 @@ def single_except_expression(a, x): ...@@ -58,6 +58,36 @@ def single_except_expression(a, x):
i = 3 i = 3
return i return i
exceptions = (ValueError, TypeError)
def single_except_global_tuple(x):
"""
>>> single_except_global_tuple(None)
2
>>> single_except_global_tuple(ValueError('test'))
3
>>> single_except_global_tuple(TypeError('test'))
3
>>> class TypeErrorSubtype(TypeError): pass
>>> single_except_global_tuple(TypeErrorSubtype('test'))
3
>>> single_except_global_tuple(AttributeError('test'))
Traceback (most recent call last):
AttributeError: test
"""
cdef int i
try:
i = 1
if x:
raise x
i = 2
except exceptions:
i = 3
return i
def double_except_no_raise(a,b): def double_except_no_raise(a,b):
""" """
>>> double_except_no_raise(TypeError, ValueError) >>> double_except_no_raise(TypeError, ValueError)
...@@ -179,6 +209,10 @@ def normal_and_bare_except_raise(x, a): ...@@ -179,6 +209,10 @@ def normal_and_bare_except_raise(x, a):
2 2
>>> normal_and_bare_except_raise(ValueError('test'), TypeError) >>> normal_and_bare_except_raise(ValueError('test'), TypeError)
3 3
>>> normal_and_bare_except_raise(TypeError('test'), (TypeError, ValueError))
2
>>> normal_and_bare_except_raise(ValueError('test'), (TypeError, ValueError))
2
>>> normal_and_bare_except_raise(None, TypeError) >>> normal_and_bare_except_raise(None, TypeError)
1 1
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment