From f7277884a65ce9525368b17cdd980c00143f952d Mon Sep 17 00:00:00 2001 From: Patrick Pelissier Date: Sat, 5 Aug 2017 13:06:04 +0200 Subject: [PATCH] Fix issue for intrusive list & free : we read the next pointer after freeing the memory ! --- m-i-list.h | 7 +++++-- tests/test-milist.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/m-i-list.h b/m-i-list.h index a9211b69..9d041098 100644 --- a/m-i-list.h +++ b/m-i-list.h @@ -115,10 +115,13 @@ typedef struct ilist_head_s { static inline void M_C(name, _clean)(list_t list) \ { \ assert (list != NULL); \ - for( struct ilist_head_s *it = list->name.next ; \ - it != &list->name; it = it->next) { \ + for(struct ilist_head_s *it = list->name.next, *next ; \ + it != &list->name; it = next) { \ type *obj = M_TYPE_FROM_FIELD(type, it, \ struct ilist_head_s, name); \ + /* Read next now before the object is destroyed */ \ + next = it->next; \ + assert (next != NULL); \ M_GET_CLEAR oplist (*obj); \ M_IF_METHOD(DEL, oplist)(M_GET_DEL oplist (obj), (void) 0); \ } \ diff --git a/tests/test-milist.c b/tests/test-milist.c index d788bf1f..0dfd286e 100644 --- a/tests/test-milist.c +++ b/tests/test-milist.c @@ -29,13 +29,16 @@ typedef struct test_s { int n; ILIST_INTERFACE (ilist_tname, struct test_s); + ILIST_INTERFACE (ilist_free, struct test_s); } test_t; #include "coverage.h" START_COVERAGE ILIST_DEF(ilist_tname, test_t) END_COVERAGE - + +ILIST_DEF(ilist_free, test_t, (DEL(free))) + static void test(void) { test_t x1, x2, x3; @@ -99,8 +102,33 @@ static void test(void) ilist_tname_clear(list); } -int main(void) +static void test_free(void) +{ + ilist_free_t list; + + ilist_free_init(list); + + for(int i = 0; i < 1200; i++) { + test_t *p = malloc(sizeof(test_t)); + assert(p != NULL); + ilist_free_init_field(p); + p->n = i; + ilist_free_push_back(list, p); + } + assert(ilist_free_size(list) == 1200); + + int n = 0; + for M_EACH(item, list, ILIST_OPLIST(ilist_free, (DEL(free)) )) { + assert (n == item->n); + n++; + } + + ilist_free_clear(list); +} + + int main(void) { test(); + test_free(); exit(0); }