From: Alan T. DeKok Date: Sun, 1 Sep 2024 13:41:16 +0000 (-0400) Subject: parse &attr[%{&foo - 1}] X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0568f41c552c8b77b6e0ecd882e7dbb235a9e04c;p=thirdparty%2Ffreeradius-server.git parse &attr[%{&foo - 1}] and ensure that things we parse but don't (yet) support are run-time errors. --- diff --git a/src/lib/server/tmpl.h b/src/lib/server/tmpl.h index 8531d582e0..4dae92676a 100644 --- a/src/lib/server/tmpl.h +++ b/src/lib/server/tmpl.h @@ -414,6 +414,7 @@ typedef enum { TMPL_ATTR_FILTER_TYPE_INDEX, //!< Filter is an index type. TMPL_ATTR_FILTER_TYPE_CONDITION, //!< Filter is a condition TMPL_ATTR_FILTER_TYPE_TMPL, //!< Filter is a tmpl + TMPL_ATTR_FILTER_TYPE_EXPR, //!< Filter is an expression } tmpl_attr_filter_type_t; typedef struct { @@ -428,6 +429,7 @@ typedef struct { union { xlat_exp_head_t _CONST *cond; //!< xlat condition tmpl_t _CONST *tmpl; //!< tmpl + xlat_exp_head_t _CONST *expr; //!< xlat expression }; } tmpl_attr_filter_t; @@ -518,12 +520,14 @@ FR_DLIST_FUNCS(tmpl_request_list, tmpl_request_t, entry) #define ar_num filter.num #define ar_cond filter.cond #define ar_tmpl filter.tmpl +#define ar_expr filter.expr #define ar_filter_type filter.type #define ar_filter_is_none(_ar) ((_ar)->ar_filter_type == TMPL_ATTR_FILTER_TYPE_NONE) #define ar_filter_is_num(_ar) ((_ar)->ar_filter_type == TMPL_ATTR_FILTER_TYPE_INDEX) #define ar_filter_is_cond(_ar) ((_ar)->ar_filter_type == TMPL_ATTR_FILTER_TYPE_CONDITION) #define ar_filter_is_tmpl(_ar) ((_ar)->ar_filter_type == TMPL_ATTR_FILTER_TYPE_TMPL) +#define ar_filter_is_expr(_ar) ((_ar)->ar_filter_type == TMPL_ATTR_FILTER_TYPE_EXPR) /** @} */ /** A source or sink of value data. diff --git a/src/lib/server/tmpl_dcursor.c b/src/lib/server/tmpl_dcursor.c index b67f5261f3..18f1d13d7a 100644 --- a/src/lib/server/tmpl_dcursor.c +++ b/src/lib/server/tmpl_dcursor.c @@ -174,8 +174,16 @@ fr_pair_t *_tmpl_cursor_eval(fr_pair_t *curr, tmpl_dcursor_ctx_t *cc) */ if (ar_filter_is_none(ar)) { num = 0; + + } else if (!ar_filter_is_num(ar)) { + request_t *request = cc->request; + + RDEBUG("Attribute filter is unsupported"); + vp = NULL; + pop = true; + goto done; + } else { - fr_assert(ar_filter_is_num(ar)); num = ar->ar_num; } diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 6a8a0df3c4..dfe6d48677 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -1464,11 +1464,52 @@ static fr_slen_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_attr_t *ar, slen = xlat_tokenize_condition(ar, &ar->ar_cond, &tmp, &p_rules, &t_rules); if (slen < 0) goto error; + fr_assert(!xlat_impure_func(ar->ar_cond)); + ar->ar_filter_type = TMPL_ATTR_FILTER_TYPE_CONDITION; fr_sbuff_set(&our_name, &tmp); /* Advance name _AFTER_ doing checks */ break; } + case '%': /* ${...} expansion */ + { + fr_sbuff_t tmp = FR_SBUFF(&our_name); + fr_slen_t slen; + tmpl_rules_t t_rules; + fr_sbuff_parse_rules_t p_rules; + fr_sbuff_term_t const filter_terminals = FR_SBUFF_TERMS(L("]")); + + if (!fr_sbuff_is_str(&our_name, "%{", 2)) { + fr_strerror_const("Invalid expression in attribute index"); + goto error; + } + + tmp = FR_SBUFF(&our_name); + t_rules = (tmpl_rules_t) {}; + t_rules.attr = *at_rules; + + p_rules = (fr_sbuff_parse_rules_t) { + .terminals = &filter_terminals, + .escapes = NULL + }; + + /* + * Check if it's an expression. + */ + slen = xlat_tokenize_expression(ar, &ar->ar_cond, &tmp, &p_rules, &t_rules); + if (slen < 0) goto error; + + if (xlat_impure_func(ar->ar_expr)) { + fr_strerror_const("Expression in attribute index cannot depend on functions which call external databases"); + goto error; + } + + ar->ar_filter_type = TMPL_ATTR_FILTER_TYPE_EXPR; + + fr_sbuff_set(&our_name, &tmp); /* Advance name _AFTER_ doing checks */ + break; + } + case 'n': /* * [n] is the last one @@ -1514,7 +1555,7 @@ static fr_slen_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_attr_t *ar, if (slen <= 0) goto error; if (!tmpl_is_attr(ar->ar_tmpl)) { - fr_strerror_printf("Invalid array index"); + fr_strerror_const("Invalid array index"); goto error; } @@ -1525,7 +1566,7 @@ static fr_slen_t tmpl_attr_parse_filter(tmpl_attr_error_t *err, tmpl_attr_t *ar, * For matching therefore, we really need to have a way to define "self". */ if (!fr_type_numeric[tmpl_attr_tail_da(ar->ar_tmpl)->type]) { - fr_strerror_printf("Invalid data type for array index (must be numeric)"); + fr_strerror_const("Invalid data type for array index (must be numeric)"); goto error; }