@@ -322,8 +322,7 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,
322
322
assert (nargs >= 0 );
323
323
assert (kwnames == NULL || PyTuple_CheckExact (kwnames ));
324
324
assert ((nargs == 0 && nkwargs == 0 ) || stack != NULL );
325
- /* kwnames must only contains str strings, no subclass, and all keys must
326
- be unique */
325
+ /* kwnames must only contain strings and all keys must be unique */
327
326
328
327
if (co -> co_kwonlyargcount == 0 && nkwargs == 0 &&
329
328
(co -> co_flags & ~PyCF_MASK ) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE ))
@@ -943,12 +942,12 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames)
943
942
vector; return NULL with exception set on error. Return the keyword names
944
943
tuple in *p_kwnames.
945
944
946
- The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET.
945
+ This also checks that all keyword names are strings. If not, a TypeError is
946
+ raised.
947
947
948
- When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames)
948
+ The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET.
949
949
950
- The type of keyword keys is not checked, these checks should be done
951
- later (ex: _PyArg_ParseStackAndKeywords). */
950
+ When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames) */
952
951
static PyObject * const *
953
952
_PyStack_UnpackDict (PyObject * const * args , Py_ssize_t nargs , PyObject * kwargs ,
954
953
PyObject * * p_kwnames )
@@ -994,14 +993,28 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
994
993
called in the performance critical hot code. */
995
994
Py_ssize_t pos = 0 , i = 0 ;
996
995
PyObject * key , * value ;
996
+ unsigned long keys_are_strings = Py_TPFLAGS_UNICODE_SUBCLASS ;
997
997
while (PyDict_Next (kwargs , & pos , & key , & value )) {
998
+ keys_are_strings &= Py_TYPE (key )-> tp_flags ;
998
999
Py_INCREF (key );
999
1000
Py_INCREF (value );
1000
1001
PyTuple_SET_ITEM (kwnames , i , key );
1001
1002
kwstack [i ] = value ;
1002
1003
i ++ ;
1003
1004
}
1004
1005
1006
+ /* keys_are_strings has the value Py_TPFLAGS_UNICODE_SUBCLASS if that
1007
+ * flag is set for all keys. Otherwise, keys_are_strings equals 0.
1008
+ * We do this check once at the end instead of inside the loop above
1009
+ * because it simplifies the deallocation in the failing case.
1010
+ * It happens to also make the loop above slightly more efficient. */
1011
+ if (!keys_are_strings ) {
1012
+ PyErr_SetString (PyExc_TypeError ,
1013
+ "keywords must be strings" );
1014
+ _PyStack_UnpackDict_Free (stack , nargs , kwnames );
1015
+ return NULL ;
1016
+ }
1017
+
1005
1018
* p_kwnames = kwnames ;
1006
1019
return stack ;
1007
1020
}
0 commit comments