]> granicus.if.org Git - python/commitdiff
_PyStack_UnpackDict() now returns -1 on error
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 17 Jan 2017 00:57:29 +0000 (01:57 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 17 Jan 2017 00:57:29 +0000 (01:57 +0100)
Issue #29286. Change _PyStack_UnpackDict() prototype to be able to notify of
failure when args is NULL.

Include/abstract.h
Objects/abstract.c
Objects/methodobject.c

index 43bf251222d8a963dee2f983d57daae67a5c463a..961279d4700845388b2fdd9d8f7ef7c6ca9af8cf 100644 (file)
@@ -177,20 +177,23 @@ PyAPI_FUNC(PyObject *) _PyStack_AsDict(
     PyObject **values,
     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
-   args unchanged if kwargs is NULL or an empty dictionary.
+   Return 0 on success, raise an exception and return -1 on error.
+
+   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 type of keyword keys is not checked, these checks should be done
    later (ex: _PyArg_ParseStackAndKeywords). */
-PyAPI_FUNC(PyObject **) _PyStack_UnpackDict(
+PyAPI_FUNC(int) _PyStack_UnpackDict(
     PyObject **args,
     Py_ssize_t nargs,
     PyObject *kwargs,
-    PyObject **kwnames,
+    PyObject ***p_stack,
+    PyObject **p_kwnames,
     PyObject *func);
 
 /* Suggested size (number of positional arguments) for arrays of PyObject*
index 48fdf6541aa5bf433150b940f5311eef7d425272..ee50f02057e604353fa6dd7552ea798fab5fc6df 100644 (file)
@@ -2421,9 +2421,9 @@ _PyStack_AsDict(PyObject **values, PyObject *kwnames)
     return kwdict;
 }
 
-PyObject **
+int
 _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;
     Py_ssize_t nkwargs;
@@ -2435,25 +2435,26 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
     assert(kwargs == NULL || PyDict_CheckExact(kwargs));
 
     if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) {
+        *p_stack = args;
         *p_kwnames = NULL;
-        return args;
+        return 0;
     }
 
     if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) {
         PyErr_NoMemory();
-        return NULL;
+        return -1;
     }
 
     stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0]));
     if (stack == NULL) {
         PyErr_NoMemory();
-        return NULL;
+        return -1;
     }
 
     kwnames = PyTuple_New(nkwargs);
     if (kwnames == NULL) {
         PyMem_Free(stack);
-        return NULL;
+        return -1;
     }
 
     /* Copy position arguments (borrowed references) */
@@ -2472,8 +2473,9 @@ _PyStack_UnpackDict(PyObject **args, Py_ssize_t nargs, PyObject *kwargs,
         i++;
     }
 
+    *p_stack = stack;
     *p_kwnames = kwnames;
-    return stack;
+    return 0;
 }
 
 PyObject *
index 1e9ad0df9149bb12f9c1ee99bbc8d8842116dcd7..7bff6a037b06fb709747ad90f8978223c1b1b361 100644 (file)
@@ -240,8 +240,8 @@ _PyCFunction_FastCallDict(PyObject *func_obj, PyObject **args, Py_ssize_t nargs,
         PyObject *kwnames;
         _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
 
-        stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj);
-        if (stack == NULL) {
+        if (_PyStack_UnpackDict(args, nargs, kwargs,
+                                &stack, &kwnames, func_obj) < 0) {
             return NULL;
         }