Commit bf93c499 authored by Stefan Behnel's avatar Stefan Behnel

fix some cases where errors in IsInstance()/IsSubtype() calls were not handled

parent b339e287
...@@ -10,6 +10,9 @@ Bugs fixed ...@@ -10,6 +10,9 @@ Bugs fixed
* Crash when returning values on generator termination. * Crash when returning values on generator termination.
* In some cases, exceptions raised during internal isinstance() checks were
not propagated.
* Runtime reported file paths of source files (e.g for profiling and tracing) * Runtime reported file paths of source files (e.g for profiling and tracing)
are now relative to the build root directory instead of the main source file. are now relative to the build root directory instead of the main source file.
......
...@@ -1017,13 +1017,17 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw) ...@@ -1017,13 +1017,17 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
self = PyTuple_GET_ITEM(args, 0); self = PyTuple_GET_ITEM(args, 0);
} }
if (self && !is_classmethod && !is_staticmethod && if (self && !is_classmethod && !is_staticmethod) {
!PyObject_IsInstance(self, binding_func->type)) { int is_instance = PyObject_IsInstance(self, binding_func->type);
PyErr_Format(PyExc_TypeError, if (unlikely(!is_instance)) {
"First argument should be of type %.200s, got %.200s.", PyErr_Format(PyExc_TypeError,
((PyTypeObject *) binding_func->type)->tp_name, "First argument should be of type %.200s, got %.200s.",
self->ob_type->tp_name); ((PyTypeObject *) binding_func->type)->tp_name,
goto __pyx_err; self->ob_type->tp_name);
goto __pyx_err;
} else if (unlikely(is_instance == -1)) {
goto __pyx_err;
}
} }
if (binding_func->__signatures__) { if (binding_func->__signatures__) {
......
...@@ -144,11 +144,15 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject ...@@ -144,11 +144,15 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
if (value && PyExceptionInstance_Check(value)) { if (value && PyExceptionInstance_Check(value)) {
instance_class = (PyObject*) Py_TYPE(value); instance_class = (PyObject*) Py_TYPE(value);
if (instance_class != type) { if (instance_class != type) {
if (PyObject_IsSubclass(instance_class, type)) { int is_subclass = PyObject_IsSubclass(instance_class, type);
if (!is_subclass) {
instance_class = NULL;
} else if (unlikely(is_subclass == -1)) {
// error on subclass test
goto bad;
} else {
// believe the instance // believe the instance
type = instance_class; type = instance_class;
} else {
instance_class = NULL;
} }
} }
} }
......
...@@ -102,6 +102,7 @@ static PyTypeObject *__pyx_GeneratorType = 0; ...@@ -102,6 +102,7 @@ static PyTypeObject *__pyx_GeneratorType = 0;
static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) { static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
PyObject *et, *ev, *tb; PyObject *et, *ev, *tb;
PyObject *value = NULL; PyObject *value = NULL;
int result;
__Pyx_ErrFetch(&et, &ev, &tb); __Pyx_ErrFetch(&et, &ev, &tb);
...@@ -121,7 +122,8 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) { ...@@ -121,7 +122,8 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
// most common case: plain StopIteration without or with separate argument // most common case: plain StopIteration without or with separate argument
if (likely(et == PyExc_StopIteration)) { if (likely(et == PyExc_StopIteration)) {
if (likely(!ev) || !PyObject_IsInstance(ev, PyExc_StopIteration)) { int error = 0;
if (!ev || !(error = PyObject_IsInstance(ev, PyExc_StopIteration))) {
// PyErr_SetObject() and friends put the value directly into ev // PyErr_SetObject() and friends put the value directly into ev
if (!ev) { if (!ev) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
...@@ -132,16 +134,26 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) { ...@@ -132,16 +134,26 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
*pvalue = ev; *pvalue = ev;
return 0; return 0;
} }
if (unlikely(error == -1)) {
// error during isinstance() check
return -1;
}
} }
// otherwise: normalise and check what that gives us // otherwise: normalise and check what that gives us
PyErr_NormalizeException(&et, &ev, &tb); PyErr_NormalizeException(&et, &ev, &tb);
if (unlikely(!PyObject_IsInstance(ev, PyExc_StopIteration))) { result = PyObject_IsInstance(ev, PyExc_StopIteration);
if (unlikely(!result)) {
// looks like normalisation failed - raise the new exception // looks like normalisation failed - raise the new exception
__Pyx_ErrRestore(et, ev, tb); __Pyx_ErrRestore(et, ev, tb);
return -1; return -1;
} }
Py_XDECREF(tb); Py_XDECREF(tb);
Py_DECREF(et); Py_DECREF(et);
if (unlikely(result == -1)) {
// error during isinstance() check
Py_DECREF(ev);
return -1;
}
#if PY_VERSION_HEX >= 0x030300A0 #if PY_VERSION_HEX >= 0x030300A0
value = ((PyStopIterationObject *)ev)->value; value = ((PyStopIterationObject *)ev)->value;
Py_INCREF(value); Py_INCREF(value);
......
...@@ -1415,6 +1415,8 @@ bad: ...@@ -1415,6 +1415,8 @@ bad:
static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name) { static PyObject* __Pyx__PyNumber_MatrixMultiply(PyObject* x, PyObject* y, const char* op_name) {
int right_is_subtype = PyObject_IsSubclass((PyObject*)Py_TYPE(y), (PyObject*)Py_TYPE(x)); int right_is_subtype = PyObject_IsSubclass((PyObject*)Py_TYPE(y), (PyObject*)Py_TYPE(x));
if (unlikely(right_is_subtype == -1))
return NULL;
if (right_is_subtype) { if (right_is_subtype) {
// to allow subtypes to override parent behaviour, try reversed operation first // to allow subtypes to override parent behaviour, try reversed operation first
// see note at https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types // see note at https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types
......
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