SkipList::clear drops the node chain and only then resets tail and len.
The drop runs each element's Drop, and T carries no bounds excluding a
panicking one. If it unwinds, tail still points at the freed node while len
stays non-zero.
back(), back_mut(), last_key_value() and last() dereference tail
through unsafe, so reading the container after the unwind is a use-after-free
(CWE-416). Drop for SkipList calls Box::from_raw on self.head, which
clear already destroyed, so dropping the container is a double free
(CWE-415).
retain, retain_mut and dedup_by reach the same state through
Node::filter_rebuild, which frees nodes and runs a user predicate before the
caller commits tail and len. There the head links are left partially
rewired, so traversal can also reach freed nodes.
Update to 1.1.1.
{
"license": "CC0-1.0"
}{
"affected_functions": null,
"affects": {
"arch": [],
"functions": [
"skiplist::ordered_skip_list::OrderedSkipList::clear",
"skiplist::ordered_skip_list::OrderedSkipList::dedup_by",
"skiplist::ordered_skip_list::OrderedSkipList::retain",
"skiplist::skip_list::SkipList::clear",
"skiplist::skip_list::SkipList::dedup_by",
"skiplist::skip_list::SkipList::retain",
"skiplist::skip_list::SkipList::retain_mut",
"skiplist::skip_map::SkipMap::clear",
"skiplist::skip_map::SkipMap::retain"
],
"os": []
}
}