Skip to content

Commit 016036a

Browse files
authored
Rollup merge of rust-lang#113441 - RalfJung:assign-no-overlap, r=oli-obk
miri: check that assignments do not self-overlap r? ``@oli-obk``
2 parents 1808063 + 7a83ef8 commit 016036a

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

compiler/rustc_const_eval/src/interpret/place.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,13 @@ where
700700
assert_eq!(src.layout.size, dest.layout.size);
701701
}
702702

703+
// Setting `nonoverlapping` here only has an effect when we don't hit the fast-path above,
704+
// but that should at least match what LLVM does where `memcpy` is also only used when the
705+
// type does not have Scalar/ScalarPair layout.
706+
// (Or as the `Assign` docs put it, assignments "not producing primitives" must be
707+
// non-overlapping.)
703708
self.mem_copy(
704-
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ false,
709+
src.ptr, src.align, dest.ptr, dest.align, dest_size, /*nonoverlapping*/ true,
705710
)
706711
}
707712

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#![feature(core_intrinsics)]
2+
#![feature(custom_mir)]
3+
4+
use std::intrinsics::mir::*;
5+
6+
// It's not that easy to fool the MIR validity check
7+
// which wants to prevent overlapping assignments...
8+
// So we use two separate pointer arguments, and then arrange for them to alias.
9+
#[custom_mir(dialect = "runtime", phase = "optimized")]
10+
pub fn self_copy(ptr1: *mut [i32; 4], ptr2: *mut [i32; 4]) {
11+
mir! {
12+
{
13+
*ptr1 = *ptr2; //~ERROR: overlapping ranges
14+
Return()
15+
}
16+
}
17+
}
18+
19+
pub fn main() {
20+
let mut x = [0; 4];
21+
let ptr = std::ptr::addr_of_mut!(x);
22+
self_copy(ptr, ptr);
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
2+
--> $DIR/overlapping_assignment.rs:LL:CC
3+
|
4+
LL | *ptr1 = *ptr2;
5+
| ^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `self_copy` at $DIR/overlapping_assignment.rs:LL:CC
11+
note: inside `main`
12+
--> $DIR/overlapping_assignment.rs:LL:CC
13+
|
14+
LL | self_copy(ptr, ptr);
15+
| ^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to previous error
20+

0 commit comments

Comments
 (0)