Return an error for an empty timeout string. Just use strtol() for

syntax checking instead of scanning with strspn().
This commit is contained in:
Todd C. Miller
2017-12-11 09:19:42 -07:00
parent bbc43b5e30
commit b5463c2809

View File

@@ -45,66 +45,64 @@ int
parse_timeout(const char *timestr) parse_timeout(const char *timestr)
{ {
debug_decl(parse_timeout, SUDOERS_DEBUG_PARSER) debug_decl(parse_timeout, SUDOERS_DEBUG_PARSER)
const char digits[] = "0123456789";
const char suffixes[] = "dhms"; const char suffixes[] = "dhms";
const char *cp; const char *cp = timestr;
int timeout = 0; int timeout = 0;
size_t len = 0;
int idx = 0; int idx = 0;
for (cp = timestr; *cp != '\0'; cp += len) { do {
char *ep;
char ch; char ch;
long l; long l;
if ((len = strspn(cp, digits)) == 0) { /* Parse number, must be present and positive. */
/* parse error */ errno = 0;
l = strtol(cp, &ep, 10);
if (ep == cp) {
/* missing timeout */
errno = EINVAL; errno = EINVAL;
debug_return_int(-1); debug_return_int(-1);
} }
if (cp[len] == '\0') { if (errno == ERANGE || l < 0 || l > INT_MAX)
/* no suffix, assume seconds. */ goto overflow;
ch = 's';
} else {
ch = tolower(cp[len]);
len++;
}
/* Find a matching suffix or return an error. */ /* Find a matching suffix or return an error. */
while (suffixes[idx] != ch) { if (*ep != '\0') {
if (suffixes[idx] == '\0') { ch = tolower((unsigned char)*ep++);
/* parse error */ while (suffixes[idx] != ch) {
errno = EINVAL; if (suffixes[idx] == '\0') {
debug_return_int(-1); /* parse error */
errno = EINVAL;
debug_return_int(-1);
}
idx++;
} }
idx++;
}
errno = 0; /* Apply suffix. */
l = strtol(cp, NULL, 10); switch (ch) {
if (errno == ERANGE || l > INT_MAX) case 'd':
goto overflow; if (l > INT_MAX / (24 * 60 * 60))
switch (ch) { goto overflow;
case 'd': l *= 24 * 60 * 60;
if (l > INT_MAX / (24 * 60 * 60)) break;
case 'h':
if (l > INT_MAX / (60 * 60))
goto overflow;
l *= 60 * 60;
break;
case 'm':
if (l > INT_MAX / 60)
goto overflow;
l *= 60;
break;
}
if (l > INT_MAX - timeout)
goto overflow; goto overflow;
l *= 24 * 60 * 60;
break;
case 'h':
if (l > INT_MAX / (60 * 60))
goto overflow;
l *= 60 * 60;
break;
case 'm':
if (l > INT_MAX / 60)
goto overflow;
l *= 60;
break;
} }
if (l > INT_MAX - timeout) cp = ep;
goto overflow;
timeout += l; timeout += l;
} } while (*cp != '\0');
debug_return_int(timeout); debug_return_int(timeout);
overflow: overflow: