]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
xlat: Integrate list allocation into node init
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 13 Feb 2023 03:35:34 +0000 (21:35 -0600)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sun, 19 Feb 2023 22:53:40 +0000 (16:53 -0600)
src/lib/unlang/xlat_expr.c
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_purify.c
src/lib/unlang/xlat_tokenize.c

index aa57a30119a6eb2af975369cb86cd8d3a383741e..c5b97fa8efd5524a9c3fadc80f3ec0ff784eebd7 100644 (file)
@@ -86,14 +86,12 @@ static void xlat_func_append_arg(xlat_exp_t *head, xlat_exp_t *node, bool exists
                node = xlat_exists_alloc(head, node);
        }
 
-       group = xlat_exp_alloc_null(head->call.args);
-       xlat_exp_set_type(group, XLAT_GROUP);
+       group = xlat_exp_alloc(head->call.args, XLAT_GROUP, NULL, 0);
        group->quote = T_BARE_WORD;
 
        group->fmt = node->fmt; /* not entirely correct, but good enough for now */
        group->flags = node->flags;
 
-       MEM(group->group = xlat_exp_head_alloc(group));
        talloc_steal(group->group, node);
        xlat_exp_insert_tail(group->group, node);
 
@@ -117,7 +115,6 @@ static xlat_exp_t *xlat_exists_alloc(TALLOC_CTX *ctx, xlat_exp_t *child)
         *      Create an "exists" node.
         */
        MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, "exists", 6));
-       MEM(node->call.args = xlat_exp_head_alloc(node));
        MEM(node->call.func = xlat_func_find("exists", 6));
        fr_assert(node->call.func != NULL);
        node->flags = node->call.func->flags;
@@ -191,7 +188,6 @@ static int reparse_rcode(TALLOC_CTX *ctx, xlat_exp_t **p_arg, bool allow)
        }
 
        MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, arg->vpt->name, len));
-       MEM(node->call.args = xlat_exp_head_alloc(node));
        node->call.func = func;
        node->flags = func->flags;
 
@@ -1945,7 +1941,6 @@ static fr_slen_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
        *out_c = c;
 
        MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, func->name, strlen(func->name)));
-       MEM(unary->call.args = xlat_exp_head_alloc(unary));
        unary->fmt = fr_tokens[func->token];
        unary->call.func = func;
        unary->flags = func->flags;
@@ -1999,7 +1994,6 @@ static xlat_exp_t *expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type)
         *      whatever "node" comes next.
         */
        MEM(cast = xlat_exp_alloc(ctx, XLAT_FUNC, "cast", 4));
-       MEM(cast->call.args = xlat_exp_head_alloc(cast));
        MEM(cast->call.func = xlat_func_find("cast", 4));
        fr_assert(cast->call.func != NULL);
        cast->flags = cast->call.func->flags;
@@ -2010,8 +2004,7 @@ static xlat_exp_t *expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type)
         *      to print the name of the type, and not the
         *      number.
         */
-       MEM(node = xlat_exp_alloc_null(cast));
-       xlat_exp_set_type(node, XLAT_BOX);
+       MEM(node = xlat_exp_alloc(cast, XLAT_BOX, NULL, 0));
        node->flags.constant = true;
        xlat_exp_set_name_buffer_shallow(node,
                                         talloc_strdup(node,
@@ -2105,8 +2098,7 @@ static fr_slen_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_
        /*
         *      Allocate the xlat node now so the talloc hierarchy is correct
         */
-       MEM(node = xlat_exp_alloc_null(head));
-       xlat_exp_set_type(node, XLAT_TMPL);
+       MEM(node = xlat_exp_alloc(head, XLAT_TMPL, NULL, 0));
 
        /*
         *      tmpl_afrom_substr does pretty much all the work of parsing the operand.  Note that we pass '/'
@@ -2265,8 +2257,7 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf
        /*
         *      Allocate the xlat node now so the talloc hierarchy is correct
         */
-       MEM(node = xlat_exp_alloc_null(head));
-       xlat_exp_set_type(node, XLAT_TMPL);
+       MEM(node = xlat_exp_alloc(head, XLAT_TMPL, NULL, 0));
 
        /*
         *      tmpl_afrom_substr does pretty much all the work of
@@ -2493,7 +2484,6 @@ static fr_slen_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr
        ssize_t         slen;
        fr_sbuff_marker_t  m_lhs, m_op, m_rhs;
        fr_sbuff_t      our_in = FR_SBUFF(in);
-       xlat_exp_head_t *args;
        char c = '\0';
 
        XLAT_DEBUG("EXPRESSION <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
@@ -2704,7 +2694,6 @@ redo:
         *      Create the function node, with the LHS / RHS arguments.
         */
        MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_tokens[op], strlen(fr_tokens[op])));
