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
This commit is contained in:
parent
34713ed8a5
commit
7cf47a7740
43
lib/llist.c
43
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;
|
||||
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;
|
||||
}
|
||||
--list->_size;
|
||||
}
|
||||
else {
|
||||
if(e->_prev)
|
||||
e->_prev->_next = e->_next;
|
||||
|
||||
if(!e->_next)
|
||||
list->_tail = e->_prev;
|
||||
else
|
||||
e->_next->_prev = e->_prev;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user