]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Rework list concat functions
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 20 Sep 2021 21:24:59 +0000 (16:24 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 20 Sep 2021 21:44:34 +0000 (16:44 -0500)
14 files changed:
src/lib/server/map_async.c
src/lib/unlang/map.c
src/lib/unlang/xlat_builtin.c
src/lib/unlang/xlat_eval.c
src/lib/util/dlist.h
src/lib/util/value.c
src/lib/util/value.h
src/modules/rlm_cipher/rlm_cipher.c
src/modules/rlm_client/rlm_client.c
src/modules/rlm_csv/rlm_csv.c
src/modules/rlm_json/rlm_json.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_rest/rlm_rest.c
src/modules/rlm_sql/rlm_sql.c

index 121d2392b594789079b2ad3bf3304d5d3936dcab..72337adf7e4c6229c5d5806759d3745dbe894119 100644 (file)
@@ -318,7 +318,10 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                 *      This should always be a noop, but included
                 *      here for robustness.
                 */
-               if (fr_value_box_list_concat(lhs_result_head, lhs_result_head, lhs_result, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(lhs_result_head,
+                                                     lhs_result_head, lhs_result, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        RPEDEBUG("Left side expansion failed");
                        fr_dlist_talloc_free(lhs_result);
                        goto error;
@@ -703,7 +706,10 @@ int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out,
                 *      This should always be a noop, but included
                 *      here for robustness.
                 */
-               if (fr_value_box_list_concat(rhs_result_head, rhs_result_head, rhs_result, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(rhs_result_head,
+                                                     rhs_result_head, rhs_result, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        RPEDEBUG("Right side expansion failed");
                        fr_dlist_talloc_free(rhs_result);
                        goto error;
index 7e6cfe7e7b109c4a06ed4ce5c4888d82da19618e..dc0c5a78028c2fac3e5c81142f50038e3168acf6 100644 (file)
@@ -223,8 +223,10 @@ static unlang_action_t list_mod_create(rlm_rcode_t *p_result, request_t *request
                         *      Concat the top level results together
                         */
                        if (!fr_dlist_empty(&update_state->rhs_result) &&
-                           (fr_value_box_list_concat(update_state, fr_dlist_head(&update_state->rhs_result), &update_state->rhs_result,
-                                                     FR_TYPE_STRING, true) < 0)) {
+                           (fr_value_box_list_concat_in_place(update_state,
+                                                              fr_dlist_head(&update_state->rhs_result), &update_state->rhs_result, FR_TYPE_STRING,
+                                                              FR_VALUE_BOX_LIST_FREE, true,
+                                                              SIZE_MAX) < 0)) {
                                RPEDEBUG("Failed concatenating RHS expansion results");
                                goto error;
                        }
index 64f443c3f7f9fb44d4b2c88ac67c7377bb660dac..134c2bdc609a66b7c78e80f5b7b7f554abbe0e9d 100644 (file)
@@ -2440,7 +2440,10 @@ static xlat_action_t xlat_func_regex(TALLOC_CTX *ctx, fr_dcursor_t *out,
                /*
                 *      Concatenate all input
                 */
-               if (fr_value_box_list_concat(ctx, in_head, in, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(ctx,
+                                                     in_head, in, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        RPEDEBUG("Failed concatenating input");
                        return XLAT_ACTION_FAIL;
                }
index 8a2a2435debdb606b579e0bb1cef0e89ef39491c..a5895ef751696ec2c64efa642bae1baed6ded3c4 100644 (file)
@@ -285,10 +285,14 @@ do { \
                        vb = fr_dlist_head(list);       /* Reset */
                }
 
-               if (fr_value_box_list_concat(ctx, vb, list, arg->type, true) < 0) {
-                       RPEDEBUG("Failed concatenating argument %u", arg_num);
+               if (fr_value_box_list_concat_in_place(ctx,
+                                                     vb, list, arg->type,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
+                       RPEDEBUG("Failed concatenating arguments");
                        return XLAT_ACTION_FAIL;
                }
+               fr_assert(fr_dlist_num_elements(list) <= 1);
 
                return XLAT_ACTION_DONE;
        }
index 71197bf9d903c26dbba06c17f190a5c897fe45d6..2d47885ce6c7f6b8baa735c0cb34d644282784e1 100644 (file)
@@ -78,7 +78,6 @@ static_assert(sizeof(unsigned int) >= 4, "Unsigned integer too small on this pla
  * @param[in] _type            of item the list contains.
  * @param[in] _iter            Name of iteration variable.
  *                             Will be declared in the scope of the loop.
- * @param[in] _tmp             A fr_dlist_t to hold the iteration state.
  */
 #define fr_dlist_foreach_safe(_list_head, _type, _iter) \
 { \
index 91b42210ff5734d658ea4dc3689b8308fda2c337..e72c892d6193a0fcfed45bdcf90312e9a6ffca9b 100644 (file)
@@ -5151,6 +5151,179 @@ ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, f
        return fr_sbuff_set(out, &our_out);
 }
 
+/** Concatenate a list of value boxes together
+ *
+ * All boxes will be removed from the list.
+ *
+ * @param[out] tainted         If nonnull, will be set to true if any input boxes are tainted.
+ *                             bool pointed to must be initialised.
+ * @param[out] sbuff           to write the result of the concatenation to.
+ * @param[in] list             to concatenate.
+ * @param[in] sep              Insert a separator between the values.
+ * @param[in] sep_len          Length of the separator.
+ * @param[in] e_rules          To apply to FR_TYPE_STRING types.
+ *                             Is not currently applied to any other box type.
+ * @param[in] proc_action      What to do with the boxes in the list once
+ *                             they've been processed.
+ * @param[in] flatten          If true and we encounter a #FR_TYPE_GROUP,
+ *                             we concat the contents of its children together.
+ *                             If false, the contents will be cast to #type.
+ * @return
+ *      - >=0 the number of bytes written to the sbuff.
+ *     - <0 how many additional bytes we would have needed to
+ *       concat the next box.
+ */
+ssize_t fr_value_box_list_concat_as_string(bool *tainted, fr_sbuff_t *sbuff, fr_value_box_list_t *list,
+                                          char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules,
+                                          fr_value_box_list_action_t proc_action, bool flatten)
+{
+       fr_sbuff_t our_sbuff = FR_SBUFF_NO_ADVANCE(sbuff);
+       ssize_t slen;
+
+       if (fr_dlist_empty(list)) return 0;
+
+       fr_dlist_foreach(list, fr_value_box_t, vb) {
+               switch (vb->type) {
+               case FR_TYPE_GROUP:
+                       if (!flatten) goto cast;
+                       slen = fr_value_box_list_concat_as_string(tainted, &our_sbuff, &vb->vb_group,
+                                                                 sep, sep_len, e_rules,
+                                                                 proc_action, flatten);
+                       break;
+
+               case FR_TYPE_OCTETS:
+                       slen = fr_sbuff_in_bstrncpy(&our_sbuff, (char const *)vb->vb_strvalue, vb->vb_length);
+                       break;
+
+               case FR_TYPE_STRING:
+                       slen = fr_sbuff_in_bstrncpy(&our_sbuff, vb->vb_strvalue, vb->vb_length);
+                       break;
+
+               default:
+               cast:
+                       slen = fr_value_box_print(&our_sbuff, vb, e_rules);
+                       break;
+               }
+               if (slen < 0) {
+               error:
+                       return slen;
+               }
+
+               if (sep && fr_dlist_next(list, vb)) {
+                       slen = fr_sbuff_in_bstrncpy(&our_sbuff, sep, sep_len);
+                       if (slen < 0) goto error;
+               }
+       }
+
+       /*
+        *      Free the boxes last so if there's
+        *      an issue concating them, everything
+        *      is still in a known state.
+        */
+       fr_dlist_foreach_safe(list, fr_value_box_t, vb) {
+               if (tainted && vb->tainted) *tainted = true;
+
+               if (vb_should_remove(proc_action)) fr_dlist_remove(list, vb);
+               if (vb_should_free_value(proc_action)) fr_value_box_clear(vb);
+               if (vb_should_free(proc_action)) talloc_free(vb);
+       }}
+
+       return fr_sbuff_set(sbuff, &our_sbuff);
+}
+
+/** Concatenate a list of value boxes together
+ *
+ * All boxes will be removed from the list.
+ *
+ * @param[out] tainted         If nonnull, will be set to true if any input boxes are tainted.
+ *                             bool pointed to must be initialised.
+ * @param[out] dbuff           to write the result of the concatenation to.
+ * @param[in] list             to concatenate.
+ * @param[in] sep              Insert a separator between the values.
+ * @param[in] sep_len          Length of the separator.
+ * @param[in] proc_action      What to do with the boxes in the list once
+ *                             they've been processed.
+ * @param[in] flatten          If true and we encounter a #FR_TYPE_GROUP,
+ *                             we concat the contents of its children together.
+ *                             If false, the contents will be cast to #type.
+ * @return
+ *      - >=0 the number of bytes written to the sbuff.
+ *     - <0 how many additional bytes we would have needed to
+ *       concat the next box.
+ */
+ssize_t fr_value_box_list_concat_as_octets(bool *tainted, fr_dbuff_t *dbuff, fr_value_box_list_t *list,
+                                          uint8_t const *sep, size_t sep_len,
+                                          fr_value_box_list_action_t proc_action, bool flatten)
+{
+       fr_dbuff_t      our_dbuff = FR_DBUFF(dbuff);
+       TALLOC_CTX      *tmp_ctx = NULL;
+       ssize_t         slen;
+
+       if (fr_dlist_empty(list)) return 0;
+
+       fr_dlist_foreach(list, fr_value_box_t, vb) {
+               switch (vb->type) {
+               case FR_TYPE_GROUP:
+                       if (!flatten) goto cast;
+                       slen = fr_value_box_list_concat_as_octets(tainted, &our_dbuff, &vb->vb_group,
+                                                                 sep, sep_len,
+                                                                 proc_action, flatten);
+                       break;
+
+               case FR_TYPE_OCTETS:
+                       slen = fr_dbuff_in_memcpy(&our_dbuff, vb->vb_octets, vb->vb_length);
+                       break;
+
+               case FR_TYPE_STRING:
+                       slen = fr_dbuff_in_memcpy(&our_dbuff, (uint8_t const *)vb->vb_strvalue, vb->vb_length);
+                       break;
+
+               default:
+               cast:
+                       if (!tmp_ctx) tmp_ctx = talloc_pool(NULL, 1024);
+                       fr_value_box_t tmp_vb;
+
+                       /*
+                        *      Not equivalent to fr_value_box_to_network
+                        */
+                       if (fr_value_box_cast_to_octets(tmp_ctx, &tmp_vb, FR_TYPE_OCTETS, NULL, vb) < 0) {
+                               slen = -1;
+                               goto error;
+                       }
+
+                       slen = fr_dbuff_in_memcpy(&our_dbuff, tmp_vb.vb_octets, tmp_vb.vb_length);
+                       fr_value_box_clear_value(&tmp_vb);
+                       break;
+               }
+
+               if (slen < 0) {
+               error:
+                       talloc_free(tmp_ctx);
+                       return slen;
+               }
+
+               if (sep && fr_dlist_next(list, vb)) {
+                       slen = fr_dbuff_in_memcpy(&our_dbuff, sep, sep_len);
+                       if (slen < 0) goto error;
+               }
+       }
+
+       /*
+        *      Free the boxes last so if there's
+        *      an issue concating them, everything
+        *      is still in a known state.
+        */
+       fr_dlist_foreach_safe(list, fr_value_box_t, vb) {
+               if (tainted && vb->tainted) *tainted = true;
+
+               if (vb_should_remove(proc_action)) fr_dlist_remove(list, vb);
+               if (vb_should_free_value(proc_action)) fr_value_box_clear(vb);
+               if (vb_should_free(proc_action)) talloc_free(vb);
+       }}
+
+       return fr_dbuff_set(dbuff, &our_dbuff);
+}
+
 /** Concatenate a list of value boxes
  *
  * @note Will automatically cast all #fr_value_box_t to type specified.
@@ -5160,18 +5333,31 @@ ssize_t fr_value_box_print_quoted(fr_sbuff_t *out, fr_value_box_t const *data, f
  * @param[in] list             to concatenate together.
  * @param[in] type             May be #FR_TYPE_STRING or #FR_TYPE_OCTETS, no other types are
  *                             supported.
- * @param[in] free_input       If true, free the input boxes.
+ * @param[in] proc_action      What to do with the boxes in the list once
+ *                             they've been processed.
+ * @param[in] flatten          If true and we encounter a #FR_TYPE_GROUP,
+ *                             we concat the contents of its children together.
+ *                             If false, the contents will be cast to #type.
+ * @param[in] max_size         of the value.
  * @return
  *     - 0 on success.
  *     - -1 on failure.
  */
-int fr_value_box_list_concat(TALLOC_CTX *ctx,
-                            fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, bool free_input)
+int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx,
+                                     fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type,
+                                     fr_value_box_list_action_t proc_action, bool flatten,
+                                     size_t max_size)
 {
-       TALLOC_CTX              *pool;
-       fr_dcursor_t            cursor;
-       fr_value_box_t const    *vb;
-       fr_value_box_t          *head_vb;
+       fr_dbuff_t              dbuff;          /* FR_TYPE_OCTETS */
+       fr_dbuff_uctx_talloc_t  dbuff_tctx;
+
+       fr_sbuff_t              sbuff;          /* FR_TYPE_STRING */
+       fr_sbuff_uctx_talloc_t  sbuff_tctx;
+
+       fr_value_box_t          *head_vb = fr_dlist_head(list);
+       bool                    tainted = false;
+
+       fr_dlist_t              entry;
 
        if (!list || fr_dlist_empty(list)) {
                fr_strerror_const("Invalid arguments.  List was NULL");
@@ -5180,7 +5366,11 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
 
        switch (type) {
        case FR_TYPE_STRING:
+               if (unlikely(!fr_sbuff_init_talloc(ctx, &sbuff, &sbuff_tctx, 256, max_size))) return -1;
+               break;
+
        case FR_TYPE_OCTETS:
+               if (unlikely(!fr_dbuff_init_talloc(ctx, &dbuff, &dbuff_tctx, 256, max_size))) return -1;
                break;
 
        default:
@@ -5189,89 +5379,116 @@ int fr_value_box_list_concat(TALLOC_CTX *ctx,
                return -1;
        }
 
-       head_vb = fr_dlist_head(list);
-       fr_dcursor_init(&cursor, list);
-
        /*
-        *      Allow concatenating in place
+        *      Merge all siblings into list head.
+        *
+        *      This is where the first element in the
+        *      list is the output box.
+        *
+        *      i.e. we want to merge all its siblings
+        *      into it.
         */
-       if (out == head_vb) {
-               if (head_vb->type != type) {
-                       fr_value_box_t from_cast;
-                       fr_dlist_t entry = {
-                               .next = out->entry.next,
-                               .prev = out->entry.prev
-                       };
+       if (!out || (out == head_vb)) {
+               out = head_vb;  /* sync up out and head_vb */
 
+               switch (type) {
+               case FR_TYPE_STRING:
                        /*
-                        *      Two phase, as the casting code doesn't
-                        *      allow 'cast-in-place'.
+                        *      Head gets dealt with specially as we don't
+                        *      want to free it, and we don't want to free
+                        *      the buffer associated with it (just yet).
                         */
-                       if (fr_value_box_cast(ctx, &from_cast, type, NULL, out) < 0) return -1;
-                       if (fr_value_box_copy(ctx, out, &from_cast) < 0) return -1;
+                       if (fr_value_box_list_concat_as_string(&tainted, &sbuff, list,
+                                                              NULL, 0, NULL,
+                                                              FR_VALUE_BOX_LIST_REMOVE, flatten) < 0) {
+                               fr_strerror_printf("Concatenation exceeded max_size (%zu)", max_size);
+                       error:
+                               switch (type) {
+                               case FR_TYPE_STRING:
+                                       talloc_free(fr_sbuff_buff(&sbuff));
+                                       break;
 
-                       out->entry.next = entry.next;           /* Restore the list pointers */
-                       out->entry.prev = entry.prev;
+                               case FR_TYPE_OCTETS:
+                                       talloc_free(fr_dbuff_buff(&dbuff));
+                                       break;
 
-               }
-               fr_dcursor_next(&cursor);
-       } else {
-               if (fr_value_box_cast(ctx, out, type, NULL, head_vb) < 0) return -1;    /* Decomposes to copy */
+                               default:
+                                       break;
+                               }
+                               return -1;
+                       }
 
-               if (free_input) {
-                       fr_dcursor_free_item(&cursor);          /* Advances cursor */
-               } else {
-                       fr_dcursor_next(&cursor);
-               }
-       }
+                       /*
+                        *      Concat the rest of the children...
+                        */
+                       if (fr_value_box_list_concat_as_string(&tainted, &sbuff, list,
+                                                              NULL, 0, NULL,
+                                                              proc_action, flatten) < 0) {
+                               fr_dlist_insert_head(list, head_vb);
+                               goto error;
+                       }
+                       (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
+                       if (vb_should_free_value(proc_action)) fr_value_box_clear_value(out);
+                       fr_value_box_bstrndup_shallow(out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), tainted);
+                       break;
 
-       /*
-        *      Imploding a one element list.
-        */
-       if (!fr_dcursor_current(&cursor)) return 0;
+               case FR_TYPE_OCTETS:
+                       if (fr_value_box_list_concat_as_octets(&tainted, &dbuff, list,
+                                                              NULL, 0,
+                                                              FR_VALUE_BOX_LIST_REMOVE, flatten) < 0) goto error;
 
-       pool = talloc_pool(NULL, 255);  /* To absorb the temporary strings */
+                       if (fr_value_box_list_concat_as_octets(&tainted, &dbuff, list,
+                                                              NULL, 0,
+                                                              proc_action, flatten) < 0) {
+                               fr_dlist_insert_head(list, head_vb);
+                               goto error;
+                       }
+                       (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
+                       if (vb_should_free_value(proc_action)) fr_value_box_clear_value(out);
+                       fr_value_box_memdup_shallow(out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), tainted);
+                       break;
 
+               default:
+                       break;
+               }
+               fr_dlist_insert_head(list, out);
        /*
-        *      Join the remaining values
+        *      Merge all the boxes in the list into
+        *      a single contiguous buffer.
+        *
+        *      This deals with an unrelated out and list
+        *      and also where list is the children of
+        *      out.
         */
-       while ((vb = fr_dcursor_current(&cursor))) {
-               fr_value_box_t from_cast;
-               fr_value_box_t const *n;
-
-               if (vb->type != type) {
-                       talloc_free_children(pool);             /* Clear out previous buffers */
-                       memset(&from_cast, 0, sizeof(from_cast));
-
-                       if (fr_value_box_cast(pool, &from_cast, type, NULL, vb) < 0) {
-                       error:
-                               talloc_free(pool);
-                               return -1;
-                       }
+       } else {
+               switch (type) {
+               case FR_TYPE_STRING:
+                       if (fr_value_box_list_concat_as_string(&tainted, &sbuff, list,
+                                                              NULL, 0, NULL,
+                                                              proc_action, flatten) < 0) goto error;
+                       (void)fr_sbuff_trim_talloc(&sbuff, SIZE_MAX);
+
+                       entry = out->entry;
+                       fr_value_box_bstrndup_shallow(out, NULL, fr_sbuff_buff(&sbuff), fr_sbuff_used(&sbuff), tainted);
+                       out->entry = entry;
+                       break;
 
-                       n = &from_cast;
-               } else {
-                       n = vb;
-               }
+               case FR_TYPE_OCTETS:
+                       if (fr_value_box_list_concat_as_octets(&tainted, &dbuff, list,
+                                                              NULL, 0,
+                                                              proc_action, flatten) < 0) goto error;
+                       (void)fr_dbuff_trim_talloc(&dbuff, SIZE_MAX);
 
-               /*
-                *      Append the next value
-                */
-               if (type == FR_TYPE_STRING) {
-                       if (fr_value_box_bstrn_append(ctx, out, n->vb_strvalue, n->vb_length, n->tainted) < 0) goto error;
-               } else {
-                       if (fr_value_box_mem_append(ctx, out, n->vb_octets, n->vb_length, n->tainted) < 0) goto error;
-               }
+                       entry = out->entry;
+                       fr_value_box_memdup_shallow(out, NULL, fr_dbuff_buff(&dbuff), fr_dbuff_used(&dbuff), tainted);
+                       out->entry = entry;
+                       break;
 
-               if (free_input) {
-                       fr_dcursor_free_item(&cursor);          /* Advances cursor */
-               } else {
-                       fr_dcursor_next(&cursor);
+               default:
+                       break;
                }
        }
 
-       talloc_free(pool);
-
        return 0;
 }
 
index c1b4b63d1d219017f98c7ba97a66aa2921cef2b2..6aa7e5d23a226882a777a7374fa1c74a3e9299ad 100644 (file)
@@ -158,6 +158,22 @@ struct value_box_s {
        fr_dlist_t                      entry;                  //!< Doubly linked list entry.
 };
 
+/** Actions to perform when we process a box in a list
+ *
+ */
+typedef enum {
+       FR_VALUE_BOX_LIST_NONE                  = 0x00,                 //!< Do nothing to processed boxes.
+       FR_VALUE_BOX_LIST_REMOVE                = 0x01,                 //!< Remove the box from the input list.
+       FR_VALUE_BOX_LIST_FREE_BOX              = (0x02 | FR_VALUE_BOX_LIST_REMOVE), //!< Free each processed box.
+       FR_VALUE_BOX_LIST_FREE_BOX_VALUE        = 0x04,                 //!< Explicitly free any value buffers associated
+                                                                       ///< with a box.
+       FR_VALUE_BOX_LIST_FREE                  = (FR_VALUE_BOX_LIST_FREE_BOX | FR_VALUE_BOX_LIST_FREE_BOX_VALUE)
+} fr_value_box_list_action_t;
+
+#define vb_should_free(_action)                ((_action & FR_VALUE_BOX_LIST_FREE_BOX) == FR_VALUE_BOX_LIST_FREE_BOX)
+#define vb_should_free_value(_action)  ((_action & FR_VALUE_BOX_LIST_FREE_BOX_VALUE) == FR_VALUE_BOX_LIST_FREE_BOX_VALUE)
+#define vb_should_remove(_action)      ((_action & FR_VALUE_BOX_LIST_REMOVE) == FR_VALUE_BOX_LIST_REMOVE)
+
 /** @name Field accessors for #fr_value_box_t
  *
  * Use these instead of accessing fields directly to make refactoring
@@ -782,9 +798,18 @@ int                fr_value_box_from_str(TALLOC_CTX *ctx, fr_value_box_t *dst,
  *
  * @{
  */
-int            fr_value_box_list_concat(TALLOC_CTX *ctx,
-                                        fr_value_box_t *out, fr_value_box_list_t *list,
-                                        fr_type_t type, bool free_input);
+ssize_t                fr_value_box_list_concat_as_string(bool *tainted, fr_sbuff_t *sbuff, fr_value_box_list_t *list,
+                                                  char const *sep, size_t sep_len, fr_sbuff_escape_rules_t const *e_rules,
+                                                  fr_value_box_list_action_t proc_action, bool flatten);
+
+ssize_t                fr_value_box_list_concat_as_octets(bool *tainted, fr_dbuff_t *dbuff, fr_value_box_list_t *list,
+                                                  uint8_t const *sep, size_t sep_len,
+                                                  fr_value_box_list_action_t proc_action, bool flatten);
+
+int            fr_value_box_list_concat_in_place(TALLOC_CTX *ctx,
+                                                 fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type,
+                                                 fr_value_box_list_action_t proc_action, bool flatten,
+                                                 size_t max_size);
 
 char           *fr_value_box_list_aprint(TALLOC_CTX *ctx, fr_value_box_list_t const *list, char const *delim,
                                         fr_sbuff_escape_rules_t const *e_rules);
index 1655176af16c9852a4f3f673932d0a6e9dca1896..38932f56dd06901fc6df7bc1f35cfef76ed86784 100644 (file)
@@ -826,7 +826,10 @@ static xlat_action_t cipher_rsa_verify_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out,
         *      Concat (...) args to get message data
         */
        args = fr_dlist_head(in);
-       if (fr_value_box_list_concat(ctx, args, in, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat_in_place(ctx,
+                                             args, in, FR_TYPE_STRING,
+                                             FR_VALUE_BOX_LIST_FREE, true,
+                                             SIZE_MAX) < 0) {
                REDEBUG("Failed concatenating arguments to form plaintext");
                return XLAT_ACTION_FAIL;
        }
index 29bd433afaa91cf48dbb5247d8a00883d06d6b64..017b7fea0e323125fcf79c46c22cb4800be1d3c6 100644 (file)
@@ -131,7 +131,10 @@ static rlm_rcode_t map_proc_client(UNUSED void *mod_inst, UNUSED void *proc_inst
                 *      Concat don't asprint, as this becomes a noop
                 *      in the vast majority of cases.
                 */
-               if (fr_value_box_list_concat(request, client_override_head, client_override, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(request,
+                                                     client_override_head, client_override, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        REDEBUG("Failed concatenating input data");
                        return RLM_MODULE_FAIL;
                }
index f62b9f56279747426d61dc038e7a4e599f367bcb..84a95a359b69920ade33060bd840fa4dfa653bf4 100644 (file)
@@ -984,7 +984,10 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
        }
 
        if ((inst->key_data_type == FR_TYPE_OCTETS) || (inst->key_data_type == FR_TYPE_STRING)) {
-               if (fr_value_box_list_concat(request, key_head, key, inst->key_data_type, true) < 0) {
+               if (fr_value_box_list_concat_in_place(request,
+                                                     key_head, key, inst->key_data_type,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        REDEBUG("Failed parsing key");
                        return RLM_MODULE_FAIL;
                }
index 61337df8092bfbcc4d768d120863d74e9f55b9ac..6254e6fbbe0ed7e76e6336452bf746472e413ed3 100644 (file)
@@ -469,7 +469,10 @@ static rlm_rcode_t mod_map_proc(UNUSED void *mod_inst, void *proc_inst, request_
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, json_head, json, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat_in_place(request,
+                                             json_head, json, FR_TYPE_STRING,
+                                             FR_VALUE_BOX_LIST_FREE, true,
+                                             SIZE_MAX) < 0) {
                REDEBUG("Failed concatenating input");
                return RLM_MODULE_FAIL;
        }
index f5049237efd2694b39b5be91e85dc1c3b9573fe1..85e7baf6217973f84220724742545331d2b1a090 100644 (file)
@@ -508,7 +508,10 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, url_head, url, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat_in_place(request,
+                                             url_head, url, FR_TYPE_STRING,
+                                             FR_VALUE_BOX_LIST_FREE, true,
+                                             SIZE_MAX) < 0) {
                REDEBUG("Failed concatenating input");
                return RLM_MODULE_FAIL;
        }
index a3a7574e2f70f82e73e589981d7fdd8139dd17de..1c0239e6ad995a1cf9348aeab1afa4e2aa32ea39 100644 (file)
@@ -397,7 +397,10 @@ static xlat_action_t rest_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
         */
        if  ((fr_dlist_head(in))) {
                uri_vb = fr_dlist_head(&in_vb->vb_group);
-               if (fr_value_box_list_concat(uri_vb, uri_vb, &in_vb->vb_group, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(uri_vb,
+                                                     uri_vb, &in_vb->vb_group, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        REDEBUG("Failed concatenating argument");
                        return XLAT_ACTION_FAIL;
                }
@@ -450,7 +453,10 @@ static xlat_action_t rest_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
        }
 
        uri_vb = fr_dlist_head(&in_vb->vb_group);
-       if (fr_value_box_list_concat(uri_vb, uri_vb, &in_vb->vb_group, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat_in_place(uri_vb,
+                                             uri_vb, &in_vb->vb_group, FR_TYPE_STRING,
+                                             FR_VALUE_BOX_LIST_FREE, true,
+                                             SIZE_MAX) < 0) {
                REDEBUG("Concatenating URI");
                goto error;
        }
@@ -459,7 +465,10 @@ static xlat_action_t rest_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out,
         *      Any additional arguments are freeform data
         */
        if ((in_vb = fr_dlist_head(in))) {
-               if (fr_value_box_list_concat(in_vb, in_vb, in, FR_TYPE_STRING, true) < 0) {
+               if (fr_value_box_list_concat_in_place(in_vb,
+                                                     in_vb, in, FR_TYPE_STRING,
+                                                     FR_VALUE_BOX_LIST_FREE, true,
+                                                     SIZE_MAX) < 0) {
                        REDEBUG("Failed to concatenate freeform data");
                        goto error;
                }
index 63b88ab3577346272e2d4d8722d260267260167f..c336ec5f5bed836db664fd1f10f81edcaef0dec9 100644 (file)
@@ -364,7 +364,10 @@ static rlm_rcode_t mod_map_proc(void *mod_inst, UNUSED void *proc_inst, request_
                return RLM_MODULE_FAIL;
        }
 
-       if (fr_value_box_list_concat(request, query_head, query, FR_TYPE_STRING, true) < 0) {
+       if (fr_value_box_list_concat_in_place(request,
+                                             query_head, query, FR_TYPE_STRING,
+                                             FR_VALUE_BOX_LIST_FREE, true,
+                                             SIZE_MAX) < 0) {
                RPEDEBUG("Failed concatenating input string");
                return RLM_MODULE_FAIL;
        }