- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Closed
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.
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
Metadata
Metadata
Assignees
Labels
A-borrow-checkerArea: The borrow checkerArea: The borrow checkerC-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.Performance or correctness regression from one stable version to another.