Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 62d48e1

Browse files
committed
vgetargskeywords: Verify kwlist has the required length while parsing
the format, instead of waiting until after we can overindex it by mistake.
1 parent b92cf06 commit 62d48e1

1 file changed

Lines changed: 24 additions & 20 deletions

File tree

Python/getargs.c

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)