From: Arran Cudbard-Bell Date: Sun, 19 Feb 2023 18:18:53 +0000 (-0600) Subject: xlat: Automatically alloc list heads X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c7fc3d59decacec743fa6ecbdfd9a1f40278b7b0;p=thirdparty%2Ffreeradius-server.git xlat: Automatically alloc list heads --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 24860df438a..ac77ce42768 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -3198,7 +3198,7 @@ tmpl_t *tmpl_copy(TALLOC_CTX *ctx, tmpl_t const *in) /* * Copy the xlat component */ - if (tmpl_contains_xlat(vpt) && unlikely(xlat_copy(vpt, &vpt->data.xlat.ex, in->data.xlat.ex) < 0)) goto error; + if (tmpl_contains_xlat(vpt) && unlikely(xlat_copy(vpt, vpt->data.xlat.ex, in->data.xlat.ex) < 0)) goto error; return vpt; } diff --git a/src/lib/unlang/all.mk b/src/lib/unlang/all.mk index 148748918ef..007a6f2497d 100644 --- a/src/lib/unlang/all.mk +++ b/src/lib/unlang/all.mk @@ -26,12 +26,13 @@ SOURCES := base.c \ tmpl.c \ variable.c \ xlat.c \ + xlat_alloc.c \ xlat_builtin.c \ xlat_eval.c \ xlat_expr.c \ xlat_inst.c \ - xlat_tokenize.c \ xlat_pair.c \ + xlat_tokenize.c \ xlat_purify.c HEADERS := $(subst src/lib/,,$(wildcard src/lib/unlang/*.h)) diff --git a/src/lib/unlang/xlat.h b/src/lib/unlang/xlat.h index ee07321cb34..c077d7daa83 100644 --- a/src/lib/unlang/xlat.h +++ b/src/lib/unlang/xlat.h @@ -480,7 +480,7 @@ tmpl_t *xlat_to_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t *xlat); int xlat_from_tmpl_attr(TALLOC_CTX *ctx, xlat_exp_head_t **head, tmpl_t **vpt_p); -int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in); +int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in); /* * xlat_inst.c diff --git a/src/lib/unlang/xlat_alloc.c b/src/lib/unlang/xlat_alloc.c new file mode 100644 index 00000000000..4a7dc53cb46 --- /dev/null +++ b/src/lib/unlang/xlat_alloc.c @@ -0,0 +1,209 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * $Id$ + * + * @file xlat_alloc.c + * @brief Functions to allocate different types of xlat nodes + */ + +RCSID("$Id$") + +#include +#include + +#include +#include + +#define _XLAT_PRIVATE +#include + +xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS 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; +#ifndef NDEBUG + head->file = file; + head->line = line; +#endif + + 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. + */ +void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type) +{ + /* + * Do nothing if it's the same type + */ + if (node->type == type) return; + + /* + * Free existing lists if present + */ + if (node->type != 0) switch (node->type) { + case XLAT_ALTERNATE: + TALLOC_FREE(node->alternate[0]); + TALLOC_FREE(node->alternate[1]); + break; + + case XLAT_GROUP: + TALLOC_FREE(node->group); + break; + + case XLAT_FUNC: + case XLAT_FUNC_UNRESOLVED: + if (type != XLAT_FUNC) { + TALLOC_FREE(node->call.args); /* Just switching from unresolved to resolved */ + } else goto done; + break; + + default: + break; + } + + /* + * Alloc new lists to match the type + */ + switch (type) { + case XLAT_ALTERNATE: + node->alternate[0] = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node); + node->alternate[1] = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node); + break; + + case XLAT_GROUP: + node->group = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node); + break; + + case XLAT_FUNC: + case XLAT_FUNC_UNRESOLVED: + node->call.args = _xlat_exp_head_alloc(NDEBUG_LOCATION_VALS node); + break; + + default: + break; + } + +done: + node->type = type; +} + +static xlat_exp_t *xlat_exp_alloc_pool(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, unsigned int extra_hdrs, size_t extra) +{ + xlat_exp_t *node; + + 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; +#ifndef NDEBUG + node->file = file; + node->line = line; +#endif + + 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. + */ +xlat_exp_t *_xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx) +{ + return xlat_exp_alloc_pool(NDEBUG_LOCATION_VALS ctx, 0, 0); +} + +/** Allocate an xlat node + * + * @param[in] ctx to allocate node in. + * @param[in] type of the node. + * @param[in] in original input string. + * @param[in] inlen the length of the original input string. + * @return A new xlat node. + */ +xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen) +{ + xlat_exp_t *node; + unsigned int extra_hdrs; + size_t extra; + + /* + * 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(NDEBUG_LOCATION_VALS + ctx, + (in != NULL) + extra_hdrs, + inlen + extra); + _xlat_exp_set_type(NDEBUG_LOCATION_VALS node, type); + + if (!in) return node; + + node->fmt = talloc_bstrndup(node, in, inlen); + switch (type) { + case XLAT_BOX: + fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false); + break; + + default: + break; + } + + return node; +} + +/** Set the format string for an xlat node + * + * @param[in] node to set fmt for. + * @param[in] fmt talloced buffer to set as the fmt string. + */ +void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt) +{ + if (node->fmt) talloc_const_free(node->fmt); + node->fmt = talloc_get_type_abort(fmt, char); +} diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index c5b97fa8efd..5d43cdc6009 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -89,7 +89,7 @@ static void xlat_func_append_arg(xlat_exp_t *head, xlat_exp_t *node, bool exists 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 */ + xlat_exp_set_name_buffer_shallow(group, node->fmt); /* not entirely correct, but good enough for now */ group->flags = node->flags; talloc_steal(group->group, node); @@ -121,7 +121,7 @@ static xlat_exp_t *xlat_exists_alloc(TALLOC_CTX *ctx, xlat_exp_t *child) fr_assert(child->type == XLAT_TMPL); fr_assert(tmpl_contains_attr(child->vpt)); - node->fmt = child->vpt->name; + xlat_exp_set_name_buffer_shallow(node, child->vpt->name); xlat_func_append_arg(node, child, false); @@ -890,7 +890,7 @@ static int xlat_instantiate_logical(xlat_inst_ctx_t const *xctx) * result is "false" for "delete this argument" * result is "true" for "return this argument". */ -static bool xlat_node_matches_bool(xlat_exp_t *parent, xlat_exp_head_t *head, bool sense, bool *result) +static bool xlat_node_matches_bool(bool *result, xlat_exp_t *parent, xlat_exp_head_t *head, bool sense) { fr_value_box_t *box; xlat_exp_t *node; @@ -929,7 +929,7 @@ check: xlat_inst_remove(parent); - parent->type = XLAT_BOX; + xlat_exp_set_type(parent, XLAT_BOX); fr_value_box_copy(parent, &parent->data, box); parent->flags = (xlat_flags_t) { .pure = true, .constant = true, }; @@ -969,17 +969,17 @@ static void xlat_ungroup(xlat_exp_head_t *head) */ static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t *request) { - int i, j; - int deleted = 0; - bool result; - xlat_logical_inst_t *inst = talloc_get_type_abort(instance, xlat_logical_inst_t); - xlat_exp_head_t *group; + int i, j; + int deleted = 0; + bool result; + xlat_logical_inst_t *inst = talloc_get_type_abort(instance, xlat_logical_inst_t); + xlat_exp_head_t *group; fr_assert(node->type == XLAT_FUNC); /* - * Don't check the last argument. If everything else gets deleted, then we just return the last - * argument. + * Don't check the last argument. If everything else gets deleted, + * then we just return the last argument. */ for (i = 0; i < inst->argc; i++) { /* @@ -1002,9 +1002,7 @@ static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t * result is "false" for "delete this argument" * result is "true" for "return this argument". */ - if (!xlat_node_matches_bool(node, inst->argv[i], inst->stop_on_match, &result)) { - continue; - } + if (!xlat_node_matches_bool(&result, node, inst->argv[i], inst->stop_on_match)) continue; /* * 0 && EXPR --> 0. @@ -1068,11 +1066,12 @@ static int xlat_expr_logical_purify(xlat_exp_t *node, void *instance, request_t */ group = inst->argv[0]; fr_assert(group != NULL); + fr_assert(group->fmt != NULL); talloc_steal(node, group); xlat_inst_remove(node); - node->type = XLAT_GROUP; - node->fmt = group->fmt; + xlat_exp_set_type(node, XLAT_BOX); + xlat_exp_set_name_buffer_shallow(node, group->fmt); node->group = group; node->flags = group->flags; @@ -1940,8 +1939,7 @@ 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))); - unary->fmt = fr_tokens[func->token]; + MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, fr_tokens[func->token], strlen(fr_tokens[func->token]))); unary->call.func = func; unary->flags = func->flags; @@ -2007,9 +2005,8 @@ static xlat_exp_t *expr_cast_alloc(TALLOC_CTX *ctx, fr_type_t type) MEM(node = xlat_exp_alloc(cast, XLAT_BOX, NULL, 0)); node->flags.constant = true; xlat_exp_set_name_buffer_shallow(node, - talloc_strdup(node, - fr_table_str_by_value(fr_type_table, - type, ""))); + talloc_typed_strdup(node, + fr_table_str_by_value(fr_type_table, type, ""))); fr_value_box_init(&node->data, FR_TYPE_UINT8, attr_cast_base, false); node->data.vb_uint8 = type; @@ -2145,7 +2142,7 @@ static fr_slen_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_ node->vpt = vpt; node->quote = quote; - node->fmt = vpt->name; + xlat_exp_set_name_buffer_shallow(node, vpt->name); node->flags.pure = !tmpl_contains_xlat(node->vpt); node->flags.needs_resolving = tmpl_needs_resolving(node->vpt); @@ -2311,17 +2308,9 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf */ if (tmpl_is_xlat(vpt) || tmpl_is_xlat_unresolved(vpt)) { xlat_exp_head_t *xlat = tmpl_xlat(vpt); - xlat_exp_t *cast; - fr_type_t type = FR_TYPE_NULL; - - talloc_steal(node, xlat); - node->fmt = talloc_typed_strdup(node, vpt->name); - - xlat_exp_set_type(node, XLAT_GROUP); - node->quote = quote; - node->group = xlat; - - node->flags = xlat->flags; + fr_type_t type = FR_TYPE_NULL; + xlat_exp_t *arg = NULL; + xlat_exp_t *cast = NULL; /* * Enforce a cast type. @@ -2346,11 +2335,31 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf if (type != FR_TYPE_NULL) { MEM(cast = expr_cast_alloc(head, type)); - xlat_func_append_arg(cast, node, false); + head = cast->call.args; /* Arguments */ + } + + MEM(arg = xlat_exp_alloc(head, XLAT_GROUP, vpt->name, strlen(vpt->name))); + + /* + * This is less efficient than just stealing the + * xlat into the context of the new node... + * + * But talloc_steal can be extremely inefficient O(N) + * where N is chunk siblings. + */ + xlat_copy(arg->group, arg->group, xlat); + arg->quote = quote; + arg->flags = xlat->flags; + + talloc_free(node); /* also frees tmpl, leaving just the xlat */ + + if (cast) { + xlat_func_append_arg(cast, arg, false); node = cast; + } else { + node = arg; } - talloc_free(vpt); goto done; } @@ -2372,7 +2381,7 @@ static fr_slen_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuf */ node->vpt = vpt; node->quote = quote; - node->fmt = vpt->name; + xlat_exp_set_name_buffer_shallow(node, vpt->name); node->flags.pure = tmpl_is_data(node->vpt); node->flags.constant = node->flags.pure; @@ -2694,7 +2703,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]))); - node->fmt = fr_tokens[op]; node->call.func = func; node->flags = func->flags; diff --git a/src/lib/unlang/xlat_inst.c b/src/lib/unlang/xlat_inst.c index b8475027b06..a7ef6b977aa 100644 --- a/src/lib/unlang/xlat_inst.c +++ b/src/lib/unlang/xlat_inst.c @@ -641,7 +641,5 @@ int xlat_inst_remove(xlat_exp_t *node) TALLOC_FREE(node->call.inst); } - - node->type = XLAT_INVALID; return 0; } diff --git a/src/lib/unlang/xlat_priv.h b/src/lib/unlang/xlat_priv.h index d65947c0b0d..27ffc8c6d49 100644 --- a/src/lib/unlang/xlat_priv.h +++ b/src/lib/unlang/xlat_priv.h @@ -34,6 +34,7 @@ extern "C" { #include #include #include +#include #ifdef DEBUG_XLAT # define XLAT_DEBUG RDEBUG3 @@ -41,6 +42,18 @@ extern "C" { # define XLAT_DEBUG(...) #endif +/* + * Allow public and private versions of the same structures + */ +#ifdef _CONST +# error _CONST can only be defined in the local header +#endif +#ifndef _XLAT_PRIVATE +# define _CONST const +#else +# define _CONST +#endif + typedef fr_slen_t (*xlat_print_t)(fr_sbuff_t *in, xlat_exp_t const *self, void *inst, fr_sbuff_escape_rules_t const *e_rules); typedef int (*xlat_resolve_t)(xlat_exp_t *self, void *inst, xlat_res_rules_t const *xr_rules); typedef int (*xlat_purify_t)(xlat_exp_t *self, void *inst, request_t *request); @@ -125,13 +138,18 @@ typedef struct { * These nodes form a tree which represents one or more nested expansions. */ struct xlat_exp_s { - char const *fmt; //!< The original format string (a talloced buffer). - fr_token_t quote; //!< Type of quoting around XLAT_GROUP types. + char const * _CONST fmt; //!< The original format string (a talloced buffer). + fr_token_t quote; //!< Type of quoting around XLAT_GROUP types. + + xlat_flags_t flags; //!< Flags that control resolution and evaluation. - xlat_flags_t flags; //!< Flags that control resolution and evaluation. + xlat_type_t _CONST type; //!< type of this expansion. + fr_dlist_t entry; - xlat_type_t type; //!< type of this expansion. - fr_dlist_t entry; +#ifndef NDEBUG + char const * _CONST file; //!< File where the xlat was allocated. + int line; //!< Line where the xlat was alocated. +#endif union { xlat_exp_head_t *alternate[2]; //!< alternate expansions @@ -160,11 +178,16 @@ struct xlat_exp_s { }; struct xlat_exp_head_s { - char const *fmt; //!< The original format string (a talloced buffer). - xlat_flags_t flags; //!< Flags that control resolution and evaluation. - bool instantiated; //!< temporary flag until we fix more things - fr_dict_t const *dict; //!< dictionary for this xlat - fr_dlist_head_t dlist; + fr_dlist_head_t dlist; + char const * _CONST fmt; //!< The original format string (a talloced buffer). + xlat_flags_t flags; //!< Flags that control resolution and evaluation. + bool instantiated; //!< temporary flag until we fix more things + fr_dict_t const *dict; //!< dictionary for this xlat + +#ifndef NDEBUG + char const * _CONST file; //!< File where the xlat was allocated. + int line; //!< Line where the xlat was alocated. +#endif }; @@ -217,146 +240,6 @@ static inline xlat_exp_t *xlat_exp_next(xlat_exp_head_t const *head, xlat_exp_t 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; - } -} - -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_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. - * @param[in] type of the node. - * @param[in] in original input string. - * @param[in] inlen the length of the original input string. - * @return A new xlat node. - */ -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; - - /* - * 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; - - node->fmt = talloc_bstrndup(node, in, inlen); - switch (type) { - case XLAT_BOX: - fr_value_box_strdup_shallow(&node->data, NULL, node->fmt, false); - break; - - default: - break; - } - - return node; -} - -/** Set the format string for an xlat node - * - * @param[in] node to set fmt for. - * @param[in] fmt talloced buffer to set as the fmt string. - */ -static inline void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt) -{ - if (node->fmt) talloc_const_free(node->fmt); - node->fmt = fmt; -} - - /** Mark an xlat function as internal * * @param[in] xlat to mark as internal. @@ -411,10 +294,27 @@ int xlat_purify_list(xlat_exp_head_t *head, request_t *request); */ typedef int (*xlat_walker_t)(xlat_exp_t *exp, void *uctx); +/* + * xlat_alloc.c + */ +xlat_exp_head_t *_xlat_exp_head_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx); +#define xlat_exp_head_alloc(_ctx) _xlat_exp_head_alloc(NDEBUG_LOCATION_EXP _ctx) + +void _xlat_exp_set_type(NDEBUG_LOCATION_ARGS xlat_exp_t *node, xlat_type_t type); +#define xlat_exp_set_type(_node, _type) _xlat_exp_set_type(NDEBUG_LOCATION_EXP _node, _type) + +xlat_exp_t *_xlat_exp_alloc_null(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx); +#define xlat_exp_alloc_null(_ctx) _xlat_exp_alloc_null(NDEBUG_LOCATION_EXP _ctx) + +xlat_exp_t *_xlat_exp_alloc(NDEBUG_LOCATION_ARGS TALLOC_CTX *ctx, xlat_type_t type, char const *in, size_t inlen); +#define xlat_exp_alloc(_ctx, _type, _in, _inlen) _xlat_exp_alloc(NDEBUG_LOCATION_EXP _ctx, _type, _in, _inlen) + +void xlat_exp_set_name_buffer_shallow(xlat_exp_t *node, char const *fmt) CC_HINT(nonnull); + /* * xlat_func.c */ -xlat_t *xlat_func_find(char const *name, ssize_t namelen); +xlat_t *xlat_func_find(char const *name, ssize_t namelen); /* * xlat_eval.c @@ -450,9 +350,9 @@ void unlang_xlat_init(void); int unlang_xlat_push_node(TALLOC_CTX *ctx, bool *p_success, FR_DLIST_HEAD(fr_value_box_list) *out, request_t *request, xlat_exp_t *node); -int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, - request_t *request, void *decode_ctx, fr_pair_decode_t decode, - FR_DLIST_HEAD(fr_value_box_list) *in); +int xlat_decode_value_box_list(TALLOC_CTX *ctx, fr_pair_list_t *out, + request_t *request, void *decode_ctx, fr_pair_decode_t decode, + FR_DLIST_HEAD(fr_value_box_list) *in); /* * xlat_expr.c */ diff --git a/src/lib/unlang/xlat_purify.c b/src/lib/unlang/xlat_purify.c index 42714a7431a..676a38a8612 100644 --- a/src/lib/unlang/xlat_purify.c +++ b/src/lib/unlang/xlat_purify.c @@ -38,15 +38,19 @@ static void xlat_value_list_to_xlat(xlat_exp_head_t *head, FR_DLIST_HEAD(fr_valu while ((box = fr_value_box_list_pop_head(list)) != NULL) { MEM(node = xlat_exp_alloc(head, XLAT_BOX, NULL, 0)); fr_value_box_copy(node, &node->data, box); - talloc_free(box); if (node->data.type == FR_TYPE_STRING) { node->quote = T_DOUBLE_QUOTED_STRING; - node->fmt = node->data.vb_strvalue; + xlat_exp_set_name_buffer_shallow(node, node->data.vb_strvalue); } else { + char *name; + node->quote = T_BARE_WORD; - node->fmt = ""; /* @todo - fixme? */ + fr_value_box_aprint(node, &name, box, NULL); + + xlat_exp_set_name_buffer_shallow(node, name); } + talloc_free(box); xlat_exp_insert_tail(head, node); } @@ -57,7 +61,6 @@ int xlat_purify_list(xlat_exp_head_t *head, request_t *request) { int rcode; bool success; - xlat_exp_head_t *group; FR_DLIST_HEAD(fr_value_box_list) list; xlat_flags_t our_flags; @@ -155,19 +158,13 @@ int xlat_purify_list(xlat_exp_head_t *head, request_t *request) if (!success) return -1; /* - * The function call becomes a GROUP of boxes. We just re-use the argument head, - * which is already of the type we need. + * The function call becomes a GROUP of boxes */ - /* coverity[dead_error_begin] */ - group = node->call.args; - fr_dlist_talloc_free(&group->dlist); - xlat_inst_remove(node); - node->type = XLAT_GROUP; - node->group = group; + xlat_exp_set_type(node, XLAT_GROUP); /* Frees the argument list */ - xlat_value_list_to_xlat(group, &list); - node->flags = group->flags; + xlat_value_list_to_xlat(node->group, &list); + node->flags = node->group->flags; break; } diff --git a/src/lib/unlang/xlat_tokenize.c b/src/lib/unlang/xlat_tokenize.c index 9f852e0dd0e..520ea0185e6 100644 --- a/src/lib/unlang/xlat_tokenize.c +++ b/src/lib/unlang/xlat_tokenize.c @@ -120,7 +120,7 @@ xlat_exp_t *xlat_exp_func_alloc(TALLOC_CTX *ctx, xlat_t *func, xlat_exp_head_t c MEM(node = xlat_exp_alloc(ctx, XLAT_FUNC, func->name, strlen(func->name))); node->call.func = func; - if (unlikely(xlat_copy(node, &node->call.args, args) < 0)) { + if (unlikely(xlat_copy(node, node->call.args, args) < 0)) { talloc_free(node); return NULL; } @@ -284,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, *arg_group; + xlat_exp_t *node; xlat_t *func; fr_sbuff_marker_t m_s; @@ -1061,13 +1061,15 @@ static void _xlat_debug(xlat_exp_head_t const *head, int depth) fr_assert(head != NULL); - INFO_INDENT("head flags = { %s %s %s }", - head->flags.needs_resolving ? "need_resolving" : "", + INFO_INDENT("head flags = %s %s %s", + head->flags.needs_resolving ? "need_resolving," : "", head->flags.pure ? "pure" : "", head->flags.can_purify ? "can_purify" : ""); + depth++; + xlat_exp_foreach(head, node) { - INFO_INDENT("[%d] flags = { %s %s %s }", i++, + INFO_INDENT("[%d] flags = %s %s %s ", i++, node->flags.needs_resolving ? "need_resolving" : "", node->flags.pure ? "pure" : "", node->flags.can_purify ? "can_purify" : ""); @@ -1080,6 +1082,9 @@ static void _xlat_debug(xlat_exp_head_t const *head, int depth) needs_resolving |= node->flags.needs_resolving; #endif + INFO_INDENT("{"); + depth++; + if (node->quote != T_BARE_WORD) INFO_INDENT("quote = %c", fr_token_quote[node->quote]); switch (node->type) { @@ -1173,10 +1178,10 @@ static void _xlat_debug(xlat_exp_head_t const *head, int depth) case XLAT_ALTERNATE: DEBUG("XLAT-IF {"); - _xlat_debug(node->alternate[0], depth + 1); + _xlat_debug(node->alternate[0], depth); DEBUG("}"); DEBUG("XLAT-ELSE {"); - _xlat_debug(node->alternate[1], depth + 1); + _xlat_debug(node->alternate[1], depth); DEBUG("}"); break; @@ -1184,6 +1189,9 @@ static void _xlat_debug(xlat_exp_head_t const *head, int depth) DEBUG("XLAT-INVALID"); break; } + + depth--; + INFO_INDENT("}"); } fr_assert(needs_resolving == head->flags.needs_resolving); @@ -2047,17 +2055,13 @@ done: * - 0 on success. * - -1 on failure. */ -int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in) +int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t *out, xlat_exp_head_t const *in) { - xlat_exp_head_t *head; + xlat_exp_head_t *head = NULL; - if (!in) { - *out = NULL; - return 0; - } + if (!in) return 0; - MEM(head = xlat_exp_head_alloc(ctx)); - head->flags = in->flags; + xlat_flags_merge(&out->flags, &in->flags); /* * Copy everything in the list of nodes @@ -2065,7 +2069,14 @@ int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in) xlat_exp_foreach(in, p) { xlat_exp_t *node; - MEM(node = xlat_exp_alloc(ctx, p->type, p->fmt, talloc_array_length(p->fmt) - 1)); + (void)talloc_get_type_abort(p, xlat_exp_t); + + /* + * Ensure the format string is valid... At this point + * they should all be talloc'd strings. + */ + MEM(node = xlat_exp_alloc(ctx, p->type, + talloc_get_type_abort(p->fmt, char), talloc_array_length(p->fmt) - 1)); node->quote = p->quote; node->flags = p->flags; @@ -2099,12 +2110,12 @@ int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in) */ node->call.func = p->call.func; node->call.ephemeral = p->call.ephemeral; - if (unlikely(xlat_copy(node, &node->call.args, p->call.args) < 0)) goto error; + if (unlikely(xlat_copy(node, node->call.args, p->call.args) < 0)) goto error; break; case XLAT_TMPL: node->vpt = tmpl_copy(node, p->vpt); - continue; + break; #ifdef HAVE_REGEX case XLAT_REGEX: @@ -2113,18 +2124,17 @@ int xlat_copy(TALLOC_CTX *ctx, xlat_exp_head_t **out, xlat_exp_head_t const *in) #endif case XLAT_ALTERNATE: - if (unlikely(xlat_copy(node, &node->alternate[0], p->alternate[0]) < 0)) goto error; - if (unlikely(xlat_copy(node, &node->alternate[1], p->alternate[1]) < 0)) goto error; + if (unlikely(xlat_copy(node, node->alternate[0], p->alternate[0]) < 0)) goto error; + if (unlikely(xlat_copy(node, node->alternate[1], p->alternate[1]) < 0)) goto error; break; case XLAT_GROUP: - if (unlikely(xlat_copy(node, &node->group, p->group) < 0)) goto error; + if (unlikely(xlat_copy(node, node->group, p->group) < 0)) goto error; break; } - xlat_exp_insert_tail(head, node); + xlat_exp_insert_tail(out, node); } - *out = head; return 0; }