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 |