From 96c7c0685045b739fdc5145018cddfd252155713 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Thu, 15 Jun 2017 17:05:23 +0200 Subject: [PATCH] bpo-20627: Fix error message when keyword arguments are used (#2115) --- Lib/test/test_call.py | 26 ++++++++++++++++++++++++++ Modules/_hashopenssl.c | 4 ++-- Modules/_struct.c | 20 ++++++++++++++------ Python/bltinmodule.c | 12 ++++++------ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/Lib/test/test_call.py b/Lib/test/test_call.py index f46eb2142f1..ca678b9deb7 100644 --- a/Lib/test/test_call.py +++ b/Lib/test/test_call.py @@ -5,6 +5,8 @@ try: import _testcapi except ImportError: _testcapi = None +import struct +import collections # The test cases here cover several paths through the function calling # code. They depend on the METH_XXX flag that is used to define a C @@ -160,6 +162,30 @@ class CFunctionCallsErrorMessages(unittest.TestCase): msg = r"^hasattr\(\) takes no keyword arguments$" self.assertRaisesRegex(TypeError, msg, hasattr, x=2) + def test_varargs6_kw(self): + msg = r"^getattr\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, getattr, x=2) + + def test_varargs7_kw(self): + msg = r"^next\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, next, x=2) + + def test_varargs8_kw(self): + msg = r"^pack\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, struct.pack, x=2) + + def test_varargs9_kw(self): + msg = r"^pack_into\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, struct.pack_into, x=2) + + def test_varargs10_kw(self): + msg = r"^index\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, collections.deque().index, x=2) + + def test_varargs11_kw(self): + msg = r"^pack\(\) takes no keyword arguments$" + self.assertRaisesRegex(TypeError, msg, struct.Struct.pack, struct.Struct(""), x=2) + def test_oldargs0_1(self): msg = r"keys\(\) takes no arguments \(1 given\)" self.assertRaisesRegex(TypeError, msg, {}.keys, 0) diff --git a/Modules/_hashopenssl.c b/Modules/_hashopenssl.c index c83ebae4542..5096f93818d 100644 --- a/Modules/_hashopenssl.c +++ b/Modules/_hashopenssl.c @@ -931,11 +931,11 @@ generate_hash_name_list(void) Py_buffer view = { 0 }; \ PyObject *ret_obj; \ \ - if (!_PyArg_ParseStack(args, nargs, "|O:" #NAME , &data_obj)) { \ + if (!_PyArg_NoStackKeywords(#NAME, kwnames)) { \ return NULL; \ } \ \ - if (!_PyArg_NoStackKeywords(#NAME, kwnames)) { \ + if (!_PyArg_ParseStack(args, nargs, "|O:" #NAME , &data_obj)) { \ return NULL; \ } \ \ diff --git a/Modules/_struct.c b/Modules/_struct.c index 5b74ec5b492..46e7b4071b9 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1823,6 +1823,9 @@ s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) PyObject *result; /* Validate arguments. */ + if (!_PyArg_NoStackKeywords("pack", kwnames)) { + return NULL; + } soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); @@ -1832,9 +1835,6 @@ s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) "pack expected %zd items for packing (got %zd)", soself->s_len, nargs); return NULL; } - if (!_PyArg_NoStackKeywords("pack", kwnames)) { - return NULL; - } /* Allocate a new buffer */ result = PyBytes_FromStringAndSize((char *)NULL, soself->s_size); @@ -1866,6 +1866,9 @@ s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames Py_ssize_t offset; /* Validate arguments. +1 is for the first arg as buffer. */ + if (!_PyArg_NoStackKeywords("pack_into", kwnames)) { + return NULL; + } soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); @@ -1886,9 +1889,6 @@ s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames } return NULL; } - if (!_PyArg_NoStackKeywords("pack_into", kwnames)) { - return NULL; - } /* Extract a writable memory buffer from the first argument */ if (!PyArg_Parse(args[0], "w*", &buffer)) @@ -2131,6 +2131,10 @@ pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) PyObject *s_object = NULL; PyObject *format, *result; + if (!_PyArg_NoStackKeywords("pack", kwnames)) { + return NULL; + } + if (nargs == 0) { PyErr_SetString(PyExc_TypeError, "missing format argument"); return NULL; @@ -2159,6 +2163,10 @@ pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) PyObject *s_object = NULL; PyObject *format, *result; + if (!_PyArg_NoStackKeywords("pack_into", kwnames)) { + return NULL; + } + if (nargs == 0) { PyErr_SetString(PyExc_TypeError, "missing format argument"); return NULL; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index f7690b17ff4..d16b1b4407a 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -997,13 +997,13 @@ builtin_getattr(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *v, *result, *dflt = NULL; PyObject *name; - if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt)) - return NULL; - if (!_PyArg_NoStackKeywords("getattr", kwnames)) { return NULL; } + if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt)) + return NULL; + if (!PyUnicode_Check(name)) { PyErr_SetString(PyExc_TypeError, "getattr(): attribute name must be string"); @@ -1307,13 +1307,13 @@ builtin_next(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *it, *res; PyObject *def = NULL; - if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def)) - return NULL; - if (!_PyArg_NoStackKeywords("next", kwnames)) { return NULL; } + if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def)) + return NULL; + if (!PyIter_Check(it)) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not an iterator",