From: Alan T. DeKok Date: Thu, 14 Oct 2021 20:18:49 +0000 (-0400) Subject: add fr_time_scale() and use it when parsing times. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=927bec531f6515630170f2d59d8f01cbcbba76d5;p=thirdparty%2Ffreeradius-server.git add fr_time_scale() and use it when parsing times. so that we can clamp the times at min/max values, if the user gives us something which is out of bounds. we still need to fix value_box_from_network for DATE, as those values are unsigned. And also fix the various casting functions to clamp the relevant values. --- diff --git a/src/lib/util/misc.c b/src/lib/util/misc.c index c7d9d556138..b726d423280 100644 --- a/src/lib/util/misc.c +++ b/src/lib/util/misc.c @@ -578,7 +578,6 @@ static int get_part(char **str, int *date, int min, int max, char term, char con int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_res_t hint) { int i; - fr_unix_time_t t; int64_t tmp; struct tm *tm, s_tm; char buf[64]; @@ -593,29 +592,7 @@ int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_re */ tmp = strtoul(date_str, &tail, 10); if (*tail == '\0') { - switch (hint) { - case FR_TIME_RES_SEC: - t = fr_unix_time_from_sec(tmp); - break; - - case FR_TIME_RES_MSEC: - t = fr_unix_time_from_msec(tmp); - break; - - case FR_TIME_RES_USEC: - t = fr_unix_time_from_usec(tmp); - break; - - case FR_TIME_RES_NSEC: - t = fr_unix_time_from_nsec(tmp); - break; - - default: - fr_strerror_printf("Invalid hint %d for time delta", hint); - return -1; - } - - *date = t; + *date = fr_unix_time_from_nsec(fr_time_scale(tmp, hint)); return 0; } diff --git a/src/lib/util/time.c b/src/lib/util/time.c index 9434b7b35cd..74106027b1a 100644 --- a/src/lib/util/time.c +++ b/src/lib/util/time.c @@ -239,6 +239,14 @@ int fr_time_delta_from_str(fr_time_delta_t *out, char const *in, fr_time_res_t h goto parse_precision; } + /* + * The input is just a number. Scale and clamp it as appropriate. + */ + if (!*end) { + *out = fr_time_delta_from_nsec(fr_time_scale(sec, hint)); + return 0; + } + /* * Decimal number */ @@ -625,3 +633,51 @@ int64_t fr_time_delta_scale(fr_time_delta_t delta, fr_time_res_t hint) return 0; } + +/** Scale an input time to NSEC, clamping it at max / min. + * + * @param t input time / time delta + * @param hint time resolution hint + * @return + * - INT64_MIN on underflow + * - 0 on invalid hint + * - INT64_MAX on overflow + * - otherwise a valid number, multiplied by the relevant scale, + * so that the result is in nanoseconds. + */ +int64_t fr_time_scale(int64_t t, fr_time_res_t hint) +{ + int64_t scale; + + switch (hint) { + case FR_TIME_RES_SEC: + scale = NSEC; + break; + + case FR_TIME_RES_MSEC: + scale = 1000000; + break; + + case FR_TIME_RES_USEC: + scale = 1000; + break; + + case FR_TIME_RES_NSEC: + return t; + + default: + return 0; + } + + if (t < 0) { + if (t < (INT64_MIN / scale)) { + return INT64_MIN; + } + } else if (t > 0) { + if (t > (INT64_MAX / scale)) { + return INT64_MAX; + } + } + + return t * scale; +} diff --git a/src/lib/util/time.h b/src/lib/util/time.h index b63be194ab1..78e4b6edd33 100644 --- a/src/lib/util/time.h +++ b/src/lib/util/time.h @@ -651,6 +651,8 @@ static inline fr_time_t fr_time(void) int fr_time_start(void); int fr_time_sync(void); +int64_t fr_time_scale(int64_t t, fr_time_res_t hint); + int fr_time_delta_from_time_zone(char const *tz, fr_time_delta_t *delta) CC_HINT(nonnull); int fr_time_delta_from_str(fr_time_delta_t *out, char const *in, fr_time_res_t hint) CC_HINT(nonnull); diff --git a/src/lib/util/value.c b/src/lib/util/value.c index b045fbd0c06..9b2833d06dc 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -1810,28 +1810,7 @@ ssize_t fr_value_box_from_network(TALLOC_CTX *ctx, date = tmp; } - switch (precision) { - case FR_TIME_RES_SEC: /* external seconds, internal nanoseconds */ - dst->vb_time_delta = fr_time_delta_from_sec(date); - break; - - case FR_TIME_RES_CSEC: - dst->vb_time_delta = fr_time_delta_from_csec(date); - break; - - case FR_TIME_RES_MSEC: - dst->vb_time_delta = fr_time_delta_from_msec(date); - break; - - case FR_TIME_RES_USEC: - dst->vb_time_delta = fr_time_delta_from_usec(date); - break; - - case FR_TIME_RES_NSEC: - dst->vb_time_delta = fr_time_delta_wrap(date); - break; - } - + dst->vb_time_delta = fr_time_delta_wrap(fr_time_scale(date, precision)); } break;