diff Python/getargs.c @ 20720:aaefc2f21bae legacy-trunk

vgetargskeywords: Verify kwlist has the required length while parsing the format, instead of waiting until after we can overindex it by mistake.
author Tim Peters <tim.peters@gmail.com>
date Sat, 27 Oct 2001 06:42:16 +0000
parents c6384591d846
children acb854b897bb
line wrap: on
line diff
--- a/Python/getargs.c	Sat Oct 27 06:16:31 2001 +0000
+++ b/Python/getargs.c	Sat Oct 27 06:42:16 2001 +0000
@@ -1032,9 +1032,9 @@
 	char *fname, *message;
 	int min, max;
 	char *formatsave;
-	int i, len, nargs, nkeywords;
+	int i, len, nargs, nkeywords, nkwlist;
 	char *msg, *ks, **p;
-	int nkwlist, pos, match, converted;
+	int pos, match, converted;
 	PyObject *key, *value;
 
 	assert(args != NULL && PyTuple_Check(args));
@@ -1048,15 +1048,24 @@
 	   name <- routine name, if any (else NULL).
 	   min <- # of required arguments, or -1 if all are required.
 	   max <- most arguments (required + optional).
+	   Check that kwlist has a non-NULL entry for each arg.
 	   Raise error if a tuple arg spec is found.
 	*/
 	fname = message = NULL;
 	formatsave = format;
+	p = kwlist;
 	min = -1;
 	max = 0;
 	while ((i = *format++) != '\0') {
-		if (isalpha(i) && i != 'e')
+		if (isalpha(i) && i != 'e') {
 			max++;
+			if (*p == NULL) {
+				/* kwlist is too short */
+				PyErr_BadInternalCall();
+				return 0;
+			}
+			p++;
+		}
 		else if (i == '|')
 			min = max;
 		else if (i == ':') {
@@ -1072,13 +1081,19 @@
 		      "tuple found in format when using keyword arguments");
 			return 0;
 		}
-	}	
+	}
+	format = formatsave;
+	if (*p != NULL) {
+		/* kwlist is too long */
+		PyErr_BadInternalCall();
+		return 0;
+	}
 	if (min < 0) {
 		/* All arguments are required. */
 		min = max;
 	}
-	format = formatsave;
 
+	nkwlist = max;
 	nargs = PyTuple_GET_SIZE(args);
 	nkeywords = keywords == NULL ? 0 : PyDict_Size(keywords);
 
@@ -1103,9 +1118,11 @@
 	}
 
 	/* required arguments missing from args can be supplied by keyword 
-	   arguments */
+	   arguments; set len to the number of posiitional arguments, and,
+	   if that's less than the minimum required, add in the number of
+	   required arguments that are supplied by keywords */
 	len = nargs;
-	if (keywords && nargs < min) {
+	if (nkeywords > 0 && nargs < min) {
 		for (i = nargs; i < min; i++) {
 			if (PyDict_GetItemString(keywords, kwlist[i]))
 				len++;
@@ -1118,7 +1135,6 @@
 	   is a little confusing with keywords since keyword arguments
 	   which are supplied, but don't match the required arguments
 	   are not included in the "%d given" part of the message */
-
 	if (len < min || max < len) {
 		if (message == NULL) {
 			sprintf(msgbuf,
@@ -1151,18 +1167,6 @@
 	if (nkeywords == 0)
 		return 1; 
 
-	/* make sure the number of keywords in the keyword list matches the 
-	   number of items in the format string */
-	nkwlist = 0;
-	p =  kwlist;
-	while (*p++)
-		nkwlist++;
-	if (nkwlist != max) {
-		PyErr_SetString(PyExc_SystemError,
-	  "number of items in format string and keyword list do not match");
-		return 0;
-	}	  	  
-
 	/* convert the keyword arguments; this uses the format 
 	   string where it was left after processing args */
 	converted = 0;