]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
hacks to check input terminal sequences.
authorAlan T. DeKok <aland@freeradius.org>
Tue, 7 Jun 2022 22:42:20 +0000 (18:42 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 20 Jun 2022 15:46:57 +0000 (11:46 -0400)
These really need to be cleaned up, as when we're in the middle
of parsing an expression like

(foo......)

we do NOT want to pay attention to input terminals.  We've hit our
tokenizer, and WE decide what the tokens are.

src/lib/unlang/xlat_expr.c

index 362e1a1092e8bf2a6e5648167d5704d8359ad8e6..b5f8aa8dd4398fd3ebc73df46908e9150ba180e1 100644 (file)
@@ -1441,11 +1441,13 @@ static const int precedence[T_TOKEN_LAST] = {
 
 static ssize_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
                                   fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
-                                  fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules, bool expect_regex);
+                                  fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules,
+                                  fr_sbuff_parse_rules_t const *input_rules, bool expect_regex, int depth);
 
 static ssize_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
-                             fr_sbuff_parse_rules_t const *bracket_rules, bool expect_regex);
+                             fr_sbuff_parse_rules_t const *bracket_rules,
+                             fr_sbuff_parse_rules_t const *input_rules, bool expect_regex, int depth);
 
 static fr_table_num_sorted_t const expr_quote_table[] = {
        { L("\""),      T_DOUBLE_QUOTED_STRING  },      /* Don't re-order, backslash throws off ordering */
@@ -1471,7 +1473,8 @@ static size_t expr_quote_table_len = NUM_ELEMENTS(expr_quote_table);
  */
 static ssize_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
-                             fr_sbuff_parse_rules_t const *bracket_rules, bool expect_regex)
+                             fr_sbuff_parse_rules_t const *bracket_rules,
+                             fr_sbuff_parse_rules_t const *input_rules, bool expect_regex, int depth)
 {
        ssize_t                 slen;
        xlat_exp_t              *node = NULL, *unary = NULL;
@@ -1527,7 +1530,7 @@ static ssize_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_
         *      that we return that, and not the child node
         */
        if (!func) {
-               return tokenize_field(head, out, in, p_rules, t_rules, bracket_rules, expect_regex);
+               return tokenize_field(head, out, in, p_rules, t_rules, bracket_rules, input_rules, expect_regex, depth);
        }
        
        MEM(unary = xlat_exp_alloc(head, XLAT_FUNC, func->name, strlen(func->name)));
@@ -1536,8 +1539,8 @@ static ssize_t tokenize_unary(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_
        unary->call.func = func;
        unary->flags = func->flags;
 
-       slen = tokenize_field(unary->call.args, &node, &our_in, p_rules, t_rules, bracket_rules, expect_regex);
-       if (slen <= 0) {
+       slen = tokenize_field(unary->call.args, &node, &our_in, p_rules, t_rules, bracket_rules, input_rules, expect_regex, depth);
+       if (slen < 0) {
                talloc_free(unary);
                FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
        }
@@ -1608,7 +1611,8 @@ static ssize_t expr_cast_from_substr(fr_type_t *cast, fr_sbuff_t *in)
  */
 static ssize_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
                              fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
-                             fr_sbuff_parse_rules_t const *bracket_rules, bool expect_regex)
+                             fr_sbuff_parse_rules_t const *bracket_rules,
+                             fr_sbuff_parse_rules_t const *input_rules, bool expect_regex, int depth)
 {
        ssize_t                 slen;
        xlat_exp_t              *node = NULL;
@@ -1641,7 +1645,7 @@ static ssize_t tokenize_field(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_
         *      value when we get the output of the expression.
         */
        if (fr_sbuff_next_if_char(&our_in, '(')) {
-               slen = tokenize_expression(head, &node, &our_in, bracket_rules, t_rules, T_INVALID, bracket_rules, false);
+               slen = tokenize_expression(head, &node, &our_in, bracket_rules, t_rules, T_INVALID, bracket_rules, input_rules, false, depth + 1);
                if (slen <= 0) {
                        FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
                }
@@ -1995,7 +1999,8 @@ static int reparse_rcode(TALLOC_CTX *ctx, xlat_exp_t **p_arg, bool allow)
  */
 static ssize_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr_sbuff_t *in,
                                   fr_sbuff_parse_rules_t const *p_rules, tmpl_rules_t const *t_rules,
-                                  fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules, bool expect_regex)
+                                  fr_token_t prev, fr_sbuff_parse_rules_t const *bracket_rules,
+                                  fr_sbuff_parse_rules_t const *input_rules, bool expect_regex, int depth)
 {
        xlat_exp_t      *lhs = NULL, *rhs = NULL, *node;
        xlat_t          *func = NULL;
@@ -2015,12 +2020,17 @@ static ssize_t tokenize_expression(xlat_exp_head_t *head, xlat_exp_t **out, fr_s
         *      Get the LHS of the operation.
         */
        if (expect_regex) {
-               slen = tokenize_field(head, &lhs, &our_in, p_rules, t_rules, bracket_rules, expect_regex);
+               slen = tokenize_field(head, &lhs, &our_in, p_rules, t_rules, bracket_rules, input_rules, expect_regex, depth);
        } else {
-               slen = tokenize_unary(head, &lhs, &our_in, p_rules, t_rules, bracket_rules, false);
+               slen = tokenize_unary(head, &lhs, &our_in, p_rules, t_rules, bracket_rules, input_rules, false, depth);
        }
-       if (slen <= 0) return slen;
+       if (slen < 0) return slen;
 
+       if (slen == 0) {
+               fr_assert(lhs == NULL);
+               *out = NULL;
+               return fr_sbuff_set(in, &our_in);
+       }
 
 redo:
 #ifdef __clang_analyzer__
@@ -2057,6 +2067,11 @@ redo:
        }
        fr_sbuff_skip_whitespace(&our_in);
 
+       /*
+        *      We hit a terminal sequence, stop.
+        */
+       if (input_rules && (depth == 0) && fr_sbuff_is_terminal(&our_in, input_rules->terminals)) goto done;
+
        /*
         *      Remember where we were after parsing the LHS.
         */
@@ -2099,8 +2114,8 @@ redo:
         *      We now parse the RHS, allowing a (perhaps different) cast on the RHS.
         */
        XLAT_DEBUG("    recurse RHS <-- %pV", fr_box_strvalue_len(fr_sbuff_current(&our_in), fr_sbuff_remaining(&our_in)));
-       slen = tokenize_expression(head, &rhs, &our_in, p_rules, t_rules, op, bracket_rules,
-                                  ((op == T_OP_REG_EQ) || (op == T_OP_REG_NE)));
+       slen = tokenize_expression(head, &rhs, &our_in, p_rules, t_rules, op, bracket_rules, input_rules,
+                                  ((op == T_OP_REG_EQ) || (op == T_OP_REG_NE)), depth);
        if (slen <= 0) {
                talloc_free(lhs);
                FR_SBUFF_ERROR_RETURN_ADJ(&our_in, slen);
@@ -2273,7 +2288,7 @@ ssize_t xlat_tokenize_expression(TALLOC_CTX *ctx, xlat_exp_head_t **out, fr_sbuf
                t_rules = &my_rules;
        }
 
-       slen = tokenize_expression(head, &node, in, terminal_rules, t_rules, T_INVALID, bracket_rules, false);
+       slen = tokenize_expression(head, &node, in, terminal_rules, t_rules, T_INVALID, bracket_rules, p_rules, false, 0);
        talloc_free(bracket_rules);
        talloc_free(terminal_rules);
 
@@ -2373,7 +2388,7 @@ ssize_t xlat_tokenize_ephemeral_expression(TALLOC_CTX *ctx, xlat_exp_head_t **ou
        my_rules.xlat.runtime_el = el;
        my_rules.at_runtime = true;
 
-       slen = tokenize_expression(head, &node, in, terminal_rules, &my_rules, T_INVALID, bracket_rules, false);
+       slen = tokenize_expression(head, &node, in, terminal_rules, &my_rules, T_INVALID, bracket_rules, p_rules, false, 0);
        talloc_free(bracket_rules);
        talloc_free(terminal_rules);