@@ -1032,9 +1032,9 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
10321032 char * fname , * message ;
10331033 int min , max ;
10341034 char * formatsave ;
1035- int i , len , nargs , nkeywords ;
1035+ int i , len , nargs , nkeywords , nkwlist ;
10361036 char * msg , * ks , * * p ;
1037- int nkwlist , pos , match , converted ;
1037+ int pos , match , converted ;
10381038 PyObject * key , * value ;
10391039
10401040 assert (args != NULL && PyTuple_Check (args ));
@@ -1048,15 +1048,24 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
10481048 name <- routine name, if any (else NULL).
10491049 min <- # of required arguments, or -1 if all are required.
10501050 max <- most arguments (required + optional).
1051+ Check that kwlist has a non-NULL entry for each arg.
10511052 Raise error if a tuple arg spec is found.
10521053 */
10531054 fname = message = NULL ;
10541055 formatsave = format ;
1056+ p = kwlist ;
10551057 min = -1 ;
10561058 max = 0 ;
10571059 while ((i = * format ++ ) != '\0' ) {
1058- if (isalpha (i ) && i != 'e' )
1060+ if (isalpha (i ) && i != 'e' ) {
10591061 max ++ ;
1062+ if (* p == NULL ) {
1063+ /* kwlist is too short */
1064+ PyErr_BadInternalCall ();
1065+ return 0 ;
1066+ }
1067+ p ++ ;
1068+ }
10601069 else if (i == '|' )
10611070 min = max ;
10621071 else if (i == ':' ) {
@@ -1072,13 +1081,19 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
10721081 "tuple found in format when using keyword arguments" );
10731082 return 0 ;
10741083 }
1075- }
1084+ }
1085+ format = formatsave ;
1086+ if (* p != NULL ) {
1087+ /* kwlist is too long */
1088+ PyErr_BadInternalCall ();
1089+ return 0 ;
1090+ }
10761091 if (min < 0 ) {
10771092 /* All arguments are required. */
10781093 min = max ;
10791094 }
1080- format = formatsave ;
10811095
1096+ nkwlist = max ;
10821097 nargs = PyTuple_GET_SIZE (args );
10831098 nkeywords = keywords == NULL ? 0 : PyDict_Size (keywords );
10841099
@@ -1103,9 +1118,11 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
11031118 }
11041119
11051120 /* required arguments missing from args can be supplied by keyword
1106- arguments */
1121+ arguments; set len to the number of posiitional arguments, and,
1122+ if that's less than the minimum required, add in the number of
1123+ required arguments that are supplied by keywords */
11071124 len = nargs ;
1108- if (keywords && nargs < min ) {
1125+ if (nkeywords > 0 && nargs < min ) {
11091126 for (i = nargs ; i < min ; i ++ ) {
11101127 if (PyDict_GetItemString (keywords , kwlist [i ]))
11111128 len ++ ;
@@ -1118,7 +1135,6 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
11181135 is a little confusing with keywords since keyword arguments
11191136 which are supplied, but don't match the required arguments
11201137 are not included in the "%d given" part of the message */
1121-
11221138 if (len < min || max < len ) {
11231139 if (message == NULL ) {
11241140 sprintf (msgbuf ,
@@ -1151,18 +1167,6 @@ vgetargskeywords(PyObject *args, PyObject *keywords, char *format,
11511167 if (nkeywords == 0 )
11521168 return 1 ;
11531169
1154- /* make sure the number of keywords in the keyword list matches the
1155- number of items in the format string */
1156- nkwlist = 0 ;
1157- p = kwlist ;
1158- while (* p ++ )
1159- nkwlist ++ ;
1160- if (nkwlist != max ) {
1161- PyErr_SetString (PyExc_SystemError ,
1162- "number of items in format string and keyword list do not match" );
1163- return 0 ;
1164- }
1165-
11661170 /* convert the keyword arguments; this uses the format
11671171 string where it was left after processing args */
11681172 converted = 0 ;
0 commit comments