Closed
Description
... which can be used to trigger a UAF in safe code.
rustc 1.26.0 (a77568041 2018-05-07)
binary: rustc
commit-hash: a7756804103447ea4e68a71ccf071e7ad8f7a03e
commit-date: 2018-05-07
host: x86_64-pc-windows-msvc
release: 1.26.0
LLVM version: 6.0
fn main() {
let mut foo = Some("foo".to_string());
let bar = &mut foo;
match bar {
Some(baz) => {
bar.take();
println!("{:?}", baz); // UAF, segfaults or prints garbage
},
None => unreachable!(),
}
}
Original repro:
enum CacheFuture {
Get(Option<String>)
}
fn main() {
let mut f = CacheFuture::Get(Some("foo".to_string()));
match &mut f {
CacheFuture::Get(get) => match get {
Some(mod_name) => {
get.take();
println!("{:?}", mod_name); // UAF, segfaults or prints garbage
},
None => unreachable!(),
},
}
}
Inserting explicit annotations to disable match ergonomics leads to borrowck correctly complaining about two mutable borrows, which leads me to believe this is only because of match ergonomics.
enum CacheFuture {
Get(Option<String>)
}
fn main() {
let mut f = CacheFuture::Get(Some("foo".to_string()));
match *(&mut f) {
CacheFuture::Get(ref mut get) => match *get {
Some(ref mut mod_name) => {
get.take();
println!("{:?}", mod_name);
},
None => unreachable!(),
},
}
}
9 | Some(ref mut mod_name) => {
| ---------------- first mutable borrow occurs here
10 | get.take();
| ^^^ second mutable borrow occurs here
...
14 | },
| - first borrow ends here