Skip to content

CopyProp doesn't always respect Tree Borrows #141122

Open
@saethlin

Description

@saethlin

Reduced example from rustlantis, which is accepted by Miri using Tree Borrows without optimizations enabled:

#![feature(custom_mir, core_intrinsics)]
#![allow(internal_features)]

use std::intrinsics::mir::*;

#[custom_mir(dialect = "runtime")]
fn main() {
  mir! {
    let _1;
    let _2;
    let _3;
    let _4;
    let _5;
    let _6;
    let _7;
    {
      _1 = core::ptr::addr_of!(_2);
      _3 = 'b';
      _5 = _3;
      _6 = &_3;
      _4 = _5;
      *_1 = *_6;
      _6 = &_5;
      Call(_7 = dump_var(_4), ReturnTo(bb1), UnwindUnreachable())
    }
    bb1 = { Return() }
  }
}
fn dump_var<T>(_: T) {}

If I run this under Miri with -Zmir-enable-passes=+CopyProp, I see:

error: Undefined Behavior: read access through <1505> at alloc716[0x0] is forbidden
  --> 11575300419653739436.rs:20:7
   |
20 |       *_1 = *_6;
   |       ^^^^^^^^^ read access through <1505> at alloc716[0x0] is forbidden
   |
   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
   = help: the accessed tag <1505> has state Disabled which forbids this child read access
help: the accessed tag <1505> was created here, in the initial state Frozen
  --> 11575300419653739436.rs:18:7
   |
18 |       _6 = &_3;
   |       ^^^^^^^^
help: the accessed tag <1505> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
  --> 11575300419653739436.rs:19:7
   |
19 |       _4 = _5;
   |       ^^^^^^^
   = help: this transition corresponds to a loss of read permissions
   = note: BACKTRACE (of the first span):
   = note: inside `main` at 11575300419653739436.rs:20:7: 20:16

The MIR diff for CopyProp is

 fn main() -> () {
     let mut _0: ();
     let mut _1: *const char;
     let mut _2: char;
     let mut _3: char;
     let mut _4: char;
     let mut _5: char;
     let mut _6: &char;
     let mut _7: ();
 
     bb0: {
         _1 = &raw const _2;
         _3 = const 'b';
         _5 = copy _3;
         _6 = &_3;
-        _4 = copy _5;
+        _3 = copy _5;
         (*_1) = copy (*_6);
         _6 = &_5;
-        _7 = dump_var::<char>(copy _4) -> [return: bb1, unwind unreachable];
+        _7 = dump_var::<char>(copy _3) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
         return;
     }
 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-mir-optArea: MIR optimizationsA-rustlantisA miscompilation found by RustlantisC-bugCategory: This is a bug.I-miscompileIssue: Correct Rust code lowers to incorrect machine codeI-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions