From 9035ad932b9a7861793f7187d74051babb8b17d9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 11 Jul 2013 23:44:46 +0200 Subject: [PATCH] Issue #18408: In debug mode, PyCFunction_Call() now checks if an exception was raised if the result is NULL to help to find bugs in C mode (get the error earlier than the SystemError in ceval.c). --- Objects/methodobject.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/Objects/methodobject.c b/Objects/methodobject.c index 9944fade10..11c8b6e9c1 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -79,23 +79,34 @@ PyCFunction_GetFlags(PyObject *op) PyObject * PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { +#define CHECK_RESULT(res) assert(res != NULL || PyErr_Occurred()) + PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); + PyObject *res; Py_ssize_t size; switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) { case METH_VARARGS: - if (kw == NULL || PyDict_Size(kw) == 0) - return (*meth)(self, arg); + if (kw == NULL || PyDict_Size(kw) == 0) { + res = (*meth)(self, arg); + CHECK_RESULT(res); + return res; + } break; case METH_VARARGS | METH_KEYWORDS: - return (*(PyCFunctionWithKeywords)meth)(self, arg, kw); + res = (*(PyCFunctionWithKeywords)meth)(self, arg, kw); + CHECK_RESULT(res); + return res; case METH_NOARGS: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); - if (size == 0) - return (*meth)(self, NULL); + if (size == 0) { + res = (*meth)(self, NULL); + CHECK_RESULT(res); + return res; + } PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); @@ -105,8 +116,11 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) case METH_O: if (kw == NULL || PyDict_Size(kw) == 0) { size = PyTuple_GET_SIZE(arg); - if (size == 1) - return (*meth)(self, PyTuple_GET_ITEM(arg, 0)); + if (size == 1) { + res = (*meth)(self, PyTuple_GET_ITEM(arg, 0)); + CHECK_RESULT(res); + return res; + } PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); @@ -123,6 +137,8 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); return NULL; + +#undef CHECK_RESULT } /* Methods (the standard built-in methods, that is) */ -- 2.40.0