]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
time_delta is signed by default
authorAlan T. DeKok <aland@freeradius.org>
Thu, 2 Sep 2021 15:33:47 +0000 (11:33 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 2 Sep 2021 15:33:47 +0000 (11:33 -0400)
add tests.

Catch the case (parsing and printing) of negative zero

src/lib/util/dict.h
src/lib/util/dict_tokenize.c
src/lib/util/time.c
src/lib/util/value.c
src/tests/unit/data_types.txt

index 7525300ee8fa2ab97d541729478c6d8ecf37479c..307cabc2f65dc1abfc7a85c17551e1ace64db242 100644 (file)
@@ -91,7 +91,7 @@ typedef struct {
 
        unsigned int            virtual : 1;                    //!< for dynamic expansion
 
-       unsigned int            is_signed : 1;                  //!< hackity hack for dates and time deltas
+       unsigned int            is_unsigned : 1;                //!< hackity hack for dates and time deltas
 
        /*
         *      @todo - if we want to clean these fields up, make
index 130d1359b3068b702b6ba9d72256a3dd52d261a6..a750cfc554b2046b4512f5652de502fe1af4ebec 100644 (file)
@@ -408,28 +408,28 @@ static int dict_process_flag_field(dict_tokenize_ctx_t *ctx, char *name, fr_type
 
                                case FR_TYPE_INT16:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
-                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT16:
+                                       flags->is_unsigned = true;
                                        flags->length = 2;
                                        break;
 
                                case FR_TYPE_INT32:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
-                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT32:
+                                       flags->is_unsigned = true;
                                        flags->length = 4;
                                        break;
 
                                case FR_TYPE_INT64:
                                        if (type == FR_TYPE_DATE) goto unknown_type;
-                                       flags->is_signed = true;
                                        FALL_THROUGH;
 
                                case FR_TYPE_UINT64:
+                                       flags->is_unsigned = true;
                                        flags->length = 8;
                                        break;
                                }
index c01ae3f62db6eca77eeed5edd51493bfdf8c995c..213d4e580c1b935883cdb85c963651d17af509b9 100644 (file)
@@ -220,6 +220,9 @@ int fr_time_delta_from_str(fr_time_delta_t *out, char const *in, fr_time_res_t h
        uint64_t subsec = 0;
        int     scale = 1;
        char    *p, *end;
+       bool    negative = false;
+
+       if (*in == '-') negative = true; /* catch the case of negative zero! */
 
        sec = strtoll(in, &end, 10);
        if (in == end) {
@@ -367,7 +370,11 @@ int fr_time_delta_from_str(fr_time_delta_t *out, char const *in, fr_time_res_t h
                 */
                if (*end) goto failed;
 
-               *out = (minutes * 60 + sec) * NSEC;
+               if (negative) {
+                       *out = (minutes * 60 - sec) * NSEC;
+               } else {
+                       *out = (minutes * 60 + sec) * NSEC;
+               }
                return 0;
 
        } else if (*end) {
@@ -413,7 +420,7 @@ done:
        /*
         *      Now sec && subsec are in the same scale.
         */
-       if (sec < 0) {
+       if (negative) {
                if (sec <= (INT64_MIN / scale)) {
                        fr_strerror_const("Integer underflow in time_delta value.");
                        return -1;
index 31703de9cfac67c85a10101967a496826363adce..2409aa39a02a46c999b1a315238da69d215546bd 100644 (file)
@@ -1432,7 +1432,7 @@ ssize_t fr_value_box_to_network(fr_dbuff_t *dbuff, fr_value_box_t const *value)
                if (!value->enumv) {
                        goto delta_size4;
 
-               } else if (value->enumv->flags.is_signed) {
+               } else if (!value->enumv->flags.is_unsigned) {
                        switch (value->enumv->flags.length) {
                        case 2:
                                if (date < INT16_MIN) {
@@ -1782,7 +1782,7 @@ ssize_t fr_value_box_from_network_dbuff(TALLOC_CTX *ctx,
 
                dst->enumv = enumv;
 
-               if (!enumv || enumv->flags.is_signed) {
+               if (!enumv || !enumv->flags.is_unsigned) {
                        FR_DBUFF_OUT_INT64V_RETURN(&date, &work_dbuff, length);
                } else {
                        uint64_t tmp;
@@ -5028,10 +5028,20 @@ ssize_t fr_value_box_print(fr_sbuff_t *out, fr_value_box_t const *data, fr_sbuff
                        break;
                }
 
-               if (!data->enumv || data->enumv->flags.is_signed) {
+               if (!data->enumv || !data->enumv->flags.is_unsigned) {
+                       /*
+                        *      0 is unsigned, but we want to print
+                        *      "-0.1" if necessary.
+                        */
+                       if ((lhs == 0) && (data->datum.time_delta < 0)) {
+                               FR_SBUFF_IN_CHAR_RETURN(&our_out, '-');
+                       }
+
                        FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRIi64 ".%09" PRIu64, lhs, rhs);
                } else {
-                       if (lhs < 0) lhs = 0;
+                       if (data->datum.time_delta < 0) {
+                               lhs = rhs = 0;
+                       }
 
                        FR_SBUFF_IN_SPRINTF_RETURN(&our_out, "%" PRIu64 ".%09" PRIu64, lhs, rhs);
                }
index df7dab06b08a18b30d714273e4b2b5f84441d2f2..857764e3ec3205faab437d6379d811eb07e163e9 100644 (file)
@@ -38,6 +38,44 @@ match 0.000000001
 value time_delta 1:30
 match 90
 
+value time_delta 1h
+match 3600
+
+#
+#  And negative numbers
+#
+value time_delta -1
+match -1
+
+value time_delta -2.4
+match -2.4
+
+value time_delta -0.001
+match -0.001
+
+value time_delta -1ms
+match -0.001
+
+value time_delta -1us
+match -0.000001
+
+value time_delta -1.5us
+match -0.0000015
+
+value time_delta -1ns
+match -0.000000001
+
+value time_delta -1:30
+match -90
+
+value time_delta -1h
+match -3600
+
+
+
+#
+#  uint8
+#
 value uint8 256
 match Value 256 is invalid for type uint8 (must be in range 0...255)
 
@@ -165,4 +203,4 @@ match Double dots '..' are forbidden
 
 
 count
-match 78
+match 98