From: Alan T. DeKok Date: Fri, 29 Jul 2022 16:15:06 +0000 (-0400) Subject: ensure that list is empty before merge / union / etc. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d30dad46ad96e22610da3324282eca6cab2b3a9f;p=thirdparty%2Ffreeradius-server.git ensure that list is empty before merge / union / etc. Those operations sort their inputs *without* tracking those changes in the edit list. So if there are already edits in the list, the sort will break the ability to undo things. As a result, we forbid behavior which we know will result in wrong outcomes. --- diff --git a/src/lib/util/edit.c b/src/lib/util/edit.c index 0a8954a8cd3..9d1a4bbb8b2 100644 --- a/src/lib/util/edit.c +++ b/src/lib/util/edit.c @@ -117,6 +117,12 @@ typedef struct { fr_pair_list_t *list; //!< list to ignore (never dereferenced) } fr_edit_ignore_t; + +static bool fr_edit_list_empty(fr_edit_list_t *el) +{ + return fr_dlist_empty(&el->undo) && fr_dlist_empty(&el->ignore) && fr_pair_list_empty(&el->deleted_pairs); +} + /** Undo one particular edit. */ static int edit_undo(fr_edit_t *e) @@ -1333,21 +1339,33 @@ int fr_edit_list_apply_list_assignment(fr_edit_list_t *el, fr_pair_t *dst, fr_to case T_OP_AND_EQ: if (&dst->children == src) return 0; /* A INTERSECTION A == A */ + if (!fr_edit_list_empty(el)) { + not_empty: + fr_strerror_printf("Failed to perform %s - undo list is not empty", fr_tokens[op]); + return -1; + } + return list_intersection(el, dst, src); case T_OP_OR_EQ: if (&dst->children == src) return 0; /* A UNION A == A */ + if (!fr_edit_list_empty(el)) goto not_empty; + return list_union(el, dst, src, copy); case T_OP_GE: if (&dst->children == src) return 0; /* A MERGE A == A */ + if (!fr_edit_list_empty(el)) goto not_empty; + return list_merge_lhs(el, dst, src, copy); case T_OP_LE: if (&dst->children == src) return 0; /* A MERGE A == A */ + if (!fr_edit_list_empty(el)) goto not_empty; + return list_merge_rhs(el, dst, src, copy); default: