summaryrefslogtreecommitdiffstats
path: root/Objects/methodobject.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2017-02-08 11:06:00 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2017-02-08 11:06:00 (GMT)
commit7399a05965162f46ca00b5453a59f71fdb5851f1 (patch)
tree08c61a1b6830a77d5ebf86da2ce6b59d4597b2f4 /Objects/methodobject.c
parentee0ee9ae8e9111a5ce8a09e7b705cfd380394ce7 (diff)
downloadcpython-7399a05965162f46ca00b5453a59f71fdb5851f1.zip
cpython-7399a05965162f46ca00b5453a59f71fdb5851f1.tar.gz
cpython-7399a05965162f46ca00b5453a59f71fdb5851f1.tar.bz2
Issue #29306: Fix usage of Py_EnterRecursiveCall()
* *PyCFunction_*Call*() functions now call Py_EnterRecursiveCall(). * PyObject_Call() now calls directly _PyFunction_FastCallDict() and PyCFunction_Call() to avoid calling Py_EnterRecursiveCall() twice per function call
Diffstat (limited to 'Objects/methodobject.c')
-rw-r--r--Objects/methodobject.c61
1 files changed, 36 insertions, 25 deletions
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 6618d78..0782777 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -90,11 +90,6 @@ PyObject *
_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **args,
Py_ssize_t nargs, PyObject *kwargs)
{
- PyCFunction meth;
- PyObject *result;
- int flags;
- PyObject *argstuple;
-
/* _PyMethodDef_RawFastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
@@ -105,18 +100,23 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));
- meth = method->ml_meth;
- flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
+ PyCFunction meth = method->ml_meth;
+ int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
+ PyObject *result = NULL;
+
+ if (Py_EnterRecursiveCall(" while calling a Python object")) {
+ return NULL;
+ }
switch (flags)
{
case METH_NOARGS:
- if (nargs != 0) {
+ if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
- return NULL;
- }
+ goto exit;
+ }
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
@@ -130,7 +130,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
- return NULL;
+ goto exit;
}
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
@@ -148,10 +148,11 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
/* fall through next case */
case METH_VARARGS | METH_KEYWORDS:
+ {
/* Slow-path: create a temporary tuple for positional arguments */
- argstuple = _PyStack_AsTuple(args, nargs);
+ PyObject *argstuple = _PyStack_AsTuple(args, nargs);
if (argstuple == NULL) {
- return NULL;
+ goto exit;
}
if (flags & METH_KEYWORDS) {
@@ -162,6 +163,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
}
Py_DECREF(argstuple);
break;
+ }
case METH_FASTCALL:
{
@@ -170,7 +172,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
_PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
- return NULL;
+ goto exit;
}
result = (*fastmeth) (self, stack, nargs, kwnames);
@@ -185,17 +187,19 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyMethodDef_RawFastCallDict. "
"METH_OLDARGS is no longer supported!");
- return NULL;
+ goto exit;
}
- return result;
+ goto exit;
no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name, nargs);
- return NULL;
+exit:
+ Py_LeaveRecursiveCall();
+ return result;
}
PyObject *
@@ -232,7 +236,11 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
PyCFunction meth = method->ml_meth;
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_Size(kwnames);
- PyObject *result;
+ PyObject *result = NULL;
+
+ if (Py_EnterRecursiveCall(" while calling a Python object")) {
+ return NULL;
+ }
switch (flags)
{
@@ -241,7 +249,7 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
- return NULL;
+ goto exit;
}
if (nkwargs) {
@@ -256,7 +264,7 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
- return NULL;
+ goto exit;
}
if (nkwargs) {
@@ -284,7 +292,7 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
argtuple = _PyStack_AsTuple(args, nargs);
if (argtuple == NULL) {
- return NULL;
+ goto exit;
}
if (flags & METH_KEYWORDS) {
@@ -294,7 +302,7 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
kwdict = _PyStack_AsDict(args + nargs, kwnames);
if (kwdict == NULL) {
Py_DECREF(argtuple);
- return NULL;
+ goto exit;
}
}
else {
@@ -315,16 +323,19 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject *
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyCFunction_FastCallKeywords. "
"METH_OLDARGS is no longer supported!");
- return NULL;
+ goto exit;
}
- return result;
+ goto exit;
no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name);
- return NULL;
+
+exit:
+ Py_LeaveRecursiveCall();
+ return result;
}
PyObject *