Closed
Description
There's a way to leak a &mut
member borrowed from a struct, and then manipulate that member from the Drop
handler -- even while it is immutably borrowed!
struct VecWrapper<'a>(&'a mut Vec<u8>);
impl<'a> IntoIterator for VecWrapper<'a> {
type Item = &'a u8;
type IntoIter = std::slice::Iter<'a, u8>;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl<'a> Drop for VecWrapper<'a> {
fn drop(&mut self) {
// aggressively free memory
self.0.clear();
self.0.shrink_to_fit();
}
}
fn main() {
let mut v = vec![1, 2, 3];
for i in VecWrapper(&mut v) {
let s = "foo".to_owned(); // reused allocation
println!("{}! {} {:#x} '{}'", s, i, i, *i as char);
}
}
playground output:
foo! 102 0x66 'f'
foo! 111 0x6f 'o'
foo! 111 0x6f 'o'
So this drop frees the vec's buffer, then an unrelated string allocation reuses the same memory, and those new values come out of the vec::Iter
.
I think if the member was immutable &
, then this "leak" from into_iter()
would be fine since they can both share that reference, and Drop
can't mutate it. But &mut
must be exclusive, of course...