]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add xlat_purify and tests
authorAlan T. DeKok <aland@freeradius.org>
Thu, 20 Jan 2022 00:08:35 +0000 (19:08 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 20 Jan 2022 00:08:35 +0000 (19:08 -0500)
which for now only handle xlat_expr, but that's a good enough
test to catch things which had previously been missed.

src/bin/unit_test_attribute.c
src/tests/unit/xlat/purify.txt [new file with mode: 0644]

index bfbdcd794e63c46ed47cefb76bf15b54a1346177..ea1ac85a26b5c52274463dcd667e98bcf3ca543c 100644 (file)
@@ -2631,7 +2631,7 @@ static size_t command_xlat_normalise(command_result_t *result, command_file_ctx_
        RETURN_OK(escaped_len);
 }
 
-/** Parse an reprint and xlat expression expansion
+/** Parse and reprint an xlat expression expansion
  *
  */
 static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc,
@@ -2664,6 +2664,43 @@ static size_t command_xlat_expr(command_result_t *result, command_file_ctx_t *cc
        RETURN_OK(escaped_len);
 }
 
+/** Parse, purify, and reprint an xlat expression expansion
+ *
+ */
+static size_t command_xlat_purify(command_result_t *result, command_file_ctx_t *cc,
+                                    char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
+{
+       ssize_t                 dec_len;
+       xlat_exp_t              *head = NULL;
+       size_t                  input_len = strlen(in), escaped_len;
+//     fr_sbuff_parse_rules_t  p_rules = { .escapes = &fr_value_unescape_double };
+       xlat_flags_t            flags = {
+               .pure = true,
+       };
+
+       dec_len = xlat_tokenize_expression(cc->tmp_ctx, &head, &flags, &FR_SBUFF_IN(in, input_len), NULL,
+                                          &(tmpl_attr_rules_t) {
+                                               .dict_def = cc->tmpl_rules.attr.dict_def ?
+                                                       cc->tmpl_rules.attr.dict_def : cc->config->dict,
+                                               .allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
+                                          });
+       if (dec_len <= 0) {
+               fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
+
+       return_error:
+               RETURN_OK_WITH_ERROR();
+       }
+
+       if (((size_t) dec_len != input_len)) {
+               fr_strerror_printf_push_head("Passed in %zu characters, but only parsed %zd characters", input_len, dec_len);
+               goto return_error;
+       }
+
+       escaped_len = xlat_print(&FR_SBUFF_OUT(data, COMMAND_OUTPUT_MAX), head, &fr_value_escape_double);
+       RETURN_OK(escaped_len);
+}
+
+
 /** Parse an reprint and xlat argv expansion
  *
  */
@@ -2915,6 +2952,12 @@ static fr_table_ptr_sorted_t     commands[] = {
                                        .description = "Parse then print an xlat expression, writing the normalised xlat expansion to the data buffer"
                                }},
 
+       { L("xlat_purify "),    &(command_entry_t){
+                                       .func = command_xlat_purify,
+                                       .usage = "xlat_purify <string>",
+                                       .description = "Parse, purify, then print an xlat expression, writing the normalised xlat expansion to the data buffer"
+                               }},
+
 };
 static size_t commands_len = NUM_ELEMENTS(commands);
 
diff --git a/src/tests/unit/xlat/purify.txt b/src/tests/unit/xlat/purify.txt
new file mode 100644 (file)
index 0000000..31be80e
--- /dev/null
@@ -0,0 +1,114 @@
+proto-dictionary radius
+
+#
+#  xlat_expr, but purified
+#
+xlat_purify 3 + 4
+match 7
+
+xlat_purify 3 * 4
+match 12
+
+xlat_purify 2 + 3 * 4
+match 14
+
+xlat_purify 2 + 3 * 4 + 5
+match 19
+
+#  Same as above with brackets
+xlat_purify 2 + (3 * 4) + 5
+match 19
+
+# not the same
+xlat_purify (2 + 3) * (4 + 5)
+match 45
+
+xlat_purify (2 + 3) * 4 + 5
+match 25
+
+xlat_purify &NAS-Port + 5
+match (%{NAS-Port} + 5)
+
+xlat_purify &Framed-IP-Address & 0xffff0000
+match (%{Framed-IP-Address} & 255.255.0.0)
+
+xlat_purify %{Framed-IP-Address} + 4
+match (%{Framed-IP-Address} + 0.0.0.4)
+
+xlat_purify 1 < 4
+match yes
+
+xlat_purify &Service-Type == Framed-User
+match (%{Service-Type} == Framed-User)
+
+xlat_purify 1 + (&Service-Type == Framed-User)
+match (1 + (%{Service-Type} == Framed-User))
+
+#
+#  Strings of various forms
+#
+xlat_purify &Filter-Id == "foo"
+match (%{Filter-Id} == \"foo\")
+
+xlat_purify "foo" == "bar"
+match no
+
+# note '/' is a prefix, not "divide by 24".
+# and a useless cast is removed
+xlat_purify &Framed-IP-Address < (ipv4prefix) 192.168.0.0/24
+match (%{Framed-IP-Address} < 192.168.0.0/24)
+
+xlat_purify &Framed-IP-Address < (ipv4prefix) 192.168.0.0
+match (%{Framed-IP-Address} < 192.168.0.0/32)
+
+#
+#  For IP addresses, the other side is automatically upcast to a prefix
+#
+
+#xlat_purify &Framed-IP-Address < 192.168.0.0/24
+#match %(cmp_lt:%{Framed-IP-Address}%(cast:ipv4prefix 192.168.0.0/32))
+
+#  same as above, but swap the order
+xlat_purify (ipv4prefix) 192.168.0.0/24 > &Framed-IP-Address
+match (192.168.0.0/24 > %{Framed-IP-Address})
+
+#
+#  Logical && and ||
+#
+xlat_purify 1 < 2 || 4 > 3
+match yes
+
+xlat_purify 2 || (1 > 4)
+match yes
+
+xlat_purify &Filter-Id
+match %{Filter-Id}
+
+xlat_purify %{md5:foo} + "foo"
+match  (%{md5:foo} + \"foo\")
+
+#  We can name the xlat's, tho we don't need to
+xlat_purify %(op_add:4 3) + 6
+match ((4  + 3) + 6)
+
+
+#
+#  useless casts are omitted.
+#
+xlat_purify 1 < (uint32) 2
+match yes
+
+#
+#  @todo - for exec, xlat, etc., if we're doing an existence check of
+#  string / octets, then the check is for "length>0", NOT for parsing
+#  the contents of the data type.
+#
+
+#
+#  This should likely be a parse error at boot time?
+#
+xlat_purify 1 < 2 < 3
+match ERROR offset 9: Cannot compare incompatible types (bool)... < (int64)...
+
+count
+match 51