2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-28 12:57:50 +00:00

Convert from time in minutes to timespec directly instead of

converting to double via strtod().  This makes it easier to catch
overflow.
This commit is contained in:
Todd C. Miller 2018-01-26 10:17:47 -07:00
parent eb8b5c7964
commit bcfb092a4e

View File

@ -165,9 +165,9 @@ dump_defaults(void)
break; break;
case T_TIMESPEC: { case T_TIMESPEC: {
/* display timespec in minutes as a double */ /* display timespec in minutes as a double */
double d = cur->sd_un.tspec.tv_sec / 60.0; double d = cur->sd_un.tspec.tv_sec +
d += cur->sd_un.tspec.tv_nsec / 1000000000.0; (cur->sd_un.tspec.tv_nsec / 1000000000.0);
sudo_printf(SUDO_CONV_INFO_MSG, desc, d); sudo_printf(SUDO_CONV_INFO_MSG, desc, d * 60.0);
sudo_printf(SUDO_CONV_INFO_MSG, "\n"); sudo_printf(SUDO_CONV_INFO_MSG, "\n");
break; break;
} }
@ -851,26 +851,61 @@ store_uint(const char *str, union sudo_defs_val *sd_un)
debug_return_bool(true); debug_return_bool(true);
} }
#ifndef TIME_T_MAX
# if SIZEOF_TIME_T == 8
# define TIME_T_MAX LLONG_MAX
# else
# define TIME_T_MAX INT_MAX
# endif
#endif
static bool static bool
store_timespec(const char *str, union sudo_defs_val *sd_un) store_timespec(const char *str, union sudo_defs_val *sd_un)
{ {
char *endp; struct timespec ts;
double d; char sign = '+';
int i;
debug_decl(store_timespec, SUDOERS_DEBUG_DEFAULTS) debug_decl(store_timespec, SUDOERS_DEBUG_DEFAULTS)
if (str == NULL) { sudo_timespecclear(&ts);
sd_un->tspec.tv_sec = 0; if (str != NULL) {
sd_un->tspec.tv_nsec = 0; /* Convert from minutes to timespec. */
if (*str == '+' || *str == '-')
sign = *str++;
while (*str != '\0' && *str != '.') {
if (!isdigit((unsigned char)*str))
debug_return_bool(false); /* invalid number */
if (ts.tv_sec > TIME_T_MAX / 10)
debug_return_bool(false); /* overflow */
ts.tv_sec *= 10;
ts.tv_sec += *str++ - '0';
}
if (*str++ == '.') {
/* Convert optional fractional component to nanosecs. */
for (i = 100000000; i > 0; i /= 10) {
if (*str == '\0')
break;
if (!isdigit((unsigned char)*str))
debug_return_bool(false); /* invalid number */
ts.tv_nsec += i * (*str++ - '0');
}
}
/* Convert from minutes to seconds. */
if (ts.tv_sec > TIME_T_MAX / 60)
debug_return_bool(false); /* overflow */
ts.tv_sec *= 60;
ts.tv_nsec *= 60;
while (ts.tv_nsec >= 1000000000) {
ts.tv_sec++;
ts.tv_nsec -= 1000000000;
}
}
if (sign == '-') {
sd_un->tspec.tv_sec = -ts.tv_sec;
sd_un->tspec.tv_nsec = -ts.tv_nsec;
} else { } else {
d = strtod(str, &endp); sd_un->tspec.tv_sec = ts.tv_sec;
if (*endp != '\0') sd_un->tspec.tv_nsec = ts.tv_nsec;
debug_return_bool(false);
/* XXX - should check against HUGE_VAL */
/* Convert from minutes to seconds and nanoseconds. */
d *= 60.0;
sd_un->tspec.tv_sec = (time_t)d;
sd_un->tspec.tv_nsec = (long)((d - sd_un->tspec.tv_sec) * 1000000000.0);
} }
debug_return_bool(true); debug_return_bool(true);
} }