miri: check that assignments do not self-overlap
This commit is contained in:
parent
1a449dcfd2
commit
7a83ef82da
@ -700,8 +700,13 @@ fn copy_op_no_validate(
|
|||||||
assert_eq!(src.layout.size, dest.layout.size);
|
assert_eq!(src.layout.size, dest.layout.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setting `nonoverlapping` here only has an effect when we don't hit the fast-path above,
|
||||||
|
// but that should at least match what LLVM does where `memcpy` is also only used when the
|
||||||
|
// type does not have Scalar/ScalarPair layout.
|
||||||
|
// (Or as the `Assign` docs put it, assignments "not producing primitives" must be
|
||||||
|
// non-overlapping.)
|
||||||
self.mem_copy(
|
self.mem_copy(
|
||||||
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false,
|
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
src/tools/miri/tests/fail/overlapping_assignment.rs
Normal file
23
src/tools/miri/tests/fail/overlapping_assignment.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![feature(custom_mir)]
|
||||||
|
|
||||||
|
use std::intrinsics::mir::*;
|
||||||
|
|
||||||
|
// It's not that easy to fool the MIR validity check
|
||||||
|
// which wants to prevent overlapping assignments...
|
||||||
|
// So we use two separate pointer arguments, and then arrange for them to alias.
|
||||||
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
|
pub fn self_copy(ptr1: *mut [i32; 4], ptr2: *mut [i32; 4]) {
|
||||||
|
mir! {
|
||||||
|
{
|
||||||
|
*ptr1 = *ptr2; //~ERROR: overlapping ranges
|
||||||
|
Return()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let mut x = [0; 4];
|
||||||
|
let ptr = std::ptr::addr_of_mut!(x);
|
||||||
|
self_copy(ptr, ptr);
|
||||||
|
}
|
20
src/tools/miri/tests/fail/overlapping_assignment.stderr
Normal file
20
src/tools/miri/tests/fail/overlapping_assignment.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
|
||||||
|
--> $DIR/overlapping_assignment.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | *ptr1 = *ptr2;
|
||||||
|
| ^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
|
||||||
|
|
|
||||||
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
= note: BACKTRACE:
|
||||||
|
= note: inside `self_copy` at $DIR/overlapping_assignment.rs:LL:CC
|
||||||
|
note: inside `main`
|
||||||
|
--> $DIR/overlapping_assignment.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | self_copy(ptr, ptr);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user