diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2013-07-11 23:44:46 +0200 |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2013-07-11 23:44:46 +0200 |
commit | e822e9e9c1a27846eb90b5357d2692b01abe1599 (patch) | |
tree | c620ad00aa5d9b1703df28b86e187091344716e8 /Objects/methodobject.c | |
parent | 77ec13e47fdd3aede81f701096bb759fd17be4d9 (diff) | |
download | cpython-e822e9e9c1a27846eb90b5357d2692b01abe1599.tar.gz |
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).
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r-- | Objects/methodobject.c | 30 |
1 files 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) */ |