]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fix fr_cursor_merge so to_append are always inserted in the correct order
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Jan 2018 03:14:58 +0000 (20:14 -0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 25 Jan 2018 19:12:24 +0000 (12:12 -0700)
Previously they'd be reversed, which is fine for things that don't care about item ordering, but not fine for attribute lists

src/lib/util/cursor.c

index 3fdd08f5e319dbdce93f40005dbb1df50e8488ba..ffe95c56af822f2b08c67c8c8256cd38b5538e3c 100644 (file)
@@ -357,14 +357,35 @@ void fr_cursor_insert(fr_cursor_t *cursor, void *v)
  */
 void fr_cursor_merge(fr_cursor_t *cursor, fr_cursor_t *to_append)
 {
-       void            *v;
+       void            *head = NULL, *next, *v;
 
        /*
-        *      We have to do it the expensive way, as to_append
-        *      may use a custom iterator function, and so we only
-        *      merge a subset of the items.
+        *      Build the complete list (in reverse)
         */
-       while ((v = fr_cursor_remove(to_append))) fr_cursor_append(cursor, v);
+       while ((v = fr_cursor_remove(to_append))) {
+               *NEXT_PTR(v) = head;
+               head = v;
+       }
+
+       if (!head) return;
+
+       /*
+        *      Now insert - The elements end up in
+        *      the correct order without advancing
+        *      the cursor.
+        */
+       v = head;
+       if (cursor->current) {
+               do {
+                       next = *NEXT_PTR(v);
+                       fr_cursor_insert(cursor, v);
+               } while ((v = next));
+       } else {
+               do {
+                       next = *NEXT_PTR(v);
+                       fr_cursor_prepend(cursor, v);
+               } while ((v = next));
+       }
 }
 
 /** Remove the current item