diff options
author | Jeroen Demeyer <J.Demeyer@UGent.be> | 2019-08-16 12:41:27 +0200 |
---|---|---|
committer | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2019-08-16 03:41:27 -0700 |
commit | 0567786d26348aa7eaf0ab1b5d038fdabe409d92 (patch) | |
tree | fe7c90392253850b8a3111b3177188a8f255dc79 /Python | |
parent | f3cb68f2e4c3e0c405460f9bb881f5c1db70f535 (diff) | |
download | cpython-git-0567786d26348aa7eaf0ab1b5d038fdabe409d92.tar.gz |
bpo-37540: vectorcall: keyword names must be strings (GH-14682)
The fact that keyword names are strings is now part of the vectorcall and `METH_FASTCALL` protocols. The biggest concrete change is that `_PyStack_UnpackDict` now checks that and raises `TypeError` if not.
CC @markshannon @vstinner
https://bugs.python.org/issue37540
Diffstat (limited to 'Python')
-rw-r--r-- | Python/ceval.c | 24 | ||||
-rw-r--r-- | Python/getargs.c | 20 |
2 files changed, 12 insertions, 32 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 7c7359166d..ee03350031 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3504,7 +3504,9 @@ main_loop: PyObject **sp, *res, *names; names = POP(); - assert(PyTuple_CheckExact(names) && PyTuple_GET_SIZE(names) <= oparg); + assert(PyTuple_Check(names)); + assert(PyTuple_GET_SIZE(names) <= oparg); + /* We assume without checking that names contains only strings */ sp = stack_pointer; res = call_function(tstate, &sp, oparg, names); stack_pointer = sp; @@ -5372,20 +5374,12 @@ format_kwargs_error(PyThreadState *tstate, PyObject *func, PyObject *kwargs) _PyErr_Fetch(tstate, &exc, &val, &tb); if (val && PyTuple_Check(val) && PyTuple_GET_SIZE(val) == 1) { PyObject *key = PyTuple_GET_ITEM(val, 0); - if (!PyUnicode_Check(key)) { - _PyErr_Format(tstate, PyExc_TypeError, - "%.200s%.200s keywords must be strings", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func)); - } - else { - _PyErr_Format(tstate, PyExc_TypeError, - "%.200s%.200s got multiple " - "values for keyword argument '%U'", - PyEval_GetFuncName(func), - PyEval_GetFuncDesc(func), - key); - } + _PyErr_Format(tstate, PyExc_TypeError, + "%.200s%.200s got multiple " + "values for keyword argument '%S'", + PyEval_GetFuncName(func), + PyEval_GetFuncDesc(func), + key); Py_XDECREF(exc); Py_XDECREF(val); Py_XDECREF(tb); diff --git a/Python/getargs.c b/Python/getargs.c index 59f0fdabb7..cdc16d4730 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2043,11 +2043,7 @@ find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) if (kwname == key) { return kwstack[i]; } - if (!PyUnicode_Check(kwname)) { - /* ignore non-string keyword keys: - an error will be raised below */ - continue; - } + assert(PyUnicode_Check(kwname)); if (_PyUnicode_EQ(kwname, key)) { return kwstack[i]; } @@ -2275,16 +2271,11 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, j++; } - if (!PyUnicode_Check(keyword)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return cleanreturn(0, &freelist); - } match = PySequence_Contains(kwtuple, keyword); if (match <= 0) { if (!match) { PyErr_Format(PyExc_TypeError, - "'%U' is an invalid keyword " + "'%S' is an invalid keyword " "argument for %.200s%s", keyword, (parser->fname == NULL) ? "this function" : parser->fname, @@ -2505,16 +2496,11 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, j++; } - if (!PyUnicode_Check(keyword)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return NULL; - } match = PySequence_Contains(kwtuple, keyword); if (match <= 0) { if (!match) { PyErr_Format(PyExc_TypeError, - "'%U' is an invalid keyword " + "'%S' is an invalid keyword " "argument for %.200s%s", keyword, (parser->fname == NULL) ? "this function" : parser->fname, |