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.
This commit is contained in:
Victor Stinner 2017-06-09 13:24:53 +02:00 committed by GitHub
parent 570b1c971c
commit f0ff849adc
3 changed files with 20 additions and 18 deletions

View file

@ -290,21 +290,23 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
PyObject **values, PyObject **values,
PyObject *kwnames); 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 Return 0 on success, raise an exception and return -1 on error.
args unchanged if kwargs is NULL or an empty dictionary.
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 stack uses borrowed references.
The type of keyword keys is not checked, these checks should be done The type of keyword keys is not checked, these checks should be done
later (ex: _PyArg_ParseStack). */ later (ex: _PyArg_ParseStackAndKeywords). */
PyAPI_FUNC(PyObject **) _PyStack_UnpackDict( PyAPI_FUNC(int) _PyStack_UnpackDict(
PyObject **args, PyObject **args,
Py_ssize_t nargs, Py_ssize_t nargs,
PyObject *kwargs, PyObject *kwargs,
PyObject **kwnames, PyObject ***p_stack,
PyObject *func); PyObject **p_kwnames);
/* Call the callable object func with the "fast call" calling convention: /* Call the callable object func with the "fast call" calling convention:
args is a C array for positional arguments (nargs is the number of args is a C array for positional arguments (nargs is the number of

View file

@ -2389,9 +2389,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
return kwdict; return kwdict;
} }
PyObject ** int
_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs, _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
PyObject **p_kwnames, PyObject *func) PyObject ***p_stack, PyObject **p_kwnames)
{ {
PyObject **stack, **kwstack; PyObject **stack, **kwstack;
Py_ssize_t nkwargs; Py_ssize_t nkwargs;
@ -2402,27 +2402,27 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
assert(nargs >= 0); assert(nargs >= 0);
assert(kwargs == NULL || PyDict_CheckExact(kwargs)); assert(kwargs == NULL || PyDict_CheckExact(kwargs));
nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0; if (kwargs == NULL || (nkwargs = PyDict_Size(kwargs)) == 0) {
if (!nkwargs) { *p_stack = args;
*p_kwnames = NULL; *p_kwnames = NULL;
return args; return 0;
} }
if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) { if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return -1;
} }
stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0])); stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
if (stack == NULL) { if (stack == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
return NULL; return -1;
} }
kwnames = PyTuple_New(nkwargs); kwnames = PyTuple_New(nkwargs);
if (kwnames == NULL) { if (kwnames == NULL) {
PyMem_Free(stack); PyMem_Free(stack);
return NULL; return -1;
} }
/* Copy position arguments (borrowed references) */ /* Copy position arguments (borrowed references) */
@ -2441,8 +2441,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
i++; i++;
} }
*p_stack = stack;
*p_kwnames = kwnames; *p_kwnames = kwnames;
return stack; return 0;
} }
PyObject * PyObject *

View file

@ -243,8 +243,7 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
PyObject *kwnames; PyObject *kwnames;
_PyCFunctionFast fastmeth = (_PyCFunctionFast)meth; _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj); if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
if (stack == NULL) {
return NULL; return NULL;
} }