From: Daniel Stenberg Date: Sat, 21 Dec 2024 10:16:09 +0000 (+0100) Subject: llist: survive cleared list better X-Git-Tag: curl-8_12_0~295 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cf47a7740f666ae3c06361781a341a7da403041;p=thirdparty%2Fcurl.git llist: survive cleared list better Make Curl_node_uremove() and Curl_node_take_elem() properly survive run-time when the ->list field has been cleared previously. Like when Curl_node_take_elem() is called twice. We have asserts to catch those situations to make sure we avoid them if we can, but if they still happen in a non-debug build we should make sure the functions survive proper. Pointed out by CodeSonar. Closes #15791 --- diff --git a/lib/llist.c b/lib/llist.c index 8edbab2431..a2c199bc62 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -146,24 +146,26 @@ void *Curl_node_take_elem(struct Curl_llist_node *e) DEBUGASSERT(list->_init == LLISTINIT); DEBUGASSERT(list->_size); DEBUGASSERT(e->_init == NODEINIT); - if(e == list->_head) { - list->_head = e->_next; + if(list) { + if(e == list->_head) { + list->_head = e->_next; - if(!list->_head) - list->_tail = NULL; - else - e->_next->_prev = NULL; - } - else { - if(e->_prev) - e->_prev->_next = e->_next; + if(!list->_head) + list->_tail = NULL; + else + e->_next->_prev = NULL; + } + else { + if(e->_prev) + e->_prev->_next = e->_next; - if(!e->_next) - list->_tail = e->_prev; - else - e->_next->_prev = e->_prev; + if(!e->_next) + list->_tail = e->_prev; + else + e->_next->_prev = e->_prev; + } + --list->_size; } - ptr = e->_ptr; e->_list = NULL; @@ -174,7 +176,6 @@ void *Curl_node_take_elem(struct Curl_llist_node *e) e->_init = NODEREM; /* specific pattern on remove - not zero */ #endif - --list->_size; return ptr; } @@ -191,9 +192,11 @@ Curl_node_uremove(struct Curl_llist_node *e, void *user) list = e->_list; DEBUGASSERT(list); - ptr = Curl_node_take_elem(e); - if(list->_dtor) - list->_dtor(user, ptr); + if(list) { + ptr = Curl_node_take_elem(e); + if(list->_dtor) + list->_dtor(user, ptr); + } } void Curl_node_remove(struct Curl_llist_node *e)