]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
allow &list := {} to clear the list
authorAlan T. DeKok <aland@freeradius.org>
Sun, 12 Dec 2021 15:08:13 +0000 (10:08 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 12 Dec 2021 16:33:51 +0000 (11:33 -0500)
which makes a bit more sense than the previous !*ANY

src/lib/unlang/edit.c
src/tests/keywords/edit-list-reset [new file with mode: 0644]

index e2eabebf454fc77fb01cdb5c1a6963886f6efbda..46fd16a7938912948c34d9edf5b505f2ab8fbb7a 100644 (file)
@@ -238,12 +238,17 @@ static int apply_edits(request_t *request, unlang_frame_state_edit_t *state, map
        fr_pair_list_t *children;
        fr_value_box_t const *rhs_box = NULL;
 
-       fr_assert(state->rhs.vpt != NULL);
        fr_assert(state->lhs.vp != NULL);
 
 #ifdef __clang_analyzer__
        if (!state->lhs.vp) return -1;
 #endif
+
+       if (!state->rhs.vpt) {
+               children = &state->rhs.pair_list;
+               goto apply_list;
+       }
+
        /*
         *      Get the resulting value box.
         */
@@ -356,12 +361,22 @@ static int apply_edits(request_t *request, unlang_frame_state_edit_t *state, map
         *      Apply structural thingies!
         */
 apply_list:
-       RDEBUG2("%s %s %s", state->lhs.vpt->name, fr_tokens[map->op], state->rhs.vpt->name);
+       if (state->rhs.vpt) {
+               RDEBUG2("%s %s %s", state->lhs.vpt->name, fr_tokens[map->op], state->rhs.vpt->name);
+       } else {
+               fr_assert(children != NULL);
 
-       if (fr_debug_lvl >= L_DBG_LVL_3) {
-               RINDENT();
-               fr_pair_list_debug(children);
-               REXDENT();
+               /*
+                *      @todo - we need a debug function which takes a request list...
+                */
+               RDEBUG2("%s %s {", state->lhs.vpt->name, fr_tokens[map->op]);
+               if (fr_debug_lvl >= L_DBG_LVL_3) {
+                       RINDENT();
+                       fr_pair_list_debug(children);
+                       REXDENT();
+               }
+
+               RDEBUG2("}", state->lhs.vpt->name, fr_tokens[map->op]);
        }
 
        if (fr_edit_list_apply_list_assignment(state->el,
@@ -407,6 +422,22 @@ leaf:
        return 0;
 }
 
+static int expand_rhs_list(unlang_frame_state_edit_t *state, request_t *request, map_t const *map)
+{
+       if (map->op != T_OP_SET) {
+               REDEBUG("Operator not implemented");
+               return -1;
+       }
+
+       if (!fr_map_list_empty(&map->child)) {
+               REDEBUG("In-place lists not yet implemented");
+               return -1;
+       }
+
+       fr_assert(fr_pair_list_empty(&state->rhs.pair_list));
+
+       return 0;
+}
 
 /** Create a list of modifications to apply to one or more fr_pair_t lists
  *
@@ -488,6 +519,22 @@ static unlang_action_t process_edit(rlm_rcode_t *p_result, request_t *request, u
                                goto error;
                        }
 
+                       /*
+                        *      Leaf attributes MUST have a RHS.
+                        *      Structural attributes MAY have a RHS.
+                        */
+                       if (!map->rhs) {
+                               if (fr_type_is_leaf(state->lhs.vp->vp_type)) {
+                                       REDEBUG("Cannot assign list as a value");
+                                       goto error;
+                               }
+
+                               rcode = expand_rhs_list(state, request, map);
+                               if (rcode < 0) goto error;
+
+                               goto check_rhs;
+                       }
+
                        rcode = template_realize(state, &state->rhs.result, request, map->rhs);
                        if (rcode < 0) goto error;
 
diff --git a/src/tests/keywords/edit-list-reset b/src/tests/keywords/edit-list-reset
new file mode 100644 (file)
index 0000000..ab78d70
--- /dev/null
@@ -0,0 +1,25 @@
+#
+# PRE: edit-list
+#
+
+update control {
+       &Tmp-String-0 := "foo"
+}
+
+#  must exist
+if (!&control.Tmp-String-0) {
+       test_fail
+}
+
+#
+#  Reset the list to empty contents
+#
+&control := {}
+
+#  must not exist
+if (&control.Tmp-String-0) {
+       test_fail
+}
+
+
+success