cpython: 288ec55f1912 (original) (raw)
--- a/Python/ceval.c +++ b/Python/ceval.c @@ -3793,12 +3793,13 @@ static PyObject * PyFrameObject *f; PyObject *retval = NULL; PyObject **fastlocals, **freevars;
if (globals == NULL) { PyErr_SetString(PyExc_SystemError, @@ -3806,36 +3807,50 @@ static PyObject * return NULL; }
- /* Create a dictionary for keyword parameters (**kwags) */ if (co->co_flags & CO_VARKEYWORDS) { kwdict = PyDict_New(); if (kwdict == NULL) goto fail; i = total_args;
if (co->co_flags & CO_VARARGS)[](#l1.45)
if (co->co_flags & CO_VARARGS) {[](#l1.46) i++;[](#l1.47)
}}[](#l1.48) SETLOCAL(i, kwdict);[](#l1.49)
- /* Copy positional arguments into local variables */
- if (argcount > co->co_argcount) { n = co->co_argcount;
- }
- else {
n = argcount;[](#l1.61)
- } for (i = 0; i < n; i++) { x = args[i]; Py_INCREF(x); SETLOCAL(i, x); } +
- /* Pack other positional arguments into the *args argument */ if (co->co_flags & CO_VARARGS) { u = PyTuple_New(argcount - n);
if (u == NULL)[](#l1.72)
if (u == NULL) {[](#l1.73) goto fail;[](#l1.74)
}[](#l1.75) SETLOCAL(total_args, u);[](#l1.76) for (i = n; i < argcount; i++) {[](#l1.77) x = args[i];[](#l1.78)
@@ -3843,17 +3858,21 @@ static PyObject * PyTuple_SET_ITEM(u, i-n, x); } } +
- /* Handle keyword arguments (passed as an array of (key, value)) */ for (i = 0; i < kwcount; i++) { PyObject **co_varnames; PyObject keyword = kws[2i]; PyObject value = kws[2i + 1]; int j;
+ if (keyword == NULL || !PyUnicode_Check(keyword)) { PyErr_Format(PyExc_TypeError, "%U() keywords must be strings", co->co_name); goto fail; } + /* Speed hack: do raw pointer compares. As names are normally interned this should almost always hit. */ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; @@ -3862,6 +3881,7 @@ static PyObject if (nm == keyword) goto kw_found; } + / Slow fallback, just in case */ for (j = 0; j < total_args; j++) { PyObject *nm = co_varnames[j]; @@ -3872,6 +3892,7 @@ static PyObject * else if (cmp < 0) goto fail; } + if (j >= total_args && kwdict == NULL) { PyErr_Format(PyExc_TypeError, "%U() got an unexpected " @@ -3880,10 +3901,12 @@ static PyObject * keyword); goto fail; } + if (PyDict_SetItem(kwdict, keyword, value) == -1) { goto fail; } continue; + kw_found: if (GETLOCAL(j) != NULL) { PyErr_Format(PyExc_TypeError, @@ -3896,10 +3919,14 @@ static PyObject * Py_INCREF(value); SETLOCAL(j, value); } +
- /* Check the number of positional arguments */ if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { too_many_positional(co, argcount, defcount, fastlocals); goto fail; } +
- /* Add missing positional arguments (copy default values from defs) */ if (argcount < co->co_argcount) { int m = co->co_argcount - defcount; int missing = 0;
@@ -3922,6 +3949,8 @@ static PyObject * } } } +
- /* Add missing keyword arguments (copy default values from kwdefs) */ if (co->co_kwonlyargcount > 0) { int missing = 0; for (i = co->co_argcount; i < total_args; i++) {
@@ -3964,12 +3993,15 @@ static PyObject * goto fail; SETLOCAL(co->co_nlocals + i, c); } +
- /* Copy closure variables to free variables */ for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { PyObject *o = PyTuple_GET_ITEM(closure, i); Py_INCREF(o); freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; }
- /* Handle generator/coroutine */ if (co->co_flags & (CO_GENERATOR | CO_COROUTINE)) { PyObject *gen; PyObject *coro_wrapper = tstate->coroutine_wrapper;