_PyStack_UnpackDict() now returns -1 on error

Issue #29286. Change _PyStack_UnpackDict() prototype to be able to notify of
failure when args is NULL.
This commit is contained in:
Victor Stinner 2017-01-17 01:57:29 +01:00
parent 29d39cc8f5
commit 998c20962c
3 changed files with 19 additions and 14 deletions

View File

@ -177,20 +177,23 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
PyObject **values, PyObject **values,
PyObject *kwnames); PyObject *kwnames);
/* Convert (args, nargs, kwargs) into a (stack, nargs, kwnames). /* Convert (args, nargs, kwargs: dict) into a (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_ParseStackAndKeywords). */ 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 **p_kwnames,
PyObject *func); PyObject *func);
/* Suggested size (number of positional arguments) for arrays of PyObject* /* Suggested size (number of positional arguments) for arrays of PyObject*

View File

@ -2421,9 +2421,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 *func)
{ {
PyObject **stack, **kwstack; PyObject **stack, **kwstack;
Py_ssize_t nkwargs; Py_ssize_t nkwargs;
@ -2435,25 +2435,26 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
assert(kwargs == NULL || PyDict_CheckExact(kwargs)); assert(kwargs == NULL || PyDict_CheckExact(kwargs));
if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) { if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
*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) */
@ -2472,8 +2473,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

@ -240,8 +240,8 @@ _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,
if (stack == NULL) { &stack, &kwnames, func_obj) < 0) {
return NULL; return NULL;
} }