From: Alan T. DeKok Date: Tue, 12 Sep 2023 18:02:26 +0000 (-0400) Subject: add and use fr_pair_dcursor_child_iter_init() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c72de14356912ea50888a3e4a94fec4854da5d35;p=thirdparty%2Ffreeradius-server.git add and use fr_pair_dcursor_child_iter_init() all of the encoders previously just called fr_pair_dcursor_init() for child cursors. Which meant that the iterator could return internal attributes. The child cursor now uses the same iterator as the parent cursor. This ensures that it only returns the correct encodable attributes for this protocol. --- diff --git a/src/lib/util/dcursor.h b/src/lib/util/dcursor.h index acfc4e2562f..961eae09c28 100644 --- a/src/lib/util/dcursor.h +++ b/src/lib/util/dcursor.h @@ -195,6 +195,33 @@ static inline void fr_dcursor_copy(fr_dcursor_t *out, fr_dcursor_t const *in) if (in->copy) fr_dcursor_copy(out, in); } +/** Copy a read-only iterator from a parent to a child cursor + * + * @param[out] out Where to copy the cursor to. + * @param[in] in cursor to copy. + * + * @hidecallergraph + */ +CC_HINT(nonnull) +static inline void fr_dcursor_copy_iter(fr_dcursor_t *out, fr_dcursor_t const *in) +{ + fr_assert(!out->iter); + fr_assert(!out->iter_uctx); + + out->iter = in->iter; + out->iter_uctx = in->iter_uctx; + +#ifndef NDEBUG + /* + * The output cursor has to be read-only. + */ + out->insert = NULL; + out->remove = NULL; + out->mod_uctx = NULL; + out->copy = NULL; +#endif +} + /** Rewind cursor to the start of the list * * @param[in] cursor to operate on. diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index 8f7562517a8..6658354325f 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -580,6 +580,27 @@ fr_pair_t *_fr_pair_dcursor_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const fr_pair_t *_fr_pair_dcursor_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, bool is_const) CC_HINT(nonnull); +/** Initializes a child dcursor from a parent cursor, with an iteration function. + * + * Filters can be applied later with fr_dcursor_filter_set. + * + * @note This is the only way to use a dcursor in non-const mode with fr_pair_list_t. + * + * @param[out] cursor to initialise. + * @param[in] list to iterate over. + * @param[in] parent parent cursor to take the iterator from + * @return + * - NULL if src does not point to any items. + * - The first pair in the list. + */ +static inline fr_pair_t *fr_pair_dcursor_child_iter_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dcursor_t const *parent) +{ + fr_pair_t *vp = fr_pair_dcursor_init(cursor, list); + + fr_dcursor_copy_iter(cursor, parent); + return vp; +} + /** Initialise a cursor that will return only attributes matching the specified #fr_dict_attr_t * * @param[in] _cursor to initialise. diff --git a/src/protocols/dhcpv4/encode.c b/src/protocols/dhcpv4/encode.c index dce93f68043..c8c61847ce3 100644 --- a/src/protocols/dhcpv4/encode.c +++ b/src/protocols/dhcpv4/encode.c @@ -386,7 +386,7 @@ static ssize_t encode_child(fr_dbuff_t *dbuff, fr_assert(fr_type_is_structural(vp->vp_type)); - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); work_dbuff = FR_DBUFF(dbuff); while ((vp = fr_dcursor_current(&child_cursor)) != NULL) { diff --git a/src/protocols/dhcpv6/encode.c b/src/protocols/dhcpv6/encode.c index 110b67e222b..7e95163b117 100644 --- a/src/protocols/dhcpv6/encode.c +++ b/src/protocols/dhcpv6/encode.c @@ -283,7 +283,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, * Encode the child options. */ if (!fr_pair_list_empty(&vp->vp_group)) { - (void) fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + (void) fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); while (fr_dcursor_current(&child_cursor) != NULL) { slen = fr_dhcpv6_encode_option(&work_dbuff, &child_cursor, encode_ctx); @@ -400,7 +400,7 @@ static ssize_t encode_child(fr_dbuff_t *dbuff, fr_assert(fr_type_is_structural(vp->vp_type)); - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); work_dbuff = FR_DBUFF(dbuff); while ((vp = fr_dcursor_current(&child_cursor)) != NULL) { diff --git a/src/protocols/dns/encode.c b/src/protocols/dns/encode.c index bef5418b784..ba782477a7a 100644 --- a/src/protocols/dns/encode.c +++ b/src/protocols/dns/encode.c @@ -95,7 +95,7 @@ static ssize_t encode_value(fr_dbuff_t *dbuff, if (vp->vp_type == FR_TYPE_STRUCT) { fr_dcursor_t child_cursor; - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); slen = fr_struct_to_network(&work_dbuff, da_stack, depth, &child_cursor, encode_ctx, encode_value, encode_child); if (slen < 0) return slen; @@ -248,7 +248,7 @@ static ssize_t encode_child(fr_dbuff_t *dbuff, fr_assert(fr_type_is_structural(vp->vp_type)); - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); work_dbuff = FR_DBUFF(dbuff); while ((vp = fr_dcursor_current(&child_cursor)) != NULL) { @@ -391,7 +391,7 @@ static ssize_t fr_dns_encode_rr(fr_dbuff_t *dbuff, fr_dcursor_t *cursor, void *e if (vp->vp_type == FR_TYPE_STRUCT) { fr_dcursor_t child_cursor; - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); slen = fr_struct_to_network(&work_dbuff, &da_stack, 0, &child_cursor, encode_ctx, encode_value, encode_child); if (slen <= 0) return slen; diff --git a/src/protocols/radius/encode.c b/src/protocols/radius/encode.c index 0a6ac3d5753..0300ec8b219 100644 --- a/src/protocols/radius/encode.c +++ b/src/protocols/radius/encode.c @@ -251,7 +251,7 @@ static ssize_t encode_tlv(fr_dbuff_t *dbuff, return PAIR_ENCODE_SKIPPED; } - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); vp = fr_dcursor_current(&child_cursor); fr_proto_da_stack_build(da_stack, vp->da); @@ -855,7 +855,7 @@ static ssize_t encode_extended_nested(fr_dbuff_t *dbuff, parent = fr_dcursor_current(cursor); fr_assert(fr_type_is_structural(parent->vp_type)); - (void) fr_pair_dcursor_init(&child_cursor, &parent->vp_group); + (void) fr_pair_dcursor_child_iter_init(&child_cursor, &parent->vp_group, cursor); FR_PROTO_STACK_PRINT(da_stack, depth); @@ -1190,7 +1190,7 @@ static ssize_t encode_vendor(fr_dbuff_t *dbuff, fr_assert(vp->da == da); work_dbuff = FR_DBUFF(dbuff); - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); while ((vp = fr_dcursor_current(&child_cursor)) != NULL) { fr_proto_da_stack_build(da_stack, vp->da); @@ -1252,7 +1252,7 @@ static ssize_t encode_vsa(fr_dbuff_t *dbuff, * Loop over the children of this Vendor-Specific * attribute. */ - fr_pair_dcursor_init(&child_cursor, &vp->vp_group); + fr_pair_dcursor_child_iter_init(&child_cursor, &vp->vp_group, cursor); while ((vp = fr_dcursor_current(&child_cursor)) != NULL) { fr_proto_da_stack_build(da_stack, vp->da);