@@ -322,8 +322,7 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,
322322 assert (nargs  >= 0 );
323323 assert (kwnames  ==  NULL  ||  PyTuple_CheckExact (kwnames ));
324324 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 */ 
327326
328327 if  (co -> co_kwonlyargcount  ==  0  &&  nkwargs  ==  0  && 
329328 (co -> co_flags  &  ~PyCF_MASK ) ==  (CO_OPTIMIZED  | CO_NEWLOCALS  | CO_NOFREE ))
@@ -943,12 +942,12 @@ _PyStack_AsDict(PyObject *const *values, PyObject *kwnames)
943942 vector; return NULL with exception set on error. Return the keyword names 
944943 tuple in *p_kwnames. 
945944
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. 
947947
948-  When done, you must call _PyStack_UnpackDict_Free(stack, nargs, kwnames)  
948+  The newly allocated argument vector supports PY_VECTORCALL_ARGUMENTS_OFFSET.  
949949
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) */ 
952951static  PyObject  * const  * 
953952_PyStack_UnpackDict (PyObject  * const  * args , Py_ssize_t  nargs , PyObject  * kwargs ,
954953 PyObject  * * p_kwnames )
@@ -994,14 +993,28 @@ _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs,
994993 called in the performance critical hot code. */ 
995994 Py_ssize_t  pos  =  0 , i  =  0 ;
996995 PyObject  * key , * value ;
996+  unsigned long  keys_are_strings  =  Py_TPFLAGS_UNICODE_SUBCLASS ;
997997 while  (PyDict_Next (kwargs , & pos , & key , & value )) {
998+  keys_are_strings  &= Py_TYPE (key )-> tp_flags ;
998999 Py_INCREF (key );
9991000 Py_INCREF (value );
10001001 PyTuple_SET_ITEM (kwnames , i , key );
10011002 kwstack [i ] =  value ;
10021003 i ++ ;
10031004 }
10041005
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+ 
10051018 * p_kwnames  =  kwnames ;
10061019 return  stack ;
10071020}
0 commit comments