-       MEM(node->call.args = args = xlat_exp_head_alloc(node));
        node->fmt = fr_tokens[op];
        node->call.func = func;
        node->flags = func->flags;
index 24a8e3415268bd8020fc81f30fa5f47665ccc04a..d65947c0b0d9c9b044a43f1c2cc6dc30f081eb17 100644 (file)
@@ -33,6 +33,7 @@ extern "C" {
 #include <freeradius-devel/unlang/xlat_ctx.h>
 #include <freeradius-devel/unlang/xlat.h>
 #include <freeradius-devel/io/pair.h>
+#include <freeradius-devel/util/talloc.h>
 
 #ifdef DEBUG_XLAT
 #  define XLAT_DEBUG RDEBUG3
@@ -175,6 +176,21 @@ typedef struct {
  *     Helper functions
  */
 
+static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head)
+{
+       if (!head) return NULL;
+
+       return fr_dlist_head(&head->dlist);
+}
+
+/** Iterate over the contents of a list, only one level
+ *
+ * @param[in] _list_head       to iterate over.
+ * @param[in] _iter            Name of iteration variable.
+ *                             Will be declared in the scope of the loop.
+ */
+#define xlat_exp_foreach(_list_head, _iter) fr_dlist_foreach(&((_list_head)->dlist), xlat_exp_t, _iter)
+
 /** Merge flags from child to parent
  *
  * For pass2, if either the parent or child is marked up for pass2, then the parent
@@ -188,32 +204,87 @@ static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_
        parent->constant &= child->constant;
 }
 
+static inline CC_HINT(nonnull) int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
+{
+       xlat_flags_merge(&head->flags, &node->flags);
+       return fr_dlist_insert_tail(&head->dlist, node);
+}
+
+static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
+{
+       if (!head) return NULL;
+
+       return fr_dlist_next(&head->dlist, node);
+}
+
+static inline xlat_exp_head_t *xlat_exp_head_alloc(TALLOC_CTX *ctx)
+{
+       xlat_exp_head_t *head;
+
+       MEM(head = talloc_zero(ctx, xlat_exp_head_t));
+
+       fr_dlist_init(&head->dlist, xlat_exp_t, entry);
+       head->flags.pure = true;
+
+       return head;
+}
+
 /** Set the type of an xlat node
+ *
+ * Also initialises any xlat_exp_head necessary
  *
  * @param[in] node     to set type for.
  * @param[in] type     to set.
  */
 static inline void xlat_exp_set_type(xlat_exp_t *node, xlat_type_t type)
 {
+       xlat_type_t existing_type = node->type;
+
        node->type = type;
+
+       if (existing_type != 0) return;
+
+       switch (type) {
+       case XLAT_ALTERNATE:
+               node->alternate[0] = xlat_exp_head_alloc(node);
+               node->alternate[1] = xlat_exp_head_alloc(node);
+               break;
+
+       case XLAT_GROUP:
+               node->group = xlat_exp_head_alloc(node);
+               break;
+
+       case XLAT_FUNC:
+       case XLAT_FUNC_UNRESOLVED:
+               node->call.args = xlat_exp_head_alloc(node);
+               break;
+
+       default:
+               break;
+       }
 }
 
-/** Allocate an xlat node with no name, and no type set
- *
- * @param[in] ctx      to allocate node in.
- * @return A new xlat node.
- */
-static inline xlat_exp_t *xlat_exp_alloc_null(TALLOC_CTX *ctx)
+static inline xlat_exp_t *xlat_exp_alloc_pool(TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra)
 {
        xlat_exp_t *node;
 
-       MEM(node = talloc_zero(ctx, xlat_exp_t));
+       MEM(node = talloc_zero_pooled_object(ctx, xlat_exp_t, extra_hdrs, extra));
        node->flags.pure = true;        /* everything starts pure */
        node->quote = T_BARE_WORD;
 
        return node;
 }
 
+/** Allocate an xlat node with no name, and no type set
+ *
+ * @param[in] ctx      to allocate node in.
+ * @return A new xlat node.
+ */
+static inline xlat_exp_t *xlat_exp_alloc_null(TALLOC_CTX *ctx)
+{
+       return xlat_exp_alloc_pool(ctx, 0, 0);
+}
+
 /** Allocate an xlat node
  *
  * @param[in] ctx      to allocate node in.
@@ -226,9 +297,38 @@ static inline xlat_exp_t *xlat_exp_alloc(TALLOC_CTX *ctx, xlat_type_t type,
                                         char const *in, size_t inlen)
 {
        xlat_exp_t *node;
+       unsigned int extra_hdrs;
+       size_t extra;
 
-       node = xlat_exp_alloc_null(ctx);
-       node->type = type;
+       /*
+        *      Figure out how much extra memory we
+        *      need to allocate for this node type.
+        */
+       switch (type) {
+       case XLAT_ALTERNATE:
+               extra_hdrs = 2;
+               extra = sizeof(xlat_exp_head_t) * 2;
+               break;
+
+       case XLAT_GROUP:
+               extra_hdrs = 1;
+               extra = sizeof(xlat_exp_head_t);
+               break;
+
+       case XLAT_FUNC:
+               extra_hdrs = 1;
+               extra = sizeof(xlat_exp_head_t);
+               break;
+       
+       default:
+               extra_hdrs = 0;
+               extra = 0;
+       }
+
+       node = xlat_exp_alloc_pool(ctx,
+                                  (in != NULL) + extra_hdrs,
+                                  inlen + extra);
+       xlat_exp_set_type(node, type);
 
        if (!in) return node;
 
@@ -374,47 +474,6 @@ ssize_t            xlat_print_node(fr_sbuff_t *out, xlat_exp_head_t const *head, xlat_exp_
  */
 int            xlat_inst_remove(xlat_exp_t *node);
 
-static inline xlat_exp_t *xlat_exp_head(xlat_exp_head_t const *head)
-{
-       if (!head) return NULL;
-
-       return fr_dlist_head(&head->dlist);
-}
-
-/** Iterate over the contents of a list, only one level
- *
- * @param[in] _list_head       to iterate over.
- * @param[in] _iter            Name of iteration variable.
- *                             Will be declared in the scope of the loop.
- */
-#define xlat_exp_foreach(_list_head, _iter) fr_dlist_foreach(&((_list_head)->dlist), xlat_exp_t, _iter)
-
-static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t const *node)
-{
-       if (!head) return NULL;
-
-       return fr_dlist_next(&head->dlist, node);
-}
-
-static inline int xlat_exp_insert_tail(xlat_exp_head_t *head, xlat_exp_t *node)
-{
-       xlat_flags_merge(&head->flags, &node->flags);
-       return fr_dlist_insert_tail(&head->dlist, node);
-}
-
-static inline xlat_exp_head_t *xlat_exp_head_alloc(TALLOC_CTX *ctx)
-{
-       xlat_exp_head_t *head;
-
-       head = talloc_zero(ctx, xlat_exp_head_t);
-       if (!head) return NULL;
-
-       fr_dlist_init(&head->dlist, xlat_exp_t, entry);
-       head->flags.pure = true;
-
-       return head;
-}
-
 #ifdef __cplusplus
 }
 #endif
