diff -r ed0f83091003 Objects/abstract.c --- a/Objects/abstract.c Wed Jan 18 14:16:57 2017 +0100 +++ b/Objects/abstract.c Wed Jan 18 14:19:30 2017 +0100 @@ -2305,9 +2305,6 @@ PyObject * _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - ternaryfunc call; - PyObject *result = NULL; - /* _PyObject_FastCallDict() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ @@ -2318,42 +2315,43 @@ PyObject * assert(nargs == 0 || args != NULL); assert(kwargs == NULL || PyDict_Check(kwargs)); - if (Py_EnterRecursiveCall(" while calling a Python object")) { - return NULL; - } - if (PyFunction_Check(callable)) { - result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); + /* Py_EnterRecursiveCall() is handled by _PyEval_EvalFrameDefault() */ + return _PyFunction_FastCallDict(callable, args, nargs, kwargs); } else if (PyCFunction_Check(callable)) { - result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); + /* Py_EnterRecursiveCall() is handled by _PyCFunction_FastCallDict() */ + return _PyCFunction_FastCallDict(callable, args, nargs, kwargs); } else { - PyObject *tuple; + PyObject *argstuple, *result; + ternaryfunc call; /* Slow-path: build a temporary tuple */ call = callable->ob_type->tp_call; if (call == NULL) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", callable->ob_type->tp_name); - goto exit; - } - - tuple = _PyStack_AsTuple(args, nargs); - if (tuple == NULL) { - goto exit; + return NULL; } - result = (*call)(callable, tuple, kwargs); - Py_DECREF(tuple); - + argstuple = _PyStack_AsTuple(args, nargs); + if (argstuple == NULL) { + return NULL; + } + + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } + + result = (*call)(callable, argstuple, kwargs); + + Py_LeaveRecursiveCall(); + + Py_DECREF(argstuple); result = _Py_CheckFunctionResult(callable, result, NULL); + return result; } - -exit: - Py_LeaveRecursiveCall(); - - return result; } /* Positional arguments are obj followed by args: @@ -2495,9 +2493,11 @@ PyObject * _PyArg_ParseStackAndKeywords(). */ if (PyFunction_Check(callable)) { + /* Py_EnterRecursiveCall() is handled by _PyEval_EvalFrameDefault() */ return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); } if (PyCFunction_Check(callable)) { + /* Py_EnterRecursiveCall() is handled by _PyCFunction_FastCallKeywords() */ return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); } else { @@ -2505,49 +2505,48 @@ PyObject * temporary dictionary for keyword arguments (if any) */ ternaryfunc call; - PyObject *argtuple; + PyObject *argstuple; PyObject *kwdict, *result; Py_ssize_t nkwargs; - result = NULL; nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); assert((nargs == 0 && nkwargs == 0) || stack != NULL); - if (Py_EnterRecursiveCall(" while calling a Python object")) { - return NULL; - } - call = callable->ob_type->tp_call; if (call == NULL) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", callable->ob_type->tp_name); - goto exit; + return NULL; } - argtuple = _PyStack_AsTuple(stack, nargs); - if (argtuple == NULL) { - goto exit; + argstuple = _PyStack_AsTuple(stack, nargs); + if (argstuple == NULL) { + return NULL; } if (nkwargs > 0) { kwdict = _PyStack_AsDict(stack + nargs, kwnames); if (kwdict == NULL) { - Py_DECREF(argtuple); - goto exit; + Py_DECREF(argstuple); + return NULL; } } else { kwdict = NULL; } - result = (*call)(callable, argtuple, kwdict); - Py_DECREF(argtuple); + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } + + result = (*call)(callable, argstuple, kwdict); + + Py_LeaveRecursiveCall(); + + Py_DECREF(argstuple); Py_XDECREF(kwdict); result = _Py_CheckFunctionResult(callable, result, NULL); - - exit: - Py_LeaveRecursiveCall(); return result; } } diff -r ed0f83091003 Objects/methodobject.c --- a/Objects/methodobject.c Wed Jan 18 14:16:57 2017 +0100 +++ b/Objects/methodobject.c Wed Jan 18 14:19:30 2017 +0100 @@ -91,7 +91,7 @@ PyObject * Py_ssize_t nargs, PyObject *kwargs) { PyCFunction meth; - PyObject *result; + PyObject *result = NULL; int flags; PyObject *argstuple; @@ -108,15 +108,19 @@ PyObject * meth = method->ml_meth; flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); + 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 +134,7 @@ PyObject * 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) { @@ -151,7 +155,7 @@ PyObject * /* Slow-path: create a temporary tuple for positional arguments */ argstuple = _PyStack_AsTuple(args, nargs); if (argstuple == NULL) { - return NULL; + goto exit; } if (flags & METH_KEYWORDS) { @@ -170,7 +174,7 @@ PyObject * _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 +189,19 @@ PyObject * 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 * @@ -220,7 +226,7 @@ PyObject * { PyCFunctionObject *func; PyCFunction meth; - PyObject *self, *result; + PyObject *self, *result = NULL; Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); int flags; @@ -242,6 +248,10 @@ PyObject * self = PyCFunction_GET_SELF(func); flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } + switch (flags) { case METH_NOARGS: @@ -249,7 +259,7 @@ PyObject * PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", func->m_ml->ml_name, nargs); - return NULL; + goto exit; } if (nkwargs) { @@ -264,7 +274,7 @@ PyObject * PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", func->m_ml->ml_name, nargs); - return NULL; + goto exit; } if (nkwargs) { @@ -292,7 +302,7 @@ PyObject * argtuple = _PyStack_AsTuple(args, nargs); if (argtuple == NULL) { - return NULL; + goto exit; } if (flags & METH_KEYWORDS) { @@ -302,7 +312,7 @@ PyObject * kwdict = _PyStack_AsDict(args + nargs, kwnames); if (kwdict == NULL) { Py_DECREF(argtuple); - return NULL; + goto exit; } } else { @@ -323,17 +333,20 @@ PyObject * PyErr_SetString(PyExc_SystemError, "Bad call flags in _PyCFunction_FastCallKeywords. " "METH_OLDARGS is no longer supported!"); - return NULL; + goto exit; } result = _Py_CheckFunctionResult(func_obj, result, NULL); - return result; + goto exit; no_keyword_error: PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", func->m_ml->ml_name); - return NULL; + +exit: + Py_LeaveRecursiveCall(); + return result; } /* Methods (the standard built-in methods, that is) */