bpo-30524: Fix _PyStack_UnpackDict() (#1886) · python/cpython@f0ff849 (original) (raw)

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -290,21 +290,23 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
290 290 PyObject **values,
291 291 PyObject *kwnames);
292 292
293 -/* Convert (args, nargs, kwargs) into a (stack, nargs, kwnames).
293 +/* Convert (args, nargs, kwargs: dict) into (stack, nargs, kwnames: tuple).
294 294
295 - Return a new stack which should be released by PyMem_Free(), or return
296 - args unchanged if kwargs is NULL or an empty dictionary.
295 + Return 0 on success, raise an exception and return -1 on error.
296 +
297 + Write the new stack into *p_stack. If *p_stack is differen than args, it
298 + must be released by PyMem_Free().
297 299
298 300 The stack uses borrowed references.
299 301
300 302 The type of keyword keys is not checked, these checks should be done
301 - later (ex: _PyArg_ParseStack). */
302 -PyAPI_FUNC(PyObject **) _PyStack_UnpackDict(
303 + later (ex: _PyArg_ParseStackAndKeywords). */
304 +PyAPI_FUNC(int) _PyStack_UnpackDict(
303 305 PyObject **args,
304 306 Py_ssize_t nargs,
305 307 PyObject *kwargs,
306 -PyObject **kwnames,
307 -PyObject *func);
308 +PyObject ***p_stack,
309 +PyObject **p_kwnames);
308 310
309 311 /* Call the callable object func with the "fast call" calling convention:
310 312 args is a C array for positional arguments (nargs is the number of
Original file line number Diff line number Diff line change
@@ -2389,9 +2389,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
2389 2389 return kwdict;
2390 2390 }
2391 2391
2392 -PyObject **
2392 +int
2393 2393 _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2394 -PyObject **p_kwnames, PyObject *func)
2394 +PyObject ***p_stack, PyObject **p_kwnames)
2395 2395 {
2396 2396 PyObject **stack, **kwstack;
2397 2397 Py_ssize_t nkwargs;
@@ -2402,27 +2402,27 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2402 2402 assert(nargs >= 0);
2403 2403 assert(kwargs == NULL |
2404 2404
2405 -nkwargs = (kwargs != NULL) ? PyDict_Size(kwargs) : 0;
2406 -if (!nkwargs) {
2405 +if (kwargs == NULL |
2406 + *p_stack = args;
2407 2407 *p_kwnames = NULL;
2408 -return args;
2408 +return 0;
2409 2409 }
2410 2410
2411 2411 if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
2412 2412 PyErr_NoMemory();
2413 -return NULL;
2413 +return -1;
2414 2414 }
2415 2415
2416 2416 stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
2417 2417 if (stack == NULL) {
2418 2418 PyErr_NoMemory();
2419 -return NULL;
2419 +return -1;
2420 2420 }
2421 2421
2422 2422 kwnames = PyTuple_New(nkwargs);
2423 2423 if (kwnames == NULL) {
2424 2424 PyMem_Free(stack);
2425 -return NULL;
2425 +return -1;
2426 2426 }
2427 2427
2428 2428 /* Copy position arguments (borrowed references) */
@@ -2441,8 +2441,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
2441 2441 i++;
2442 2442 }
2443 2443
2444 +*p_stack = stack;
2444 2445 *p_kwnames = kwnames;
2445 -return stack;
2446 +return 0;
2446 2447 }
2447 2448
2448 2449 PyObject *
Original file line number Diff line number Diff line change
@@ -243,8 +243,7 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
243 243 PyObject *kwnames;
244 244 _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
245 245
246 -stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj);
247 -if (stack == NULL) {
246 +if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
248 247 return NULL;
249 248 }
250 249