Skip to content

MIR: Do we allow accesing a moved place? #112564

Closed
@cbeuw

Description

@cbeuw

fn14() dereferences a pointer to a place that has been moved to another function. Currently, Miri thinks this is fine, but this causes the compiled code to produce different results under different optimisation levels.

#![feature(custom_mir, core_intrinsics)]
extern crate core;
use core::intrinsics::mir::*;

pub fn dump_var(val0: u32) {
    println!("{val0}");
}

pub struct Adt52 {
    fld1: (u32, usize, u16),
}

#[custom_mir(dialect = "runtime", phase = "initial")]
fn fn14() {
    mir! {
    let fld1: (u32, usize, u16);
    let non_copy: Adt52;
    let p: *const u32;
    let i: u32;
    let unit: ();
    {
        fld1 = (0, 0_usize, 0);
        non_copy = Adt52 {fld1};
        p = core::ptr::addr_of!(non_copy.fld1.0);
        Call(unit, bb13, fn15(Move(non_copy)))
    }
    bb13 = {
        i = *p;
        Call(unit, bb18, dump_var(i))
    }
    bb18 = {
        Return()
    }

    }
}
pub fn fn15(mut x: Adt52) {
    x.fld1 = (1, 0, 0);
}
pub fn main() {
    fn14();
}
% rustc -Zmir-opt-level=2 -Copt-level=3 repro.rs && ./repro
0
% rustc -Zmir-opt-level=1 -Copt-level=3 repro.rs && ./repro
1
% ../miri/miri run ./repro.rs
0

At the moment, this is only reproducible with custom MIR, because when we build MIR from surface Rust we always create a temporary, so you cannot create a pointer to anything that will be directly moved into another function.

fn fn14() {
    let fld1 = (0, 0, 0);

    let mut non_copy = Adt52 {fld1};              // _2 = Adt52 { fld1: _1 };
    let p = core::ptr::addr_of!(non_copy.fld1.0); // _3 = &raw const ((_2.0: (u32, usize, u16)).0: u32);
    fn15(non_copy);                               // _5 = move _2;
                                                  // _4 = fn15(move _5) -> bb1;

    let i = unsafe { *p };
    dump_var(i);
}

So either we should call this UB or codegen shouldn't rely on the assumption that a moved MIR place will never be used later.

cc @RalfJung

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlT-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions