]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Fix fr_dlist_foreach_safe
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 6 Sep 2021 20:31:59 +0000 (15:31 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 6 Sep 2021 20:31:59 +0000 (15:31 -0500)
src/lib/util/dlist.h
src/lib/util/dlist_tests.c

index d995ada6e91fa6fd36895b2bfa4ca818202c01c1..71197bf9d903c26dbba06c17f190a5c897fe45d6 100644 (file)
@@ -87,8 +87,8 @@ static_assert(sizeof(unsigned int) >= 4, "Unsigned integer too small on this pla
        for (_iter = fr_dlist_head(_list_head), \
             _tmp = fr_dlist_head(_list_head) ? *fr_dlist_item_to_entry((_list_head)->offset, fr_dlist_head(_list_head)) : (fr_dlist_t){ .prev = NULL, .next = NULL }; \
             _iter; \
-            _iter = _tmp.next ? fr_dlist_entry_to_item((_list_head)->offset, _tmp.next) : NULL, \
-            _tmp = _tmp.next ? *_tmp.next : (fr_dlist_t){ .prev = NULL, .next = NULL })
+            _iter = _tmp.next && (_tmp.next != &(_list_head)->entry) ? fr_dlist_entry_to_item((_list_head)->offset, _tmp.next) : NULL, \
+            _tmp = _tmp.next && (_tmp.next != &(_list_head)->entry) ? *_tmp.next : (fr_dlist_t){ .prev = NULL, .next = NULL })
 
 
 /** Find the dlist pointers within a list item
index edf0f535e9089362c73a081063cef015dafd0fdb..2b48ae4a46f4d7c0afb94ce7e27769e4362f56ac 100644 (file)
@@ -162,13 +162,36 @@ static void test_dlist_entry_move(void)
        TEST_CHECK(a2.entry.prev == &a1.entry);
 }
 
+static void test_dlist_foreach_safe(void)
+{
+       dlist_test_item_t       a1 = { .id = "a1" };
+       dlist_test_item_t       a2 = { .id = "a2" };
+       dlist_test_item_t       a3 = { .id = "a3" };
+
+       fr_dlist_head_t         head;
+       unsigned int            count = 0;
+
+       fr_dlist_init(&head, dlist_test_item_t, entry);
+
+       fr_dlist_insert_tail(&head, &a1);
+       fr_dlist_insert_tail(&head, &a2);
+       fr_dlist_insert_tail(&head, &a3);
+
+       fr_dlist_foreach_safe(&head, dlist_test_item_t, i) {
+               fr_dlist_remove(&head, i);
+               count++;
+       }}
+
+       TEST_CHECK_RET((int)count, (int)3);
+}
+
 TEST_LIST = {
        /*
         *      Allocation and management
         */
        { "fr_dlist_move",              test_dlist_move         },
        { "fr_dlist_entry_move",        test_dlist_entry_move   },
-
+       { "fr_dlist_foreach_safe",      test_dlist_foreach_safe },
 
        { NULL }
 };