Skip to content

Commit 998c209

Browse files
committed
_PyStack_UnpackDict() now returns -1 on error
Issue python#29286. Change _PyStack_UnpackDict() prototype to be able to notify of failure when args is NULL.
1 parent 29d39cc commit 998c209

3 files changed

Lines changed: 19 additions & 14 deletions

File tree

Include/abstract.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,20 +177,23 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
177177
PyObject **values,
178178
PyObject *kwnames);
179179

180-
/* Convert (args, nargs, kwargs) into a (stack, nargs, kwnames).
180+
/* Convert (args, nargs, kwargs: dict) into a (stack, nargs, kwnames: tuple).
181181
182-
Return a new stack which should be released by PyMem_Free(), or return
183-
args unchanged if kwargs is NULL or an empty dictionary.
182+
Return 0 on success, raise an exception and return -1 on error.
183+
184+
Write the new stack into *p_stack. If *p_stack is differen than args, it
185+
must be released by PyMem_Free().
184186
185187
The stack uses borrowed references.
186188
187189
The type of keyword keys is not checked, these checks should be done
188190
later (ex: _PyArg_ParseStackAndKeywords). */
189-
PyAPI_FUNC(PyObject **) _PyStack_UnpackDict(
191+
PyAPI_FUNC(int) _PyStack_UnpackDict(
190192
PyObject **args,
191193
Py_ssize_t nargs,
192194
PyObject *kwargs,
193-
PyObject **kwnames,
195+
PyObject ***p_stack,
196+
PyObject **p_kwnames,
194197
PyObject *func);
195198

196199
/* Suggested size (number of positional arguments) for arrays of PyObject*

Objects/abstract.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2421,9 +2421,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
24212421
return kwdict;
24222422
}
24232423

2424-
PyObject **
2424+
int
24252425
_PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2426-
PyObject **p_kwnames, PyObject *func)
2426+
PyObject ***p_stack, PyObject **p_kwnames, PyObject *func)
24272427
{
24282428
PyObject **stack, **kwstack;
24292429
Py_ssize_t nkwargs;
@@ -2435,25 +2435,26 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
24352435
assert(kwargs == NULL || PyDict_CheckExact(kwargs));
24362436

24372437
if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
2438+
*p_stack = args;
24382439
*p_kwnames = NULL;
2439-
return args;
2440+
return 0;
24402441
}
24412442

24422443
if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
24432444
PyErr_NoMemory();
2444-
return NULL;
2445+
return -1;
24452446
}
24462447

24472448
stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
24482449
if (stack == NULL) {
24492450
PyErr_NoMemory();
2450-
return NULL;
2451+
return -1;
24512452
}
24522453

24532454
kwnames = PyTuple_New(nkwargs);
24542455
if (kwnames == NULL) {
24552456
PyMem_Free(stack);
2456-
return NULL;
2457+
return -1;
24572458
}
24582459

24592460
/* Copy position arguments (borrowed references) */
@@ -2472,8 +2473,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
24722473
i++;
24732474
}
24742475

2476+
*p_stack = stack;
24752477
*p_kwnames = kwnames;
2476-
return stack;
2478+
return 0;
24772479
}
24782480

24792481
PyObject *

Objects/methodobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
240240
PyObject *kwnames;
241241
_PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
242242

243-
stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj);
244-
if (stack == NULL) {
243+
if (_PyStack_UnpackDict(args, nargs, kwargs,
244+
&stack, &kwnames, func_obj) < 0) {
245245
return NULL;
246246
}
247247

0 commit comments

Comments
 (0)