STR
struct Bomb;
struct Observer<'a>(&'a mut (String, Bomb));
impl Drop for Bomb {
fn drop(&mut self) {
panic!("panicking destructors ftw!");
}
}
impl<'a> Drop for Observer<'a> {
fn drop(&mut self) {
let _spray = "0wned".to_owned();
println!("{}", &self.0 .0);
}
}
fn foo(b: &mut Observer) {
*b.0 = ("~".to_owned(), Bomb);
}
fn main() {
let mut bomb = ("clear".to_owned(), Bomb);
let mut observer = Observer(&mut bomb);
foo(&mut observer);
}
Results
The assignment to *b.0 within foo calls the drop-glue for the value inside. The new tuple ("~", Bomb) is created, and then the drop glue for the old value of b is executed. It first frees the original string, and then attempts to calls Bomb's destructor. As the latter destructor panics, the function unwinds without storing a value in the place of the missing String, leaving a &mut reference that points to an invalid value, which can later be observed by a destructor or recover.
Fixes
The new value for the destination is available the whole time - the panic handler can just write it in.
STR
Results
The assignment to
*b.0withinfoocalls the drop-glue for the value inside. The new tuple("~", Bomb)is created, and then the drop glue for the old value ofbis executed. It first frees the original string, and then attempts to callsBomb's destructor. As the latter destructor panics, the function unwinds without storing a value in the place of the missingString, leaving a&mutreference that points to an invalid value, which can later be observed by a destructor orrecover.Fixes
The new value for the destination is available the whole time - the panic handler can just write it in.