From: Alan T. DeKok Date: Wed, 22 Jun 2022 13:57:58 +0000 (-0400) Subject: allow for single-quoted strings in regular expressions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=42535ca1db7d764920e5b39835f07055c1d21d97;p=thirdparty%2Ffreeradius-server.git allow for single-quoted strings in regular expressions --- diff --git a/src/lib/unlang/xlat_expr.c b/src/lib/unlang/xlat_expr.c index 6a9e78d97b1..c3d8fc48d5f 100644 --- a/src/lib/unlang/xlat_expr.c +++ b/src/lib/unlang/xlat_expr.c @@ -366,9 +366,10 @@ static fr_slen_t xlat_expr_print_regex(fr_sbuff_t *out, xlat_exp_t const *node, fr_assert(tmpl_contains_regex(inst->xlat->vpt)); - FR_SBUFF_IN_CHAR_RETURN(out, '/'); + if (inst->xlat->quote == T_SINGLE_QUOTED_STRING) FR_SBUFF_IN_CHAR_RETURN(out, 'm'); + FR_SBUFF_IN_CHAR_RETURN(out, fr_token_quote[inst->xlat->quote]); FR_SBUFF_IN_STRCPY_RETURN(out, inst->xlat->vpt->name); - FR_SBUFF_IN_CHAR_RETURN(out, '/'); + FR_SBUFF_IN_CHAR_RETURN(out, fr_token_quote[inst->xlat->quote]); FR_SBUFF_RETURN(regex_flags_print, out, inst->regex_flags); @@ -1661,6 +1662,7 @@ static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sb fr_sbuff_t our_in = FR_SBUFF(in); fr_sbuff_marker_t opand_m; tmpl_t *vpt; + fr_token_t quote = T_SOLIDUS_QUOTED_STRING; XLAT_DEBUG("REGEX_RHS <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in))); @@ -1671,12 +1673,21 @@ static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sb */ fr_sbuff_marker(&opand_m, &our_in); + /* + * @todo - add m'regex' to support single-quoted regex strings, ala Perl. + */ + /* * Regexes cannot have casts or sub-expressions. */ if (!fr_sbuff_next_if_char(&our_in, '/')) { - fr_strerror_const("Expected regular expression"); - goto error; + if (!fr_sbuff_is_str(&our_in, "m'", 2)) { + fr_strerror_const("Expected regular expression"); + goto error; + } + + fr_sbuff_advance(&our_in, 2); + quote = T_SINGLE_QUOTED_STRING; } /* @@ -1686,10 +1697,10 @@ static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sb xlat_exp_set_type(node, XLAT_TMPL); /* - * tmpl_afrom_substr does pretty much all the work of - * parsing the operand. + * tmpl_afrom_substr does pretty much all the work of parsing the operand. Note that we pass '/' + * as the quote, so that the tmpl gets parsed as a regex. */ - (void) tmpl_afrom_substr(node, &vpt, &our_in, T_SOLIDUS_QUOTED_STRING, value_parse_rules_quoted[T_SOLIDUS_QUOTED_STRING], t_rules); + (void) tmpl_afrom_substr(node, &vpt, &our_in, T_SOLIDUS_QUOTED_STRING, value_parse_rules_quoted[quote], t_rules); if (!vpt) { error: talloc_free(node); @@ -1700,12 +1711,11 @@ static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sb /* * @todo - allow for the RHS to be an attribute, too? */ - fr_assert(tmpl_contains_regex(vpt)); /* * It would be nice if tmpl_afrom_substr() did this :( */ - if (!fr_sbuff_next_if_char(&our_in, '/')) { + if (!fr_sbuff_next_if_char(&our_in, fr_token_quote[quote])) { fr_strerror_const("Unterminated regular expression"); goto error; } @@ -1734,7 +1744,7 @@ static ssize_t tokenize_regex_rhs(xlat_exp_head_t *head, xlat_exp_t **out, fr_sb } node->vpt = vpt; - node->quote = T_SOLIDUS_QUOTED_STRING; + node->quote = quote; node->fmt = vpt->name; node->flags.pure = !tmpl_contains_xlat(node->vpt); diff --git a/src/tests/unit/xlat/cond_regex.txt b/src/tests/unit/xlat/cond_regex.txt index b15c784357c..97dea80b8d9 100644 --- a/src/tests/unit/xlat/cond_regex.txt +++ b/src/tests/unit/xlat/cond_regex.txt @@ -73,5 +73,11 @@ match ERROR offset 2: Invalid regex reference. Must be in range 0-32 xlat_purify &User-Name == /foo/ match ERROR offset 14: Unexpected regular expression +# +# single-quoted strings in regexes! +# +xlat_purify &User-Name =~ m'foo%' +match (&User-Name =~ m'foo%') + count -match 41 +match 43