]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
in some cases, "no data" is a parse error
authorAlan T. DeKok <aland@freeradius.org>
Thu, 19 Mar 2026 20:23:50 +0000 (16:23 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 19 Mar 2026 20:52:59 +0000 (16:52 -0400)
and add tests to match

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

index b3028743713afd46b0b65f63bd115e359c3f6187..6b431e9b9b29e12c9cbd1fbcfded53733177c2de 100644 (file)
@@ -413,6 +413,11 @@ fr_slen_t fr_time_delta_from_str(fr_time_delta_t *out, char const *in, size_t in
 {
        fr_slen_t slen;
 
+       if (!*in) {
+               fr_strerror_const("Empty input is invalid");
+               return -1;
+       }
+
        slen = fr_time_delta_from_substr(out, &FR_SBUFF_IN(in, inlen), hint, true, NULL);
        if (slen < 0) return slen;
        if (slen != (fr_slen_t)inlen) {
@@ -803,6 +808,11 @@ int fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str, fr_time_re
        unsigned long   l;
        fr_time_delta_t gmt_delta = fr_time_delta_wrap(0);
 
+       if (!*date_str) {
+               fr_strerror_const("Empty input is invalid");
+               return -1;
+       }
+
        /*
         *      Test for unix timestamp, which is just a number and
         *      nothing else.
index 940826b57f0879b6097d7318f0d70846bbe63a01..2d503144f2018df25ac6c4eccbc4e352f5d648d7 100644 (file)
@@ -5375,7 +5375,6 @@ fr_slen_t fr_value_box_from_numeric_substr(fr_value_box_t *dst, fr_type_t dst_ty
                }
        }
 
-
        return slen;
 }
 
@@ -5623,7 +5622,7 @@ parse:
        case FR_TYPE_IPV4_ADDR:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                if (fr_inet_pton4(&addr, fr_sbuff_current(in), name_len,
                                  fr_hostname_lookups, false, true) < 0) return -1;
@@ -5646,7 +5645,7 @@ parse:
        case FR_TYPE_IPV4_PREFIX:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                if (fr_inet_pton4(&dst->vb_ip, fr_sbuff_current(in), name_len,
                                  fr_hostname_lookups, false, true) < 0) return -1;
@@ -5656,7 +5655,7 @@ parse:
        case FR_TYPE_IPV6_ADDR:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                /*
                 *      Parse scope, too.
@@ -5686,7 +5685,7 @@ parse:
        case FR_TYPE_IPV6_PREFIX:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                if (fr_inet_pton6(&dst->vb_ip, fr_sbuff_current(in), name_len,
                                  fr_hostname_lookups, false, true) < 0) return -1;
@@ -5696,7 +5695,7 @@ parse:
        case FR_TYPE_COMBO_IP_ADDR:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                /*
                 *      Parse scope, too.
@@ -5723,7 +5722,7 @@ parse:
        case FR_TYPE_COMBO_IP_PREFIX:
        {
                size_t name_len = fr_sbuff_adv_past_allowed(&our_in, fr_sbuff_remaining(&our_in), sbuff_char_class_hostname, rules->terminals);
-               if (!name_len) return 0;
+               if (!name_len) goto empty_is_invalid;
 
                if (fr_inet_pton(&dst->vb_ip, fr_sbuff_current(in), name_len, AF_UNSPEC,
                                  fr_hostname_lookups, true) < 0) return -1;
@@ -5753,7 +5752,7 @@ parse:
                 *      Quoted boolean values are "yes", "no", "true", "false"
                 */
                slen = fr_sbuff_out(NULL, &dst->vb_bool, in);
-               if (slen >= 0) return slen;
+               if (slen > 0) return slen;
 
                /*
                 *      For barewords we also allow 0 for false and any other
@@ -5867,6 +5866,11 @@ parse:
                                                 dst_enumv ? dst_enumv->flags.flag_time_res : FR_TIME_RES_SEC,
                                                 false, rules->terminals);
                if (slen < 0) return slen;
+               if (!slen) {
+               empty_is_invalid:
+                       fr_strerror_const("Empty input is invalid");
+                       return -1;
+               }
                FR_SBUFF_SET_RETURN(in, &our_in);
 
        case FR_TYPE_NULL:
index 98e185b53eb1a175a2da679fece40f8eefa4d718..d9483db360cfd4f2c2b2db5bad0c5524226f434c 100644 (file)
@@ -1,5 +1,4 @@
 fuzzer-out util
-
 #
 #  Parse / print data types
 #
@@ -124,6 +123,77 @@ match -128
 value int8 -130
 match integer underflow
 
+#
+#  Empty input is invalid for IP address types.
+#
+#  The "!" is not a valid hostname character, so the parser
+#  consumes zero characters and returns "Empty input is invalid".
+#
+value ipaddr
+match Empty input is invalid
+
+value ipaddr !
+match Empty input is invalid
+
+value ipv4prefix !
+match Empty input is invalid
+
+value ipv6addr !
+match Empty input is invalid
+
+value ipv6prefix !
+match Empty input is invalid
+
+value combo-ip !
+match Empty input is invalid
+
+value combo-prefix !
+match Empty input is invalid
+
+#
+#  Non-numeric input is invalid for integer types
+#
+
+# Note end of string immediately after "uint32"
+value uint32
+match empty input is invalid
+
+value uint8 !
+match Failed parsing string as type 'uint8'
+
+value uint16 !
+match Failed parsing string as type 'uint16'
+
+value uint32 !
+match Failed parsing string as type 'uint32'
+
+value uint64 !
+match Failed parsing string as type 'uint64'
+
+value int8 !
+match Failed parsing string as type 'int8'
+
+value int16 !
+match Failed parsing string as type 'int16'
+
+value int32 !
+match Failed parsing string as type 'int32'
+
+value int64 !
+match Failed parsing string as type 'int64'
+
+value float32 !
+match Failed parsing string as type 'float32'
+
+value float64 !
+match Failed parsing string as type 'float64'
+
+#
+#  Non-boolean input is invalid
+#
+value bool !
+match Invalid boolean value.  Accepted values are "yes", "no", "true", "false" or any unquoted integer
+
 value date Jan  1 1970 12:00:00 UTC
 match 1970-01-01T12:00:00Z
 
@@ -253,4 +323,4 @@ encode-dns-label www_foo.com
 match Invalid character 0x5f in label
 
 count
-match 126
+match 164