diff --git a/Objects/call.c b/Objects/call.c index af42fc8f7f2dbf..4b1b4bd52a2e56 100644 --- a/Objects/call.c +++ b/Objects/call.c @@ -935,6 +935,10 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames) The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET. + The positional arguments are borrowed references from the input array + (which must be kept alive by the caller). The keyword argument values + are new references. + When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */ PyObject *const * _PyStack_UnpackDict(PyThreadState *tstate, @@ -970,9 +974,9 @@ _PyStack_UnpackDict(PyThreadState *tstate, stack++; /* For PY_VECTORCALL_ARGUMENTS_OFFSET */ - /* Copy positional arguments */ + /* Copy positional arguments (borrowed references) */ for (Py_ssize_t i = 0; i < nargs; i++) { - stack[i] = Py_NewRef(args[i]); + stack[i] = args[i]; } PyObject **kwstack = stack + nargs; @@ -1009,9 +1013,10 @@ void _PyStack_UnpackDict_Free(PyObject *const *stack, Py_ssize_t nargs, PyObject *kwnames) { - Py_ssize_t n = PyTuple_GET_SIZE(kwnames) + nargs; - for (Py_ssize_t i = 0; i < n; i++) { - Py_DECREF(stack[i]); + /* Only decref kwargs values, positional args are borrowed */ + Py_ssize_t nkwargs = PyTuple_GET_SIZE(kwnames); + for (Py_ssize_t i = 0; i < nkwargs; i++) { + Py_DECREF(stack[nargs + i]); } _PyStack_UnpackDict_FreeNoDecRef(stack, kwnames); } diff --git a/Python/ceval.c b/Python/ceval.c index c59f20bbf1e803..590b315ab65c2c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2000,11 +2000,16 @@ _PyEvalFramePushAndInit_Ex(PyThreadState *tstate, _PyStackRef func, PyStackRef_CLOSE(func); goto error; } - size_t total_args = nargs + PyDict_GET_SIZE(kwargs); + size_t nkwargs = PyDict_GET_SIZE(kwargs); assert(sizeof(PyObject *) == sizeof(_PyStackRef)); newargs = (_PyStackRef *)object_array; - for (size_t i = 0; i < total_args; i++) { - newargs[i] = PyStackRef_FromPyObjectSteal(object_array[i]); + /* Positional args are borrowed from callargs tuple, need new reference */ + for (Py_ssize_t i = 0; i < nargs; i++) { + newargs[i] = PyStackRef_FromPyObjectNew(object_array[i]); + } + /* Keyword args are owned by _PyStack_UnpackDict, steal them */ + for (size_t i = 0; i < nkwargs; i++) { + newargs[nargs + i] = PyStackRef_FromPyObjectSteal(object_array[nargs + i]); } } else {