vcombey / fallible_collections

impl fallible collections in rust, quite as describe in RFC 2116
Apache License 2.0
31 stars 14 forks source link

UB dropping BTreeMap containing dangling items #18

Open dtolnay opened 3 years ago

dtolnay commented 3 years ago

Based on https://github.com/rust-lang/unsafe-code-guidelines/issues/283 I believe the following code illustrates UB:

use fallible_collections::btree::BTreeMap;

fn main() {
    let mut map;
    let s = "...".to_owned();
    map = BTreeMap::<&str, &str>::new();
    map.try_insert(&s, &s).unwrap();

    // s is dropped
    // then map is dropped
}

The drop of map is running this Drop impl:

https://github.com/vcombey/fallible_collections/blob/274288654247e9be8f426d97884a1146678f4b7c/src/btree/map.rs#L129-L135

Based on the IntoIterator impl for BTreeMap, that's converting BTreeMap<&'dangling str, &'dangling str> into IntoIter<&'dangling str, &'dangling str>:

https://github.com/vcombey/fallible_collections/blob/274288654247e9be8f426d97884a1146678f4b7c/src/btree/map.rs#L1350-L1352

and dropping the IntoIter using this impl:

https://github.com/vcombey/fallible_collections/blob/274288654247e9be8f426d97884a1146678f4b7c/src/btree/map.rs#L1368-L1370

However, that ends up materializing a (&'dangling str, &'dangling str) as part of doing self.for_each(drop). As I understand it, it's UB to touch/pass/return dangling references like that by value.