From: Victor Stinner Date: Fri, 9 Jun 2017 11:24:53 +0000 (+0200) Subject: bpo-30524: Fix _PyStack_UnpackDict() (#1886) X-Git-Tag: v3.6.2rc1~81 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f0ff849adc6b4a01f9d1f08d9ad0f1511ff84541;p=python bpo-30524: Fix _PyStack_UnpackDict() (#1886) * bpo-29259: Remove unused func parameter of _PyStack_UnpackDict() * bpo-29286: Change _PyStack_UnpackDict() prototype to be able to notify of failure when args is NULL. _PyStack_UnpackDict() now returns -1 on error. --- diff --git a/Include/abstract.h b/Include/abstract.h index 7d137a22bf..6bb76ec95f 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -290,21 +290,23 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/ PyObject **values, PyObject *kwnames); - /* Convert (args, nargs, kwargs) into a (stack, nargs, kwnames). + /* Convert (args, nargs, kwargs: dict) into (stack, nargs, kwnames: tuple). - Return a new stack which should be released by PyMem_Free(), or return - args unchanged if kwargs is NULL or an empty dictionary. + Return 0 on success, raise an exception and return -1 on error. + + Write the new stack into *p_stack. If *p_stack is differen than args, it + must be released by PyMem_Free(). The stack uses borrowed references. The type of keyword keys is not checked, these checks should be done - later (ex: _PyArg_ParseStack). */ - PyAPI_FUNC(PyObject **) _PyStack_UnpackDict( + later (ex: _PyArg_ParseStackAndKeywords). */ + PyAPI_FUNC(int) _PyStack_UnpackDict( PyObject **args, Py_ssize_t nargs, PyObject *kwargs, - PyObject **kwnames, - PyObject *func); + PyObject ***p_stack, + PyObject **p_kwnames); /* Call the callable object func with the "fast call" calling convention: args is a C array for positional arguments (nargs is the number of diff --git a/Objects/abstract.c b/Objects/abstract.c index d838856d45..3585b34ca4 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2389,9 +2389,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames) return kwdict; } -PyObject ** +int _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, - PyObject **p_kwnames, PyObject *func) + PyObject ***p_stack, PyObject **p_kwnames) { PyObject **stack, **kwstack; Py_ssize_t nkwargs; @@ -2402,27 +2402,27 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, assert(nargs >= 0); assert(kwargs == NULL || PyDict_CheckExact(kwargs)); - nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0; - if (!nkwargs) { + if (kwargs == NULL || (nkwargs = PyDict_Size(kwargs)) == 0) { + *p_stack = args; *p_kwnames = NULL; - return args; + return 0; } if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) { PyErr_NoMemory(); - return NULL; + return -1; } stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0])); if (stack == NULL) { PyErr_NoMemory(); - return NULL; + return -1; } kwnames = PyTuple_New(nkwargs); if (kwnames == NULL) { PyMem_Free(stack); - return NULL; + return -1; } /* Copy position arguments (borrowed references) */ @@ -2441,8 +2441,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, i++; } + *p_stack = stack; *p_kwnames = kwnames; - return stack; + return 0; } PyObject * diff --git a/Objects/methodobject.c b/Objects/methodobject.c index c2001f0169..fe52545667 100644 --- a/Objects/methodobject.c +++ b/Objects/methodobject.c @@ -243,8 +243,7 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs, PyObject *kwnames; _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth; - stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj); - if (stack == NULL) { + if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) { return NULL; }