Skip to content

Commit 51f8b0a

Browse files
committed
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).
1 parent b993be7 commit 51f8b0a

1 file changed

Lines changed: 23 additions & 7 deletions

File tree

Objects/methodobject.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,34 @@ PyCFunction_GetFlags(PyObject *op)
7979
PyObject *
8080
PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
8181
{
82+
#define CHECK_RESULT(res) assert(res != NULL || PyErr_Occurred())
83+
8284
PyCFunctionObject* f = (PyCFunctionObject*)func;
8385
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
8486
PyObject *self = PyCFunction_GET_SELF(func);
87+
PyObject *res;
8588
Py_ssize_t size;
8689

8790
switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
8891
case METH_VARARGS:
89-
if (kw == NULL || PyDict_Size(kw) == 0)
90-
return (*meth)(self, arg);
92+
if (kw == NULL || PyDict_Size(kw) == 0) {
93+
res = (*meth)(self, arg);
94+
CHECK_RESULT(res);
95+
return res;
96+
}
9197
break;
9298
case METH_VARARGS | METH_KEYWORDS:
93-
return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
99+
res = (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
100+
CHECK_RESULT(res);
101+
return res;
94102
case METH_NOARGS:
95103
if (kw == NULL || PyDict_Size(kw) == 0) {
96104
size = PyTuple_GET_SIZE(arg);
97-
if (size == 0)
98-
return (*meth)(self, NULL);
105+
if (size == 0) {
106+
res = (*meth)(self, NULL);
107+
CHECK_RESULT(res);
108+
return res;
109+
}
99110
PyErr_Format(PyExc_TypeError,
100111
"%.200s() takes no arguments (%zd given)",
101112
f->m_ml->ml_name, size);
@@ -105,8 +116,11 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
105116
case METH_O:
106117
if (kw == NULL || PyDict_Size(kw) == 0) {
107118
size = PyTuple_GET_SIZE(arg);
108-
if (size == 1)
109-
return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
119+
if (size == 1) {
120+
res = (*meth)(self, PyTuple_GET_ITEM(arg, 0));
121+
CHECK_RESULT(res);
122+
return res;
123+
}
110124
PyErr_Format(PyExc_TypeError,
111125
"%.200s() takes exactly one argument (%zd given)",
112126
f->m_ml->ml_name, size);
@@ -123,6 +137,8 @@ PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
123137
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
124138
f->m_ml->ml_name);
125139
return NULL;
140+
141+
#undef CHECK_RESULT
126142
}
127143

128144
/* Methods (the standard built-in methods, that is) */

0 commit comments

Comments
 (0)