From: Arran Cudbard-Bell Date: Sat, 18 Jul 2020 20:06:20 +0000 (-0400) Subject: dbuff/sbuff: Shuffle functions so they're in the same order X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bada7909c70d926593fa6b7ef3d188d4bb79117e;p=thirdparty%2Ffreeradius-server.git dbuff/sbuff: Shuffle functions so they're in the same order --- diff --git a/src/lib/util/dbuff.h b/src/lib/util/dbuff.h index c4c50a86af9..9c46e4523fc 100644 --- a/src/lib/util/dbuff.h +++ b/src/lib/util/dbuff.h @@ -248,26 +248,6 @@ _fr_dbuff_init(_out, \ } /** @} */ -/** @name dbuff position manipulation - * @{ - */ -/** Reset the current position of the dbuff to the start of the string - * - */ -static inline uint8_t *fr_dbuff_start(fr_dbuff_t *dbuff) -{ - return dbuff->p = dbuff->start; -} - -/** Reset the current position of the dbuff to the end of the string - * - */ -static inline uint8_t *fr_dbuff_end(fr_dbuff_t *dbuff) -{ - return dbuff->p = dbuff->end; -} -/** @} */ - /** @name Length checks * @{ */ @@ -307,18 +287,37 @@ static inline size_t fr_dbuff_len(fr_dbuff_t const *dbuff) } /** @} */ -/** @name copy data to dbuff - * @{ +/** @name Accessors + * + * Caching the values of these pointers or the pointer values from the dbuff + * directly is strongly discouraged as they can become invalidated during + * stream parsing or when printing to an auto-expanding buffer. + * + * These functions should only be used to pass dbuff pointers into 3rd party + * APIs. */ +static inline uint8_t *fr_dbuff_start(fr_dbuff_t *dbuff) +{ + return dbuff->start; +} -/** Generic wrapper macro to return if there's insufficient memory to satisfy the request on the dbuff +static inline uint8_t *fr_dbuff_current(fr_dbuff_t *dbuff) +{ + return dbuff->p; +} + +static inline uint8_t *fr_dbuff_end(fr_dbuff_t *dbuff) +{ + return dbuff->end; +} +/** @} */ + + +/** @name Position modification (recursive) * + * Change the current position of pointers in the dbuff and their children. + * @{ */ -#define FR_DBUFF_RETURN(_func, ...) \ -do { \ - ssize_t _slen = _func(__VA_ARGS__ ); \ - if (_slen < 0) return _slen; \ -} while (0) /** Update the position of p in a list of dbuffs * @@ -371,35 +370,126 @@ _fr_dbuff_set(_dst, \ size_t : ((_dst)->p += (uintptr_t)(_src)) \ )) -/** Advance position in dbuff by N bytes without sanity checks - * - * @note Do not call this function directly. - */ -static inline ssize_t CC_HINT(nonnull) _fr_dbuff_advance(fr_dbuff_t *dbuff, size_t inlen) -{ - dbuff->p += inlen; - - return dbuff->adv_parent && dbuff->parent ? _fr_dbuff_advance(dbuff->parent, inlen) : (ssize_t)inlen; -} - /** Advance position in dbuff by N bytes * * @param[in] dbuff to advance. - * @param[in] inlen How much to advance dbuff by. + * @param[in] n How much to advance dbuff by. * @return * - 0 not advanced. * - >0 the number of bytes the dbuff was advanced by. * - <0 the number of bytes required to complete the copy. */ -static inline ssize_t fr_dbuff_advance(fr_dbuff_t *dbuff, size_t inlen) +static inline ssize_t fr_dbuff_advance(fr_dbuff_t *dbuff, size_t n) { size_t freespace = fr_dbuff_remaining(dbuff); + if (n > freespace) return -(n - freespace); + _fr_dbuff_set_recurse(dbuff, dbuff->p + n); + return n; +} +#define FR_DBUFF_ADVANCE_RETURN(_dbuff, _inlen) FR_DBUFF_RETURN(fr_dbuff_advance, _dbuff, _inlen) - if (inlen > freespace) return -(inlen - freespace); +/** Reset the current position of the dbuff to the start of the string + * + */ +static inline uint8_t *fr_dbuff_set_to_start(fr_dbuff_t *dbuff) +{ + return dbuff->p = dbuff->start; +} + +/** Reset the current position of the dbuff to the end of the string + * + */ +static inline uint8_t *fr_dbuff_set_to_end(fr_dbuff_t *dbuff) +{ + return dbuff->p = dbuff->end; +} +/** @} */ - return _fr_dbuff_advance(dbuff, inlen); +/** @name Add a marker to an dbuff + * + * Markers are used to indicate an area of the code is working at a particular + * point in a string buffer. + * + * If the dbuff is performing stream parsing, then markers are used to update + * any pointers to the buffer, as the data in the buffer is shifted to make + * room for new data from the stream. + * + * If the dbuff is being used to create strings, then the markers are updated + * if the buffer is re-allocated. + * @{ + */ +/** Adds a new pointer to the beginning of the list of pointers to update + * + */ +static inline uint8_t *fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff) +{ + m->next = dbuff->m; /* Link into the head */ + dbuff->m = m; + + m->p = dbuff->p; /* Set the current position in the dbuff */ + + return dbuff->p; } -#define FR_DBUFF_ADVANCE_RETURN(_dbuff, _inlen) FR_DBUFF_RETURN(fr_dbuff_advance, _dbuff, _inlen) + +/** Trims the linked list backed to the specified pointer + * + * Pointers should be released in the inverse order to allocation. + * + * Alternatively the oldest pointer can be released, resulting in any newer pointer + * also being removed from the list. + * + * @param[in] m to release. + */ +static inline void fr_dbuff_marker_release(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff) +{ + dbuff->m = m->next; +} + +/** Resets the position in an dbuff to specified marker + * + */ +static inline void fr_dbuff_set_to_marker(fr_dbuff_t *dbuff, fr_dbuff_marker_t *m) +{ + _fr_dbuff_set_recurse(dbuff, m->p); +} + +/** Return the current position of the marker + * + */ +static inline uint8_t *fr_dbuff_marker_current(fr_dbuff_marker_t *m) +{ + return m->p; +} + +/** How many free bytes remain in the buffer (calculated from marker) + * + */ +static inline size_t fr_dbuff_marker_remaining(fr_dbuff_t const *dbuff, fr_dbuff_marker_t *m) +{ + return dbuff->end - m->p; +} + +/** How many bytes we've used in the buffer (calculated from marker) + * + */ +static inline size_t fr_dbuff_marker_used(fr_dbuff_t const *dbuff, fr_dbuff_marker_t *m) +{ + return m->p - dbuff->start; +} +/** @} */ + +/** @name copy data to dbuff + * @{ + */ + +/** Generic wrapper macro to return if there's insufficient memory to satisfy the request on the dbuff + * + */ +#define FR_DBUFF_RETURN(_func, ...) \ +do { \ + ssize_t _slen = _func(__VA_ARGS__ ); \ + if (_slen < 0) return _slen; \ +} while (0) static inline ssize_t _fr_dbuff_memcpy_in(fr_dbuff_t *dbuff, uint8_t const *in, size_t inlen) { @@ -411,16 +501,16 @@ static inline ssize_t _fr_dbuff_memcpy_in(fr_dbuff_t *dbuff, uint8_t const *in, memcpy(dbuff->p, in, inlen); - return _fr_dbuff_advance(dbuff, inlen); + return _fr_dbuff_set(dbuff, dbuff->p + inlen); } -static inline ssize_t _fr_dbuff_memcpy_in_dbuff(fr_dbuff_t *out, fr_dbuff_t const *in, size_t inlen) +static inline ssize_t _fr_dbuff_memcpy_in_dbuff(fr_dbuff_t *dbuff, fr_dbuff_t const *in, size_t inlen) { size_t outlen; fr_dbuff_t *in_m; if (inlen > fr_dbuff_remaining(in)) inlen = fr_dbuff_remaining(in); - outlen = fr_dbuff_remaining(out); + outlen = fr_dbuff_remaining(dbuff); /* * If there's too many bytes, then @@ -429,10 +519,10 @@ static inline ssize_t _fr_dbuff_memcpy_in_dbuff(fr_dbuff_t *out, fr_dbuff_t cons */ if (inlen > outlen) return -(inlen - outlen); - (void)_fr_dbuff_memcpy_in(out, in->p, inlen); + (void)_fr_dbuff_memcpy_in(dbuff, in->p, inlen); memcpy(&in_m, &in, sizeof(in_m)); /* Stupid _Generic const issues */ - return _fr_dbuff_advance(in_m, inlen); + return _fr_dbuff_set(in_m, dbuff->p + inlen); } /** Copy inlen bytes into the dbuff @@ -487,23 +577,24 @@ static inline size_t _fr_dbuff_memcpy_in_partial(fr_dbuff_t *dbuff, uint8_t cons memcpy(dbuff->p, in, inlen); - return _fr_dbuff_advance(dbuff, inlen); + return _fr_dbuff_set(dbuff, dbuff->p + inlen); } -static inline size_t _fr_dbuff_memcpy_in_dbuff_partial(fr_dbuff_t *out, fr_dbuff_t const *in, size_t inlen) +static inline size_t _fr_dbuff_memcpy_in_dbuff_partial(fr_dbuff_t *dbuff, fr_dbuff_t const *in, size_t inlen) { size_t outlen; fr_dbuff_t *in_m; if (inlen > fr_dbuff_remaining(in)) inlen = fr_dbuff_remaining(in); - outlen = fr_dbuff_remaining(out); + outlen = fr_dbuff_remaining(dbuff); if (inlen > outlen) inlen = outlen; - (void)_fr_dbuff_memcpy_in(out, in->p, inlen); + (void)_fr_dbuff_memcpy_in(dbuff, in->p, inlen); memcpy(&in_m, &in, sizeof(in_m)); /* Stupid _Generic const issues */ - return _fr_dbuff_advance(in_m, inlen); + + return _fr_dbuff_set(in_m, dbuff->p + inlen); } /** Copy at most inlen bytes into the dbuff @@ -579,101 +670,36 @@ static inline ssize_t fr_dbuff_memset(fr_dbuff_t *dbuff, uint8_t c, size_t inlen memset(dbuff->p, c, inlen); - return _fr_dbuff_advance(dbuff, inlen); + return _fr_dbuff_set(dbuff, dbuff->p + inlen); } #define FR_DBUFF_MEMSET_RETURN(_dbuff, _c, _inlen) FR_DBUFF_RETURN(fr_dbuff_memset, _dbuff, _c, _inlen) -#define FR_DBUFF_NUM_IN_FUNC(_type) \ +#define FR_DBUFF_PARSE_INT_DEF(_type) \ static inline ssize_t fr_dbuff_##_type##_in(fr_dbuff_t *dbuff, _type##_t num) \ { \ size_t freespace = fr_dbuff_remaining(dbuff); \ fr_assert(!dbuff->is_const); \ if (sizeof(_type##_t) > freespace) return -(sizeof(_type##_t) - freespace); \ fr_net_from_##_type(dbuff->p, num); \ - return _fr_dbuff_advance(dbuff, sizeof(_type##_t)); \ + return _fr_dbuff_set(dbuff, dbuff->p + sizeof(_type##_t)); \ } -FR_DBUFF_NUM_IN_FUNC(uint16) -FR_DBUFF_NUM_IN_FUNC(uint32) -FR_DBUFF_NUM_IN_FUNC(uint64) -FR_DBUFF_NUM_IN_FUNC(int16) -FR_DBUFF_NUM_IN_FUNC(int32) -FR_DBUFF_NUM_IN_FUNC(int64) - -/** Copy an unsigned 16-bit integer into a buffer in wire format (big endian) - * - * @param[in] dbuff to copy data to - * @param[in] num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (2). - * - <0 the number of bytes required - */ -#define FR_DBUFF_UINT16_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_uint16_in, _dbuff, _num) - -/** Copy an unsigned 32-bit integer into a buffer in wire format (big endian) - * - * @param[in] _dbuff to copy data to - * @param[in] _num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (4). - * - <0 the number of bytes required - */ -#define FR_DBUFF_UINT32_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_uint32_in, _dbuff, _num) - -/** Copy an unsigned 64-bit integer into a buffer in wire format (big endian) - * - * @param[in] dbuff to copy data to - * @param[in] num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (8). - * - <0 the number of bytes required - */ -#define FR_DBUFF_UINT64_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_uint64_in, _dbuff, _num) - -/** Copy a signed 16-bit integer into a buffer in wire format (big endian) - * - * @param[in] dbuff to copy data to - * @param[in] num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (2). - * - <0 the number of bytes required - */ -#define FR_DBUFF_INT16_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_int16_in, _dbuff, _num) - -/** Copy a signed 32-bit integer into a buffer in wire format (big endian) - * - * @param[in] dbuff to copy data to - * @param[in] num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (4). - * - <0 the number of bytes required - */ -#define FR_DBUFF_INT32_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_int32_in,, _dbuff, _num) - -/** Copy a signed 64-bit integer into a buffer in wire format (big endian) - * - * @param[in] dbuff to copy data to - * @param[in] num value to copy - * @return - * - 0 no data set - * - >0 the number of bytes added to the dbuff (8). - * - <0 the number of bytes required - */ -#define FR_DBUFF_INT64_IN_RETURN(_dbuff, _num) FR_DBUFF_RETURN(fr_dbuff_int64_in, _dbuff, _num) - -#define fr_dbuff_in(dbuff, value) \ - _Generic((value), \ - int16_t : fr_dbuff_int16_in(dbuff, (int16_t)value), \ - int32_t : fr_dbuff_int32_in(dbuff, (int32_t)value), \ - int64_t : fr_dbuff_int64_in(dbuff, (int64_t)value), \ - uint16_t : fr_dbuff_uint16_in(dbuff, (uint16_t)value), \ - uint32_t : fr_dbuff_uint32_in(dbuff, (uint32_t)value), \ - uint64_t : fr_dbuff_uint64_in(dbuff, (uint64_t)value) \ +FR_DBUFF_PARSE_INT_DEF(uint16) +FR_DBUFF_PARSE_INT_DEF(uint32) +FR_DBUFF_PARSE_INT_DEF(uint64) +FR_DBUFF_PARSE_INT_DEF(int16) +FR_DBUFF_PARSE_INT_DEF(int32) +FR_DBUFF_PARSE_INT_DEF(int64) + +#define fr_dbuff_in(_dbuff, _value) \ + _Generic((_value), \ + int16_t : fr_dbuff_int16_in(_dbuff, (int16_t)_value), \ + int32_t : fr_dbuff_int32_in(_dbuff, (int32_t)_value), \ + int64_t : fr_dbuff_int64_in(_dbuff, (int64_t)_value), \ + uint16_t : fr_dbuff_uint16_in(_dbuff, (uint16_t)_value), \ + uint32_t : fr_dbuff_uint32_in(_dbuff, (uint32_t)_value), \ + uint64_t : fr_dbuff_uint64_in(_dbuff, (uint64_t)_value) \ ) +#define FR_DBUFF_IN_RETURN(_dbuff, _value) FR_DBUFF_RETURN(fr_dbuff_in, _dbuff, _value) static inline ssize_t fr_dbuff_uint64v_in(fr_dbuff_t *dbuff, uint64_t num) { @@ -686,79 +712,6 @@ static inline ssize_t fr_dbuff_uint64v_in(fr_dbuff_t *dbuff, uint64_t num) } /** @} */ -/** @name Add a marker to an dbuff - * - * Markers are used to indicate an area of the code is working at a particular - * point in a string buffer. - * - * If the dbuff is performing stream parsing, then markers are used to update - * any pointers to the buffer, as the data in the buffer is shifted to make - * room for new data from the stream. - * - * If the dbuff is being used to create strings, then the markers are updated - * if the buffer is re-allocated. - * @{ - */ -/** Adds a new pointer to the beginning of the list of pointers to update - * - */ -static inline uint8_t *fr_dbuff_marker(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff) -{ - m->next = dbuff->m; /* Link into the head */ - dbuff->m = m; - - m->p = dbuff->p; /* Set the current position in the dbuff */ - - return dbuff->p; -} - -/** Trims the linked list backed to the specified pointer - * - * Pointers should be released in the inverse order to allocation. - * - * Alternatively the oldest pointer can be released, resulting in any newer pointer - * also being removed from the list. - * - * @param[in] m to release. - */ -static inline void fr_dbuff_marker_release(fr_dbuff_marker_t *m, fr_dbuff_t *dbuff) -{ - dbuff->m = m->next; -} - -/** Resets the position in an dbuff to specified marker - * - */ -static inline void fr_dbuff_set_to_marker(fr_dbuff_t *dbuff, fr_dbuff_marker_t *m) -{ - _fr_dbuff_set_recurse(dbuff, m->p); -} - -/** Return the current position of the marker - * - */ -static inline uint8_t *fr_dbuff_marker_current(fr_dbuff_marker_t *m) -{ - return m->p; -} - -/** How many free bytes remain in the buffer (calculated from marker) - * - */ -static inline size_t fr_dbuff_marker_remaining(fr_dbuff_t const *dbuff, fr_dbuff_marker_t *m) -{ - return dbuff->end - m->p; -} - -/** How many bytes we've used in the buffer (calculated from marker) - * - */ -static inline size_t fr_dbuff_marker_used(fr_dbuff_t const *dbuff, fr_dbuff_marker_t *m) -{ - return m->p - dbuff->start; -} -/** @} */ - #ifdef __cplusplus } #endif diff --git a/src/lib/util/sbuff.c b/src/lib/util/sbuff.c index 0e05e6de26a..67c5001039c 100644 --- a/src/lib/util/sbuff.c +++ b/src/lib/util/sbuff.c @@ -342,7 +342,7 @@ size_t fr_sbuff_out_bstrncpy_until(char *out, size_t outlen, fr_sbuff_t *in, siz * - 0 no bytes copied. Examine err. * - >0 the number of bytes copied. */ -#define PARSE_INT_DEF(_name, _type, _min, _max, _max_char) \ +#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) \ { \ char buff[_max_char + 1]; \ @@ -380,10 +380,10 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t return end - buff; \ } -PARSE_INT_DEF(int8, int8_t, INT8_MIN, INT8_MAX, 2) -PARSE_INT_DEF(int16, int16_t, INT16_MIN, INT16_MAX, 6) -PARSE_INT_DEF(int32, int32_t, INT32_MIN, INT32_MAX, 11) -PARSE_INT_DEF(int64, int64_t, INT64_MIN, INT64_MAX, 20) +SBUFF_PARSE_INT_DEF(int8, int8_t, INT8_MIN, INT8_MAX, 2) +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) /** Used to define a number parsing functions for singed integers * @@ -394,7 +394,7 @@ PARSE_INT_DEF(int64, int64_t, INT64_MIN, INT64_MAX, 20) * Can't use stringify because of width modifiers like 'u' * used in . */ -#define PARSE_UINT_DEF(_name, _type, _max, _max_char) \ +#define SBUFF_PARSE_UINT_DEF(_name, _type, _max, _max_char) \ size_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]; \ @@ -428,10 +428,10 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t return end - buff; \ } -PARSE_UINT_DEF(uint8, uint8_t, UINT8_MAX, 1) -PARSE_UINT_DEF(uint16, uint16_t, UINT16_MAX, 5) -PARSE_UINT_DEF(uint32, uint32_t, UINT32_MAX, 10) -PARSE_UINT_DEF(uint64, uint64_t, UINT64_MAX, 20) +SBUFF_PARSE_UINT_DEF(uint8, uint8_t, UINT8_MAX, 1) +SBUFF_PARSE_UINT_DEF(uint16, uint16_t, UINT16_MAX, 5) +SBUFF_PARSE_UINT_DEF(uint32, uint32_t, UINT32_MAX, 10) +SBUFF_PARSE_UINT_DEF(uint64, uint64_t, UINT64_MAX, 20) static bool float_chars[UINT8_MAX + 1] = { ['0'] = true, ['1'] = true, ['2'] = true, ['3'] = true, ['4'] = true, @@ -448,7 +448,7 @@ static bool float_chars[UINT8_MAX + 1] = { * Can't use stringify because of width modifiers like 'u' * used in . */ -#define PARSE_FLOAT_DEF(_name, _type, _func, _max_char) \ +#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) \ { \ char buffer[_max_char + 1]; \ @@ -477,8 +477,8 @@ size_t fr_sbuff_out_##_name(fr_sbuff_parse_error_t *err, _type *out, fr_sbuff_t return fr_sbuff_advance(in, end - buffer); \ } -PARSE_FLOAT_DEF(float32, float, strtof, 100); -PARSE_FLOAT_DEF(float64, double, strtod, 100); +SBUFF_PARSE_FLOAT_DEF(float32, float, strtof, 100); +SBUFF_PARSE_FLOAT_DEF(float64, double, strtod, 100); /** Copy bytes into the sbuff up to the first \0 * diff --git a/src/lib/util/sbuff.h b/src/lib/util/sbuff.h index 4fba9b39679..d8297932ffb 100644 --- a/src/lib/util/sbuff.h +++ b/src/lib/util/sbuff.h @@ -204,6 +204,222 @@ do { \ /** @} */ +/** @name Accessors + * + * Caching the values of these pointers or the pointer values from the sbuff + * directly is strongly discouraged as they can become invalidated during + * stream parsing or when printing to an auto-expanding buffer. + * + * These functions should only be used to pass sbuff pointers into 3rd party + * APIs. + */ +static inline char *fr_sbuff_start(fr_sbuff_t *sbuff) +{ + return sbuff->start; +} + +static inline char *fr_sbuff_current(fr_sbuff_t *sbuff) +{ + return sbuff->p; +} + +static inline char *fr_sbuff_end(fr_sbuff_t *sbuff) +{ + return sbuff->end; +} +/** @} */ + +/** @name Position modification (recursive) + * + * Change the current position of pointers in the sbuff and their children. + * @{ + */ + +/** Update the position of p in a list of sbuffs + * + * @note Do not call directly. + */ +static inline void _fr_sbuff_set_recurse(fr_sbuff_t *sbuff, char const *p) +{ + sbuff->p_i = p; + if (sbuff->adv_parent && sbuff->parent) _fr_sbuff_set_recurse(sbuff->parent, p); +} + +/** Advance position in sbuff by N bytes + * + * @param[in] sbuff to advance. + * @param[in] n How much to advance sbuff by. + * @return + * - 0 not advanced. + * - >0 the number of bytes the sbuff was advanced by. + * - <0 the number of bytes required to complete the advancement + */ +static inline ssize_t fr_sbuff_advance(fr_sbuff_t *sbuff, size_t n) +{ + size_t freespace = fr_sbuff_remaining(sbuff); + if (n > freespace) return -(n - freespace); + _fr_sbuff_set_recurse(sbuff, sbuff->p + n); + return n; +} +#define FR_SBUFF_ADVANCE_RETURN(_sbuff, _n) FR_SBUFF_RETURN(fr_sbuff_advance, _sbuff, _n) + +/** Set a new position for 'p' in an sbuff + * + * @param[out] sbuff sbuff to set a position in. + * @param[in] p Position to set. + * @return + * - 0 not advanced. + * - >0 the number of bytes the sbuff was advanced by. + * - <0 the number of bytes required to complete the advancement + */ +static inline ssize_t _fr_sbuff_set(fr_sbuff_t *sbuff, char const *p) +{ + char const *c; + + if (unlikely(p > sbuff->end)) return -(p - sbuff->end); + if (unlikely(p < sbuff->start)) return 0; + + c = sbuff->p; + _fr_sbuff_set_recurse(sbuff, p); + + return p - c; +} + +/** Set the position in a sbuff using another sbuff, a char pointer, or a length + * + * @param[out] _dst sbuff to advance. + * @param[in] _src An sbuff, char pointer, or length value to advance + * _dst by. + * @return + * - 0 not advanced. + * - >0 the number of bytes the sbuff was advanced by. + * - <0 the number of bytes required to complete the advancement + */ +#define fr_sbuff_set(_dst, _src) \ +_fr_sbuff_set(_dst, \ + _Generic(_src, \ + fr_sbuff_t * : (_src)->p, \ + char const * : (_src), \ + char * : (_src), \ + size_t : ((_dst)->p += (uintptr_t)(_src)) \ + )) + + +/** Reset the current position of the sbuff to the start of the string + * + */ +static inline void fr_sbuff_set_to_start(fr_sbuff_t *sbuff) +{ + _fr_sbuff_set_recurse(sbuff, sbuff->start); +} + +/** Reset the current position of the sbuff to the end of the string + * + */ +static inline void fr_sbuff_set_to_end(fr_sbuff_t *sbuff) +{ + _fr_sbuff_set_recurse(sbuff, sbuff->end); +} +/** @} */ + +/** @name Add a marker to an sbuff + * + * Markers are used to indicate an area of the code is working at a particular + * point in a string buffer. + * + * If the sbuff is performing stream parsing, then markers are used to update + * any pointers to the buffer, as the data in the buffer is shifted to make + * room for new data from the stream. + * + * If the sbuff is being used to create strings, then the markers are updated + * if the buffer is re-allocated. + * @{ + */ +/** Adds a new pointer to the beginning of the list of pointers to update + * + */ +static inline char *fr_sbuff_marker(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff) +{ + m->next = sbuff->m; /* Link into the head */ + sbuff->m = m; + + m->p = sbuff->p; /* Set the current position in the sbuff */ + + return sbuff->p; +} + +/** Trims the linked list backed to the specified pointer + * + * Pointers should be released in the inverse order to allocation. + * + * Alternatively the oldest pointer can be released, resulting in any newer pointer + * also being removed from the list. + * + * @param[in] m to release. + */ +static inline void fr_sbuff_marker_release(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff) +{ + if (unlikely(sbuff->m != m)) return; + sbuff->m = m->next; +} + +/** Resets the position in an sbuff to specified marker + * + */ +static inline void fr_sbuff_set_to_marker(fr_sbuff_t *sbuff, fr_sbuff_marker_t *m) +{ + _fr_sbuff_set_recurse(sbuff, m->p); +} + +/** Return the current position of the marker + * + */ +static inline char *fr_sbuff_marker_current(fr_sbuff_marker_t *m) +{ + return m->p; +} + +/** How many free bytes remain in the buffer (calculated from marker) + * + */ +static inline size_t fr_sbuff_marker_remaining(fr_sbuff_t const *sbuff, fr_sbuff_marker_t *m) +{ + return sbuff->end - m->p; +} + +/** How many bytes we've used in the buffer (calculated from marker) + * + */ +static inline size_t fr_sbuff_marker_used(fr_sbuff_t const *sbuff, fr_sbuff_marker_t *m) +{ + return m->p - sbuff->start; +} +/** @} */ + +/** @name Position modification (non-recursive) + * + * Change the current position of pointers in the sbuff + * @{ + */ + +/** Set the start pointer to the current value of p + * + */ +static inline void fr_sbuff_trim_start(fr_sbuff_t *sbuff) +{ + sbuff->start = sbuff->p; +} + +/** Set the end pointer to the current value of p + * + */ +static inline void fr_sbuff_trim_end(fr_sbuff_t *sbuff) +{ + sbuff->end = sbuff->p; +} + +/** @} */ + /** @name Copy/print data to an sbuff * * These functions are typically used for printing. @@ -483,226 +699,6 @@ static inline bool fr_sbuff_is_space(fr_sbuff_t *sbuff) } /** @} */ -/** @name Sbuff position manipulation - * @{ - */ - -/** @name Accessors - * - * Caching the values of these pointers or the pointer values from the sbuff - * directly is strongly discouraged as they can become invalidated during - * stream parsing or when printing to an auto-expanding buffer. - * - * These functions should only be used to pass sbuff pointers into 3rd party - * APIs. - */ -static inline char *fr_sbuff_start(fr_sbuff_t *sbuff) -{ - return sbuff->start; -} - -static inline char *fr_sbuff_current(fr_sbuff_t *sbuff) -{ - return sbuff->p; -} - -static inline char *fr_sbuff_end(fr_sbuff_t *sbuff) -{ - return sbuff->end; -} -/** @} */ - -/** @name Position modification (recursive) - * - * Change the current position of pointers in the sbuff and their children. - * @{ - */ - -/** Update the position of p in a list of sbuffs - * - * @note Do not call directly. - */ -static inline void _fr_sbuff_set_recurse(fr_sbuff_t *sbuff, char const *p) -{ - sbuff->p_i = p; - if (sbuff->adv_parent && sbuff->parent) _fr_sbuff_set_recurse(sbuff->parent, p); -} - -/** Advance position in sbuff by N bytes - * - * @param[in] sbuff to advance. - * @param[in] n How much to advance sbuff by. - * @return - * - 0 not advanced. - * - >0 the number of bytes the sbuff was advanced by. - * - <0 the number of bytes required to complete the advancement - */ -static inline ssize_t fr_sbuff_advance(fr_sbuff_t *sbuff, size_t n) -{ - size_t freespace = fr_sbuff_remaining(sbuff); - if (n > freespace) return -(n - freespace); - _fr_sbuff_set_recurse(sbuff, sbuff->p + n); - return n; -} -#define FR_SBUFF_ADVANCE_RETURN(_sbuff, _n) FR_SBUFF_RETURN(fr_sbuff_advance, _sbuff, _n) - -/** Set a new position for 'p' in an sbuff - * - * @param[out] sbuff sbuff to set a position in. - * @param[in] p Position to set. - * @return - * - 0 not advanced. - * - >0 the number of bytes the sbuff was advanced by. - * - <0 the number of bytes required to complete the advancement - */ -static inline ssize_t _fr_sbuff_set(fr_sbuff_t *sbuff, char const *p) -{ - char const *c; - - if (unlikely(p > sbuff->end)) return -(p - sbuff->end); - if (unlikely(p < sbuff->start)) return 0; - - c = sbuff->p; - _fr_sbuff_set_recurse(sbuff, p); - - return p - c; -} - -/** Set the position in a sbuff using another sbuff, a char pointer, or a length - * - * @param[out] _dst sbuff to advance. - * @param[in] _src An sbuff, char pointer, or length value to advance - * _dst by. - * @return - * - 0 not advanced. - * - >0 the number of bytes the sbuff was advanced by. - * - <0 the number of bytes required to complete the advancement - */ -#define fr_sbuff_set(_dst, _src) \ -_fr_sbuff_set(_dst, \ - _Generic(_src, \ - fr_sbuff_t * : (_src)->p, \ - char const * : (_src), \ - char * : (_src), \ - size_t : ((_dst)->p += (uintptr_t)(_src)) \ - )) - - -/** Reset the current position of the sbuff to the start of the string - * - */ -static inline void fr_sbuff_set_to_start(fr_sbuff_t *sbuff) -{ - _fr_sbuff_set_recurse(sbuff, sbuff->start); -} - -/** Reset the current position of the sbuff to the end of the string - * - */ -static inline void fr_sbuff_set_to_end(fr_sbuff_t *sbuff) -{ - _fr_sbuff_set_recurse(sbuff, sbuff->end); -} -/** @} */ - -/** @name Add a marker to an sbuff - * - * Markers are used to indicate an area of the code is working at a particular - * point in a string buffer. - * - * If the sbuff is performing stream parsing, then markers are used to update - * any pointers to the buffer, as the data in the buffer is shifted to make - * room for new data from the stream. - * - * If the sbuff is being used to create strings, then the markers are updated - * if the buffer is re-allocated. - * @{ - */ -/** Adds a new pointer to the beginning of the list of pointers to update - * - */ -static inline char *fr_sbuff_marker(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff) -{ - m->next = sbuff->m; /* Link into the head */ - sbuff->m = m; - - m->p = sbuff->p; /* Set the current position in the sbuff */ - - return sbuff->p; -} - -/** Trims the linked list backed to the specified pointer - * - * Pointers should be released in the inverse order to allocation. - * - * Alternatively the oldest pointer can be released, resulting in any newer pointer - * also being removed from the list. - * - * @param[in] m to release. - */ -static inline void fr_sbuff_marker_release(fr_sbuff_marker_t *m, fr_sbuff_t *sbuff) -{ - if (unlikely(sbuff->m != m)) return; - sbuff->m = m->next; -} - -/** Resets the position in an sbuff to specified marker - * - */ -static inline void fr_sbuff_set_to_marker(fr_sbuff_t *sbuff, fr_sbuff_marker_t *m) -{ - _fr_sbuff_set_recurse(sbuff, m->p); -} - -/** Return the current position of the marker - * - */ -static inline char *fr_sbuff_marker_current(fr_sbuff_marker_t *m) -{ - return m->p; -} - -/** How many free bytes remain in the buffer (calculated from marker) - * - */ -static inline size_t fr_sbuff_marker_remaining(fr_sbuff_t const *sbuff, fr_sbuff_marker_t *m) -{ - return sbuff->end - m->p; -} - -/** How many bytes we've used in the buffer (calculated from marker) - * - */ -static inline size_t fr_sbuff_marker_used(fr_sbuff_t const *sbuff, fr_sbuff_marker_t *m) -{ - return m->p - sbuff->start; -} -/** @} */ - -/** @name Position modification (non-recursive) - * - * Change the current position of pointers in the sbuff - * @{ - */ - -/** Set the start pointer to the current value of p - * - */ -static inline void fr_sbuff_trim_start(fr_sbuff_t *sbuff) -{ - sbuff->start = sbuff->p; -} - -/** Set the end pointer to the current value of p - * - */ -static inline void fr_sbuff_trim_end(fr_sbuff_t *sbuff) -{ - sbuff->end = sbuff->p; -} - -/** @} */ - #ifdef __cplusplus } #endif diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 68914fd7752..cd5199c04f8 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -1231,7 +1231,7 @@ static ssize_t encode_vsa_hdr(fr_dbuff_t *dbuff, return PAIR_ENCODE_FATAL_ERROR; } - FR_DBUFF_UINT32_IN_RETURN(&work_dbuff, da->attr); /* Copy in the 32bit vendor ID */ + FR_DBUFF_IN_RETURN(&work_dbuff, (uint32_t)da->attr); /* Copy in the 32bit vendor ID */ len = encode_vendor_attr_hdr(&FR_DBUFF_MAX(&work_dbuff, 255 - 6), da_stack, depth, cursor, encoder_ctx); if (len < 0) return len;