diff --git a/src/lib/util/dbuff.h b/src/lib/util/dbuff.h index e14079ea041c..ce421a309d6d 100644 --- a/src/lib/util/dbuff.h +++ b/src/lib/util/dbuff.h @@ -336,15 +336,15 @@ static inline void _fr_dbuff_set_recurse(fr_dbuff_t *dbuff, uint8_t const *p) * @param[out] dbuff dbuff to set a position in. * @param[in] p Position to set. * @return - * - 0 not advanced. - * - >0 the number of bytes the dbuff was advanced by. - * - <0 the number of bytes required to complete the advancement + * - 0 not advanced (p out of range). + * - >0 the number of bytes the dbuff advanced by. + * - <0 the number of bytes the dbuff retreated by. */ static inline ssize_t _fr_dbuff_set(fr_dbuff_t *dbuff, uint8_t const *p) { uint8_t *c; - if (unlikely(p > dbuff->end)) return -(p - dbuff->end); + if (unlikely(p > dbuff->end)) return 0; if (unlikely(p < dbuff->start)) return 0; c = dbuff->p; @@ -359,7 +359,7 @@ static inline ssize_t _fr_dbuff_set(fr_dbuff_t *dbuff, uint8_t const *p) * @param[in] _src An dbuff, char pointer, or length value to advance * _dst by. * @return - * - 0 not advanced. + * - 0 not advanced (_src out of range). * - >0 the number of bytes the dbuff was advanced by. * - <0 the number of bytes required to complete the advancement */ @@ -383,8 +383,7 @@ _fr_dbuff_set(_dst, \ */ 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); + if ((dbuff->p + n) > dbuff->end) return 0; _fr_dbuff_set_recurse(dbuff, dbuff->p + n); return n; } @@ -456,6 +455,42 @@ static inline void fr_dbuff_marker_release(fr_dbuff_marker_t *m) #endif } +/** Change the position in the buffer a marker points to + * + * @param[in] m marker to alter. + * @param[in] p Position to set. + * @return + * - 0 on failure (p out of range), marker position will remain unchanged. + * - >0 the number of bytes the marker advanced. + * - <0 the number of bytes the marker retreated. + */ +static inline ssize_t fr_dbuff_marker_set(fr_dbuff_marker_t *m, uint8_t const *p) +{ + fr_dbuff_t *dbuff = m->parent; + uint8_t *current = m->p; + + if (unlikely(p > dbuff->end)) return 0; + if (unlikely(p < dbuff->start)) return 0; + + m->p_i = p; + + return p - current; +} + +/** Change the position in the buffer a marker points to + * + * @param[in] m marker to alter. + * @param[in] len how much to advance the marker by. + * @return + * - 0 on failure (p out of range), marker position will remain unchanged. + * - >0 the number of bytes the marker advanced. + * - <0 the number of bytes the marker retreated. + */ +static inline ssize_t fr_dbuff_marker_advance(fr_dbuff_marker_t *m, size_t len) +{ + return fr_dbuff_marker_set(m, m->p + len); +} + /** Resets the position in an dbuff to specified marker * */ diff --git a/src/lib/util/sbuff.h b/src/lib/util/sbuff.h index d16d39de705e..f80dc0da4b15 100644 --- a/src/lib/util/sbuff.h +++ b/src/lib/util/sbuff.h @@ -43,7 +43,7 @@ extern "C" { typedef struct fr_sbuff_s fr_sbuff_t; typedef struct fr_sbuff_ptr_s fr_sbuff_marker_t; -typedef int(*fr_sbuff_extend_t)(fr_sbuff_t *sbuff, void *uctx); +typedef int(*fr_sbuff_extend_t)(fr_sbuff_t *sbuff, size_t req_extenison); struct fr_sbuff_ptr_s { union { @@ -79,6 +79,8 @@ struct fr_sbuff_s { ///< buffer changes. fr_sbuff_extend_t extend; //!< Function to re-populate or extend ///< the buffer. + size_t shifted; //!< How many bytes this sbuff has been + ///< shifted since its creation. }; typedef enum { @@ -184,6 +186,14 @@ static inline size_t fr_sbuff_used(fr_sbuff_t const *sbuff) return sbuff->p - sbuff->start; } +/** How many bytes we've used in the buffer including shifts + * + */ +static inline size_t fr_sbuff_used_total(fr_sbuff_t const *sbuff) +{ + return (sbuff->p - sbuff->start) + sbuff->shifted; +} + /** How many bytes in the buffer total * */ @@ -264,8 +274,7 @@ static inline void _fr_sbuff_set_recurse(fr_sbuff_t *sbuff, char const *p) */ 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); + if ((sbuff->p + n) > sbuff->end) return 0; _fr_sbuff_set_recurse(sbuff, sbuff->p + n); return n; } @@ -284,7 +293,7 @@ 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->end)) return 0; if (unlikely(p < sbuff->start)) return 0; c = sbuff->p; @@ -379,6 +388,42 @@ static inline void fr_sbuff_marker_release(fr_sbuff_marker_t *m) #endif } +/** Change the position in the buffer a marker points to + * + * @param[in] m marker to alter. + * @param[in] p Position to set. + * @return + * - 0 on failure (p out of range), marker position will remain unchanged. + * - >0 the number of bytes the marker advanced. + * - <0 the number of bytes the marker retreated. + */ +static inline ssize_t fr_sbuff_marker_set(fr_sbuff_marker_t *m, char const *p) +{ + fr_sbuff_t *sbuff = m->parent; + char *current = m->p; + + if (unlikely(p > sbuff->end)) return 0; + if (unlikely(p < sbuff->start)) return 0; + + m->p_i = p; + + return p - current; +} + +/** Change the position in the buffer a marker points to + * + * @param[in] m marker to alter. + * @param[in] len how much to advance the marker by. + * @return + * - 0 on failure (p out of range), marker position will remain unchanged. + * - >0 the number of bytes the marker advanced. + * - <0 the number of bytes the marker retreated. + */ +static inline ssize_t fr_sbuff_marker_advance(fr_sbuff_marker_t *m, size_t len) +{ + return fr_sbuff_marker_set(m, m->p + len); +} + /** Resets the position in an sbuff to specified marker * */ @@ -536,10 +581,10 @@ do { \ if (_match_len) *(_match_len) = _match_len_tmp; \ } while (0) -size_t fr_sbuff_out_talloc_bstrncpy_exact(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len); - size_t fr_sbuff_out_talloc_bstrncpy(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len); +size_t fr_sbuff_out_talloc_bstrncpy_exact(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len); + size_t fr_sbuff_out_talloc_bstrncpy_allowed(TALLOC_CTX *ctx, char **out, fr_sbuff_t *in, size_t len, bool const allowed_chars[static UINT8_MAX + 1]);