Return an error for an empty timeout string. Just use strtol() for
syntax checking instead of scanning with strspn().
This commit is contained in:
@@ -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:
|
||||||
|
Reference in New Issue
Block a user