Skip to content

Miri does not detect UB due to overlaping RHS and LHS from aggregate assignment (requires custom MIR) #4712

@RalfJung

Description

@RalfJung

Consider this example:

#![feature(core_intrinsics)]
#![feature(custom_mir)]

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

#[custom_mir(dialect = "runtime", phase = "optimized")]
fn test(x: (i32, i32)) -> (i32, i32) {
    mir! {
        {
            x = (x.1, x.0);
            RET = x;
            Return()
        }
    }
}

fn main() {
    dbg!(test((0, 1)));
}

Miri and codegen currently produce the rather nonsensical output (1, 1). Arguably this code should either be UB, or produce (1, 0).

A strict reading of the MIR docs would allow the code as written but disallow a variant with a triple instead of a tuple, based on this part of the Statement docs:

Specifically, overlap is permitted only for assignments of a type with BackendRepr::Scalar | BackendRepr::ScalarPair where all the scalar fields are Scalar::Initialized

However, that part is explicitly marked as WIP -- I doubt anyone intended to allow overlapping LHS and RHS for aggregate assignment, and if they are allowed, then the output (1, 1) is definitely not in accordance with any interpretation of MIR semantics.

So I think, at least for now, this should be considered UB. That means codegen doesn't need changing, but Miri does. This is somewhat non-trivial to detect since we (have to) do the assignment field-by-field so how would we even realize that we're reading from the same memory we are writing to?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-interpreterArea: affects the core interpreterC-bugCategory: This is a bug.I-misses-UBImpact: makes Miri miss UB, i.e., a false negative (with default settings)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions