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 | 9035ad932b9a7861793f7187d74051babb8b17d9 (patch) | |
| tree | e8a9943de107740038fec6c671925da1ed82b598 /Objects/methodobject.c | |
| parent | 526daabf341a2e0e5c2624ebcf82968bd48b5019 (diff) | |
| download | cpython-git-9035ad932b9a7861793f7187d74051babb8b17d9.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) */ | 
