]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add fr_time_scale() and use it when parsing times.
authorAlan T. DeKok <aland@freeradius.org>
Thu, 14 Oct 2021 20:18:49 +0000 (16:18 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 14 Oct 2021 20:25:36 +0000 (16:25 -0400)
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.

src/lib/util/misc.c
src/lib/util/time.c
src/lib/util/time.h
src/lib/util/value.c

index c7d9d55613804c9e52dfd555e4206512002cf8b4..b726d4232806c0e60c8f87a1025c67c36ced7184 100644 (file)
@@ -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;
        }
 
index 9434b7b35cdc0e67da2d7252f428ef2cc0c365f0..74106027b1a3a7b473a795c8a4d5b57d7a1f75af 100644 (file)
@@ -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;
+}
index b63be194ab15cc67f7115ec0da7cb637eb1ea061..78e4b6edd3363877e1800d55f3c09ba217bcfd58 100644 (file)
@@ -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);
 
index b045fbd0c06dc94b14cf1df20ad4d9ae46a9d289..9b2833d06dcc99a0a4eece5c3fe6ed71b8b1f67b 100644 (file)
@@ -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;