index 7338b9bda3175cafccd8d8a4d5cd87cf95e17d0f..42714a7431a791a37eedfddabd7224da2e7068cc 100644 (file)
@@ -36,9 +36,7 @@ static void xlat_value_list_to_xlat(xlat_exp_head_t *head, FR_DLIST_HEAD(fr_valu
        xlat_exp_t *node;
 
        while ((box = fr_value_box_list_pop_head(list)) != NULL) {
-               MEM(node = xlat_exp_alloc_null(head));
-               node->type = XLAT_BOX;
-
+               MEM(node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0));
                fr_value_box_copy(node, &node->data, box);
                talloc_free(box);
 
@@ -305,8 +303,7 @@ static int binary_peephole_optimize(TALLOC_CTX *ctx, xlat_exp_t **out, xlat_exp_
 
        if (fr_value_calc_binary_op(lhs, &box, FR_TYPE_NULL, lhs_box, op, rhs_box) < 0) return -1;
 
-       MEM(node = xlat_exp_alloc_null(ctx));
-       xlat_exp_set_type(node, XLAT_BOX);
+       MEM(node = xlat_exp_alloc(ctx, XLAT_BOX, NULL, 0));
 
        if (box.type == FR_TYPE_BOOL) box.enumv = attr_expr_bool_enum;
 
index 40b968dd4547bedbc3c6f1d106484b80e0e04757..9f852e0dd0e432fb1ddb55f50d4898e365a62367 100644 (file)
@@ -159,11 +159,7 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i
 
        XLAT_DEBUG("ALTERNATE <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
 
-       node = xlat_exp_alloc_null(head);
-       xlat_exp_set_type(node, XLAT_ALTERNATE);
-       MEM(node->alternate[0] = xlat_exp_head_alloc(node));
-       MEM(node->alternate[1] = xlat_exp_head_alloc(node));
-
+       node = xlat_exp_alloc(head, XLAT_ALTERNATE, NULL, 0);
        if (func_args) {
                if (xlat_tokenize_function_args(node->alternate[0], in, t_rules) < 0) {
                error:
@@ -189,7 +185,7 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i
         *      Parse the alternate expansion.
         */
        if (xlat_tokenize_string(node->alternate[1], in,
-                                 true, &xlat_expansion_rules, t_rules) < 0) goto error;
+                                true, &xlat_expansion_rules, t_rules) < 0) goto error;
 
        if (!xlat_exp_head(node->alternate[1])) {
                talloc_free(node);
@@ -288,7 +284,7 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head,
                                              fr_sbuff_t *in,
                                              tmpl_rules_t const *t_rules)
 {
-       xlat_exp_t              *node;
+       xlat_exp_t              *node, *arg_group;
        xlat_t                  *func;
        fr_sbuff_marker_t       m_s;
 
@@ -322,8 +318,7 @@ static inline int xlat_tokenize_function_mono(xlat_exp_head_t *head,
        /*
         *      Allocate a node to hold the function
         */
-       MEM(node = xlat_exp_alloc(head, XLAT_FUNC, fr_sbuff_current(&m_s), fr_sbuff_behind(&m_s)));
-       MEM(node->call.args = xlat_exp_head_alloc(node));
+       node = xlat_exp_alloc(head, XLAT_FUNC, fr_sbuff_current(&m_s), fr_sbuff_behind(&m_s));
        if (!func) {
                if (!t_rules || !t_rules->attr.allow_unresolved) {
                        fr_strerror_const("Unresolved expansion functions are not allowed here");
@@ -533,7 +528,7 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
                xlat_exp_set_type(node, XLAT_FUNC_UNRESOLVED);
                node->flags.needs_resolving = true;     /* Needs resolution during pass2 */
        } else {
-               if (func && (func->input_type != XLAT_INPUT_ARGS)) {
+               if (func->input_type != XLAT_INPUT_ARGS) {
                        fr_strerror_const("Function should be called using %{func:arg} syntax");
                error:
                        talloc_free(node);
@@ -940,7 +935,7 @@ static int xlat_tokenize_string(xlat_exp_head_t *head,
                /*
                 *      pre-allocate the node so we don't have to steal it later.
                 */
-               node = xlat_exp_alloc_null(head);
+               node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0);
 
                /*
                 *      Find the next token
@@ -951,7 +946,6 @@ static int xlat_tokenize_string(xlat_exp_head_t *head,
                 *      It's a value box, create an appropriate node
                 */
                if (slen > 0) {
-                       xlat_exp_set_type(node, XLAT_BOX);
                        xlat_exp_set_name_buffer_shallow(node, str);
                        fr_value_box_strdup_shallow(&node->data, NULL, str, false);
                        node->flags.constant = true;
@@ -1526,9 +1520,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                 *      Alloc a new node to hold the child nodes
                 *      that make up the argument.
                 */
-               MEM(node = xlat_exp_alloc_null(head));
-               xlat_exp_set_type(node, XLAT_GROUP);
-               MEM(node->group = xlat_exp_head_alloc(node));
+               MEM(node = xlat_exp_alloc(head, XLAT_GROUP, 0, NULL));
                node->quote = quote;
 
                switch (quote) {
@@ -1564,8 +1556,7 @@ fr_slen_t xlat_tokenize_argv(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuff_t
                        char            *str;
                        xlat_exp_t      *child;
 
-                       child = xlat_exp_alloc_null(node->group);
-                       xlat_exp_set_type(child, XLAT_BOX);
+                       child = xlat_exp_alloc(node->group, XLAT_BOX, NULL, 0);
                        node->flags.constant = true;
 
                        slen = fr_sbuff_out_aunescape_until(child, &str, &our_in, SIZE_MAX,