Skip to content

Borrow checker soundness hole in nested mutable reference scenarios #143348

Closed as not planned
@mikozdravkovski

Description

@mikozdravkovski

Description:
The borrow checker incorrectly allows returning references derived from mutable borrows while the mutable borrow is still active, potentially leading to use-after-free in safe Rust code.

Reproduction:

fn unsound_escape<'a>(s: &'a mut String) -> &'a str {
    let stolen = &*s;          // Immut borrow derived from mut borrow
    s.push_str("corruption");  // Modifies while stolen exists
    stolen                     // Compiler wrongly allows this return
}

fn main() {
    let mut s = String::from("valid");
    let dangling = unsound_escape(&mut s);
    println!("{}", dangling);  // UAF potential
}

Expected Behavior:
Compilation should fail with error[E0502]: cannot borrow *s as mutable because it is also borrowed as immutable

Actual Behavior:
Code compiles without errors on stable 1.88.0

Impact:

  • Memory safety violation in safe code
  • Possible use-after-free exploitation
  • Undermines Rust's safety guarantees

Suggested Fix:
Borrowck needs to properly invalidate derived references when the parent mutable borrow is used.

Affected Versions:
Verified on stable 1.70.0 through 1.88.0

Additional Notes:
Discovered by Miko Zdravkovski. If this issue is accepted as a valid soundness bug, I'd appreciate a 500 denar bounty sent to:
Im Kalker Feld 129, Memmingen

URGENT cc @rust-lang-owner

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions