From: Alan T. DeKok Date: Mon, 28 Nov 2022 00:23:10 +0000 (-0500) Subject: add "local" flag to attributes and glue into tmpl parser X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=84b4cfdb8f849be71f40c0631259ee3adbae2221;p=thirdparty%2Ffreeradius-server.git add "local" flag to attributes and glue into tmpl parser they current are put into the request list, due to the tmpl code not supporting PAIR_LIST_ROOT. As the PAIR_LIST will be going away soon --- diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 27e274fe5f1..4fe8b40cfd4 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -1862,6 +1862,18 @@ do_suffix: */ if (tmpl_attr_parse_filter(err, ar, name, at_rules) < 0) goto error; + /* + * Local variables are always unitary. + * + * [0] is allowed, as is [n], [*], and [#]. But [1], etc. aren't allowed. + */ + if (da->flags.local && (ar->ar_num > 0)) { + fr_strerror_printf("Invalid array reference for local variable"); + if (err) *err = TMPL_ATTR_ERROR_INVALID_ARRAY_INDEX; + fr_sbuff_set(name, &m_s); + goto error; + } + /* * At the end of the attribute reference. If there's a * trailing '.' then there's another attribute reference @@ -2115,10 +2127,16 @@ ssize_t tmpl_afrom_attr_substr(TALLOC_CTX *ctx, tmpl_attr_error_t *err, if (tmpl_is_attr(vpt) && is_raw) tmpl_attr_to_raw(vpt); /* - * Check to see what the first attribute reference - * was. If it wasn't a known list group attribute, - * then we need to add in a default list. + * Local variables cannot be given an explicit parent or list modifier. + * + * @todo - maybe allow parent references for local variables? But that's just weird. */ + if (tmpl_is_attr(vpt) && tmpl_attr_tail_da(vpt) && tmpl_attr_tail_da(vpt)->flags.local && (tmpl_attr_list_num_elements(tmpl_attr(vpt)) > 1)) { + fr_strerror_printf("Local attributes cannot be used in any list"); + if (err) *err = TMPL_ATTR_ERROR_FOREIGN_NOT_ALLOWED; + fr_sbuff_set(&our_name, &m_l); + goto error; + } /* * Check whether the tmpl has a list qualifier. diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index d7e723280f1..38796852b99 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -1712,6 +1712,7 @@ static unlang_t *compile_variable(unlang_t *parent, unlang_compile_t *unlang_ctx fr_dict_attr_flags_t flags = { .internal = true, + .local = true, }; c = *prev; diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 30c52345e42..9a135910957 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -106,6 +106,8 @@ typedef struct { */ unsigned int extra : 1; //!< really "subtype is used by dict, not by protocol" + unsigned int local : 1; //!< is a local variable + /* * main: extra is set, then this field is is key, bit, or a uint16 length field. * radius: is one of 9 options for flags diff --git a/src/tests/keywords/local-array-error b/src/tests/keywords/local-array-error new file mode 100644 index 00000000000..d0174a6f3aa --- /dev/null +++ b/src/tests/keywords/local-array-error @@ -0,0 +1,6 @@ +group { + uint32 foo + + # There's only one local variable + &foo[1] := 1 # ERROR +} diff --git a/src/tests/keywords/local-list-error b/src/tests/keywords/local-list-error new file mode 100644 index 00000000000..d551de75917 --- /dev/null +++ b/src/tests/keywords/local-list-error @@ -0,0 +1,5 @@ +group { + uint32 foo + + &request.foo := 1 # ERROR +} diff --git a/src/tests/keywords/local-variable b/src/tests/keywords/local-variable new file mode 100644 index 00000000000..c04324a67df --- /dev/null +++ b/src/tests/keywords/local-variable @@ -0,0 +1,13 @@ +group { + uint32 foo + + &foo := 1 + + &Filter-Id := &foo + + if !(&Filter-Id == "1") { + test_fail + } +} + +success