]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Convert fixed width type conversion sbuff functions to return a fr_slen_t
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 25 Oct 2021 18:21:06 +0000 (14:21 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 25 Oct 2021 18:23:41 +0000 (14:23 -0400)
src/lib/server/tmpl_tokenize.c
src/lib/util/sbuff.c
src/lib/util/sbuff.h

index 24a6acd8445c4984e3f2174ceda82b53e787962f..26222f30ae3db9195f01fa0c2d8f32bb57172a23 100644 (file)
@@ -1130,7 +1130,7 @@ static tmpl_attr_filter_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_at
                fr_sbuff_parse_error_t  sberr = FR_SBUFF_PARSE_OK;
                fr_sbuff_t tmp = FR_SBUFF(name);
 
-               if (fr_sbuff_out(&sberr, &ar->num, &tmp) == 0) {
+               if (fr_sbuff_out(&sberr, &ar->num, &tmp) < 0) {
                        if (sberr == FR_SBUFF_PARSE_ERROR_NOT_FOUND) {
                                fr_strerror_const("Invalid array index");
                                if (err) *err = TMPL_ATTR_ERROR_INVALID_ARRAY_INDEX;
@@ -2035,7 +2035,7 @@ static ssize_t tmpl_afrom_bool_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t
        bool            a_bool;
        tmpl_t          *vpt;
 
-       if (!fr_sbuff_out(NULL, &a_bool, &our_in)) {
+       if (fr_sbuff_out(NULL, &a_bool, &our_in) < 0) {
                fr_strerror_const("Not a boolean value");
                return 0;
        }
@@ -2151,7 +2151,7 @@ static ssize_t tmpl_afrom_ipv4_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t
         *      an IP prefix.
         */
        if (fr_sbuff_next_if_char(&our_in, '/')) {
-               if (!fr_sbuff_out(NULL, &octet, &our_in)) {
+               if (fr_sbuff_out(NULL, &octet, &our_in) < 0) {
                        fr_strerror_const("IPv4 CIDR mask malformed");
                        goto error;
                }
@@ -2268,7 +2268,7 @@ static ssize_t tmpl_afrom_ipv6_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t
        if (fr_sbuff_next_if_char(&our_in, '/')) {
                uint8_t         mask;
 
-               if (!fr_sbuff_out(NULL, &mask, &our_in)) {
+               if (fr_sbuff_out(NULL, &mask, &our_in) < 0) {
                        fr_strerror_const("IPv6 CIDR mask malformed");
                        goto error;
                }
index eae7cc5f6f93c1eb6ea3fa05ee3b15eb6f9b0873..c39c8fcd914d8de05378d68efc2f718eec971e01 100644 (file)
@@ -35,8 +35,10 @@ static_assert(sizeof(unsigned long long) >= sizeof(uint64_t), "long long must be
 fr_table_num_ordered_t const sbuff_parse_error_table[] = {
        { L("ok"),                      FR_SBUFF_PARSE_OK                               },
        { L("token not found"),         FR_SBUFF_PARSE_ERROR_NOT_FOUND                  },
+       { L("token format invalid"),    FR_SBUFF_PARSE_ERROR_FORMAT                     },
+       { L("out of space"),            FR_SBUFF_PARSE_ERROR_OUT_OF_SPACE               },
        { L("integer overflow"),        FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW               },
-       { L("integer underflow"),       FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW              },
+       { L("integer underflow"),       FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW              }
 };
 size_t sbuff_parse_error_table_len = NUM_ELEMENTS(sbuff_parse_error_table);
 
@@ -996,58 +998,60 @@ done:
  * @param[out] out     Where to write boolean value.
  * @param[in] in       Where to search for a truth value.
  * @return
- *     - 0 no bytes copied.  Was not a truth value.
  *     - >0 the number of bytes consumed.
+ *     - -1 no bytes copied, was not a truth value.
  */
-size_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in)
+fr_slen_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in)
 {
+       fr_sbuff_t our_in = FR_SBUFF(in);
+
        static bool const bool_prefix[UINT8_MAX + 1] = {
                ['t'] = true, ['T'] = true,     /* true */
                ['f'] = true, ['F'] = true,     /* false */
                ['y'] = true, ['Y'] = true,     /* yes */
-               ['n'] = true, ['N'] = true      /* no */
+               ['n'] = true, ['N'] = true,     /* no */
        };
 
-#define IS_TOKEN(_t) ((fr_sbuff_extend_lowat(NULL, in, sizeof(_t) - 1) >= (sizeof(_t) - 1)) && \
-                     (strncasecmp(in->p, _t, sizeof(_t) - 1) == 0))
-
-       if (fr_sbuff_is_in_charset(in, bool_prefix)) {
-               switch (tolower(*in->p)) {
+       if (fr_sbuff_is_in_charset(&our_in, bool_prefix)) {
+               switch (tolower(*fr_sbuff_current(&our_in))) {
                default:
                        break;
 
                case 't':
-                       if (IS_TOKEN("true")) {
+                       if (fr_sbuff_adv_past_strcase_literal(&our_in, "true")) {
                                *out = true;
-                               return fr_sbuff_advance(in, sizeof("true") - 1);
+                               return fr_sbuff_set(in, &our_in);
                        }
                        break;
 
                case 'f':
-                       if (IS_TOKEN("false")) {
+                       if (fr_sbuff_adv_past_strcase_literal(&our_in, "false")) {
                                *out = false;
-                               return fr_sbuff_advance(in, sizeof("false") - 1);
+                               return fr_sbuff_set(in, &our_in);
                        }
                        break;
 
                case 'y':
-                       if (IS_TOKEN("yes")) {
+                       if (fr_sbuff_adv_past_strcase_literal(&our_in, "yes")) {
                                *out = true;
-                               return fr_sbuff_advance(in, sizeof("yes") - 1);
+                               return fr_sbuff_set(in, &our_in);
                        }
                        break;
 
                case 'n':
-                       if (IS_TOKEN("no")) {
+                       if (fr_sbuff_adv_past_strcase_literal(&our_in, "no")) {
                                *out = false;
-                               return fr_sbuff_advance(in, sizeof("no") - 1);
+                               return fr_sbuff_set(in, &our_in);
                        }
                        break;
                }
        }
 
        *out = false;   /* Always initialise out */
-       return 0;
+
+       fr_strerror_const("Not a valid boolean value.  Accepted values are 'yes', 'no', 'true', 'false'");
+
+       return -1;
 }
 
 /** Used to define a number parsing functions for singed integers
@@ -1061,7 +1065,7 @@ size_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in)
  *                     used in <stdint.h>.
  */
 #define SBUFF_PARSE_INT_DEF(_name, _type, _min, _max, _max_char) \
-size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
+fr_slen_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
 { \
        char            buff[_max_char + 1]; \
        char            *end, *a_end; \
@@ -1071,28 +1075,28 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t
        len = fr_sbuff_out_bstrncpy(&FR_SBUFF_IN(buff, sizeof(buff)), &our_in, _max_char); \
        if (len == 0) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } \
        num = strtoll(buff, &end, 10); \
        if (end == buff) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } \
        if ((num > (_max)) || ((errno == EINVAL) && (num == LLONG_MAX))) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW; \
                *out = (_type)(_max); \
-               return 0; \
+               return -1; \
        } else if (no_trailing && (((a_end = in->p + (end - buff)) + 1) < in->end)) { \
                if (isdigit(*a_end)) { \
                        if (err) *err = FR_SBUFF_PARSE_ERROR_TRAILING; \
                        *out = (_type)(_max); \
-                       return 0; \
+                       return fr_sbuff_error(&our_in); \
                } \
                *out = (_type)(num); \
        } else if (num < (_min) || ((errno == EINVAL) && (num == LLONG_MIN))) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW; \
                *out = (_type)(_min); \
-               return 0; \
+               return -1; \
        } else { \
                if (err) *err = FR_SBUFF_PARSE_OK; \
                *out = (_type)(num); \
@@ -1104,6 +1108,7 @@ SBUFF_PARSE_INT_DEF(int8, int8_t, INT8_MIN, INT8_MAX, 4)
 SBUFF_PARSE_INT_DEF(int16, int16_t, INT16_MIN, INT16_MAX, 6)
 SBUFF_PARSE_INT_DEF(int32, int32_t, INT32_MIN, INT32_MAX, 11)
 SBUFF_PARSE_INT_DEF(int64, int64_t, INT64_MIN, INT64_MAX, 20)
+SBUFF_PARSE_INT_DEF(ssize, ssize_t, SSIZE_MIN, SSIZE_MAX, 20)
 
 /** Used to define a number parsing functions for singed integers
  *
@@ -1116,7 +1121,7 @@ SBUFF_PARSE_INT_DEF(int64, int64_t, INT64_MIN, INT64_MAX, 20)
  * @param[in] _base    of the number being parsed, 8, 10, 18 etc...
  */
 #define SBUFF_PARSE_UINT_DEF(_name, _type, _max, _max_char, _base) \
-size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
+fr_slen_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
 { \
        char                    buff[_max_char + 1]; \
        char                    *end, *a_end; \
@@ -1126,22 +1131,22 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t
        len = fr_sbuff_out_bstrncpy(&FR_SBUFF_IN(buff, sizeof(buff)), &our_in, _max_char); \
        if (len == 0) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } \
        num = strtoull(buff, &end, _base); \
        if (end == buff) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } \
        if ((num > (_max)) || ((errno == EINVAL) && (num == ULLONG_MAX))) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW; \
                *out = (_type)(_max); \
-               return 0; \
+               return -1; \
        } else if (no_trailing && (((a_end = in->p + (end - buff)) + 1) < in->end)) { \
                if (isdigit(*a_end) || ((_base > 10) && ((tolower(*a_end) >= 'a') && (tolower(*a_end) <= 'f')))) { \
                        if (err) *err = FR_SBUFF_PARSE_ERROR_TRAILING; \
                        *out = (_type)(_max); \
-                       return 0; \
+                       return fr_sbuff_error(&our_in); \
                } \
                if (err) *err = FR_SBUFF_PARSE_OK; \
                *out = (_type)(num); \
@@ -1156,16 +1161,19 @@ SBUFF_PARSE_UINT_DEF(uint8, uint8_t, UINT8_MAX, 3, 10)
 SBUFF_PARSE_UINT_DEF(uint16, uint16_t, UINT16_MAX, 4, 10)
 SBUFF_PARSE_UINT_DEF(uint32, uint32_t, UINT32_MAX, 10, 10)
 SBUFF_PARSE_UINT_DEF(uint64, uint64_t, UINT64_MAX, 19, 10)
+SBUFF_PARSE_UINT_DEF(size, size_t, SIZE_MAX, 19, 10)
 
 SBUFF_PARSE_UINT_DEF(uint8_oct, uint8_t, UINT8_MAX, 3, 8)
 SBUFF_PARSE_UINT_DEF(uint16_oct, uint16_t, UINT16_MAX, 6, 8)
 SBUFF_PARSE_UINT_DEF(uint32_oct, uint32_t, UINT32_MAX, 11, 8)
 SBUFF_PARSE_UINT_DEF(uint64_oct, uint64_t, UINT64_MAX, 22, 8)
+SBUFF_PARSE_UINT_DEF(size_oct, size_t, SIZE_MAX, 22, 8)
 
 SBUFF_PARSE_UINT_DEF(uint8_hex, uint8_t, UINT8_MAX, 2, 16)
 SBUFF_PARSE_UINT_DEF(uint16_hex, uint16_t, UINT16_MAX, 4, 16)
 SBUFF_PARSE_UINT_DEF(uint32_hex, uint32_t, UINT32_MAX, 8, 16)
 SBUFF_PARSE_UINT_DEF(uint64_hex, uint64_t, UINT64_MAX, 16, 16)
+SBUFF_PARSE_UINT_DEF(size_hex, size_t, SIZE_MAX, 22, 16)
 
 /** Used to define a number parsing functions for floats
  *
@@ -1177,7 +1185,7 @@ SBUFF_PARSE_UINT_DEF(uint64_hex, uint64_t, UINT64_MAX, 16, 16)
  *                     used in <stdint.h>.
  */
 #define SBUFF_PARSE_FLOAT_DEF(_name, _type, _func, _max_char) \
-size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
+fr_slen_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t *in, bool no_trailing) \
 { \
        char            buff[_max_char + 1]; \
        char            *end; \
@@ -1187,20 +1195,24 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t
        len = fr_sbuff_out_bstrncpy_allowed(&FR_SBUFF_OUT(buff, sizeof(buff)), &our_in, SIZE_MAX, sbuff_char_class_float); \
        if (len == sizeof(buff)) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } else if (len == 0) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_NOT_FOUND; \
-               return 0; \
+               return -1; \
        } \
        res = _func(buff, &end); \
        if (errno == ERANGE) { \
-               if (err) *err = ((res > 0) ? FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW : FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW); \
-               return 0; \
+               if (res > 0) { \
+                       if (err) *err = FR_SBUFF_PARSE_ERROR_NUM_OVERFLOW; \
+               } else { \
+                       if (err) *err = FR_SBUFF_PARSE_ERROR_NUM_UNDERFLOW; \
+               } \
+               return -1; \
        } \
        if (no_trailing && (*end != '\0')) { \
                if (err) *err = FR_SBUFF_PARSE_ERROR_TRAILING; \
                *out = res; \
-               return 0; \
+               return fr_sbuff_error(&our_in); \
        } \
        return fr_sbuff_advance(in, end - buff); \
 }
index bd2eb5e82b45658905b7c057ecd25aa672acc941..8780d8e3d20b1a0f9a5b6d579da35ad38dfb9f11 100644 (file)
@@ -42,6 +42,17 @@ extern "C" {
 #include <freeradius-devel/util/table.h>
 #include <freeradius-devel/util/talloc.h>
 
+/** Represents number of bytes parsed or location of parse error
+ *
+ * Number of bytes parsed will be >= 0.
+ *
+ * If a parse error occurs the value will be the negative offset
+ * of the error -1.  i.e. offset 0 will be -1.
+ *
+ * This is to disambiguate between 0 bytes parsed and error at
+ * offset 0.
+ */
+typedef ssize_t fr_slen_t;
 typedef struct fr_sbuff_s fr_sbuff_t;
 typedef struct fr_sbuff_ptr_s fr_sbuff_marker_t;
 
@@ -806,6 +817,15 @@ static inline fr_sbuff_t *fr_sbuff_init_talloc(TALLOC_CTX *ctx,
        ((size_t)(fr_sbuff_start(_sbuff_or_marker) > fr_sbuff_current(_sbuff_or_marker) ? \
                0 : (fr_sbuff_current(_sbuff_or_marker) - fr_sbuff_start(_sbuff_or_marker))))
 
+/** Return the current position as an error marker
+ *
+ * +1 is added to the position to disambiguate with 0 meaning "parsed no data".
+ *
+ * An error at offset 0 will be returned as -1.
+ */
+#define fr_sbuff_error(_sbuff_or_marker) \
+       (-(fr_sbuff_used(_sbuff_or_marker) + 1))
+
 /** Like fr_sbuff_used, but adjusts for the value returned for the amount shifted
  *
  * @param[in] _sbuff_or_marker to return the number of bytes used for.
@@ -1427,29 +1447,33 @@ SBUFF_OUT_TALLOC_FUNC_DEF(fr_sbuff_out_unescape_until, in, len, tt, u_rules)
  * so that if the output variable type changes, the parse rules are automatically changed.
  * @{
  */
-size_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in);
-
-size_t fr_sbuff_out_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-
-size_t fr_sbuff_out_uint8_oct(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint16_oct(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint32_oct(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint64_oct(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-
-size_t fr_sbuff_out_uint8_hex(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint16_hex(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint32_hex(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_uint64_hex(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
-
-size_t fr_sbuff_out_float32(fr_sbuff_parse_error_t *err, float *out, fr_sbuff_t *sbuff, bool no_trailing);
-size_t fr_sbuff_out_float64(fr_sbuff_parse_error_t *err, double *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_bool(bool *out, fr_sbuff_t *in);
+
+fr_slen_t fr_sbuff_out_int8(fr_sbuff_parse_error_t *err, int8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_int16(fr_sbuff_parse_error_t *err, int16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_int32(fr_sbuff_parse_error_t *err, int32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_int64(fr_sbuff_parse_error_t *err, int64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_ssize(fr_sbuff_parse_error_t *err, ssize_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint8(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint16(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint32(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint64(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_size(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+
+fr_slen_t fr_sbuff_out_uint8_oct(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint16_oct(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint32_oct(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint64_oct(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_size_oct(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+
+fr_slen_t fr_sbuff_out_uint8_hex(fr_sbuff_parse_error_t *err, uint8_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint16_hex(fr_sbuff_parse_error_t *err, uint16_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint32_hex(fr_sbuff_parse_error_t *err, uint32_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_uint64_hex(fr_sbuff_parse_error_t *err, uint64_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_size_hex(fr_sbuff_parse_error_t *err, size_t *out, fr_sbuff_t *sbuff, bool no_trailing);
+
+fr_slen_t fr_sbuff_out_float32(fr_sbuff_parse_error_t *err, float *out, fr_sbuff_t *sbuff, bool no_trailing);
+fr_slen_t fr_sbuff_out_float64(fr_sbuff_parse_error_t *err, double *out, fr_sbuff_t *sbuff, bool no_trailing);
 
 /** Parse a value based on the output type
  *
@@ -1466,10 +1490,12 @@ size_t fr_sbuff_out_float64(fr_sbuff_parse_error_t *err, double *out, fr_sbuff_t
                 int16_t *      : fr_sbuff_out_int16(_err, (int16_t *)_out, _in, true), \
                 int32_t *      : fr_sbuff_out_int32(_err, (int32_t *)_out, _in, true), \
                 int64_t *      : fr_sbuff_out_int64(_err, (int64_t *)_out, _in, true), \
+                ssize_t *      : fr_sbuff_out_ssize(_err, (ssize_t *)_out, _in, true), \
                 uint8_t *      : fr_sbuff_out_uint8(_err, (uint8_t *)_out, _in, true), \
                 uint16_t *     : fr_sbuff_out_uint16(_err, (uint16_t *)_out, _in, true), \
                 uint32_t *     : fr_sbuff_out_uint32(_err, (uint32_t *)_out, _in, true), \
                 uint64_t *     : fr_sbuff_out_uint64(_err, (uint64_t *)_out, _in, true), \
+                size_t *       : fr_sbuff_out_size(_err, (size_t *)_out, _in, true), \
                 float *        : fr_sbuff_out_float32(_err, (float *)_out, _in, true), \
                 double *       : fr_sbuff_out_float64(_err, (double *)_out, _in, true) \
        )