Skip to content

Commit

Permalink
fix some cases where errors in IsInstance()/IsSubtype() calls were no…
Browse files Browse the repository at this point in the history
…t handled
  • Loading branch information
scoder committed May 3, 2015
1 parent b339e28 commit bf93c49
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 12 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Bugs fixed

* 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)
are now relative to the build root directory instead of the main source file.

Expand Down
18 changes: 11 additions & 7 deletions Cython/Utility/CythonFunction.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,13 +1017,17 @@ __pyx_FusedFunction_call(PyObject *func, PyObject *args, PyObject *kw)
self = PyTuple_GET_ITEM(args, 0);
}

if (self && !is_classmethod && !is_staticmethod &&
!PyObject_IsInstance(self, binding_func->type)) {
PyErr_Format(PyExc_TypeError,
"First argument should be of type %.200s, got %.200s.",
((PyTypeObject *) binding_func->type)->tp_name,
self->ob_type->tp_name);
goto __pyx_err;
if (self && !is_classmethod && !is_staticmethod) {
int is_instance = PyObject_IsInstance(self, binding_func->type);
if (unlikely(!is_instance)) {
PyErr_Format(PyExc_TypeError,
"First argument should be of type %.200s, got %.200s.",
((PyTypeObject *) binding_func->type)->tp_name,
self->ob_type->tp_name);
goto __pyx_err;
} else if (unlikely(is_instance == -1)) {
goto __pyx_err;
}
}

if (binding_func->__signatures__) {
Expand Down
10 changes: 7 additions & 3 deletions Cython/Utility/Exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,15 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
if (value && PyExceptionInstance_Check(value)) {
instance_class = (PyObject*) Py_TYPE(value);
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
type = instance_class;
} else {
instance_class = NULL;
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions Cython/Utility/Generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static PyTypeObject *__pyx_GeneratorType = 0;
static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
PyObject *et, *ev, *tb;
PyObject *value = NULL;
int result;

__Pyx_ErrFetch(&et, &ev, &tb);

Expand All @@ -121,7 +122,8 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {

// most common case: plain StopIteration without or with separate argument
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
if (!ev) {
Py_INCREF(Py_None);
Expand All @@ -132,16 +134,26 @@ static int __Pyx_PyGen_FetchStopIterationValue(PyObject **pvalue) {
*pvalue = ev;
return 0;
}
if (unlikely(error == -1)) {
// error during isinstance() check
return -1;
}
}
// otherwise: normalise and check what that gives us
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
__Pyx_ErrRestore(et, ev, tb);
return -1;
}
Py_XDECREF(tb);
Py_DECREF(et);
if (unlikely(result == -1)) {
// error during isinstance() check
Py_DECREF(ev);
return -1;
}
#if PY_VERSION_HEX >= 0x030300A0
value = ((PyStopIterationObject *)ev)->value;
Py_INCREF(value);
Expand Down
2 changes: 2 additions & 0 deletions Cython/Utility/ObjectHandling.c
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,8 @@ static PyObject* __Pyx_PyObject_CallMatrixMethod(PyObject* method, PyObject* arg

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));
if (unlikely(right_is_subtype == -1))
return NULL;
if (right_is_subtype) {
// 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
Expand Down

0 comments on commit bf93c49

Please sign in to comment.