diff options
| author | The Miri Cronjob Bot <miri@cron.bot> | 2024-09-16 05:06:25 +0000 |
|---|---|---|
| committer | The Miri Cronjob Bot <miri@cron.bot> | 2024-09-16 05:06:25 +0000 |
| commit | 4d824fd5b7101bddd2fdd829e474740838687ead (patch) | |
| tree | 7e319bfe4e2ca29e601bb7f1c3a1c1ef22faad68 /src/tools/miri/tests | |
| parent | ffcaa7fddee251f2b7ed2ca62900c2440f25e04f (diff) | |
| parent | c16ff44537509ca911ffd3653b17c6187c71831d (diff) | |
| download | rust-4d824fd5b7101bddd2fdd829e474740838687ead.tar.gz rust-4d824fd5b7101bddd2fdd829e474740838687ead.zip | |
Merge from rustc
Diffstat (limited to 'src/tools/miri/tests')
9 files changed, 237 insertions, 7 deletions
diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs new file mode 100644 index 00000000000..751a308a399 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs @@ -0,0 +1,57 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +#![feature(core_intrinsics)] +#![feature(custom_mir)] + +use std::intrinsics::mir::*; +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; +use std::thread::JoinHandle; + +static P: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut()); + +fn spawn_thread() -> JoinHandle<()> { + std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }) +} + +fn finish(t: JoinHandle<()>, val_ptr: *mut u8) { + P.store(val_ptr, Relaxed); + + // Wait for the thread to be done. + t.join().unwrap(); + + // Read initialized value. + assert_eq!(unsafe { *val_ptr }, 127); +} + +#[custom_mir(dialect = "runtime", phase = "optimized")] +fn main() { + mir! { + let t; + let val; + let val_ptr; + let _ret; + { + Call(t = spawn_thread(), ReturnTo(after_spawn), UnwindContinue()) + } + after_spawn = { + // This races with the write in the other thread. + StorageLive(val); + + val_ptr = &raw mut val; + Call(_ret = finish(t, val_ptr), ReturnTo(done), UnwindContinue()) + } + done = { + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr new file mode 100644 index 00000000000..f46eb078a51 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) creating a new allocation on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_alloc_race.rs:LL:CC + | +LL | StorageLive(val); + | ^^^^^^^^^^^^^^^^ + = 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 (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_alloc_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs new file mode 100644 index 00000000000..80d2b7b7c12 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.rs @@ -0,0 +1,38 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + // Create the local variable, and initialize it. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // This read is not ordered with the store above, and thus should be reported as a race. + let _val = val; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr new file mode 100644 index 00000000000..d14c2fb47ff --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic read on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_read_race.rs:LL:CC + | +LL | let _val = val; + | ^^^ + = 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 (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_read_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs new file mode 100644 index 00000000000..eabbe4403c6 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.rs @@ -0,0 +1,37 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::Ordering::*; +use std::sync::atomic::*; + +static P: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut()); + +fn main() { + let t1 = std::thread::spawn(|| { + while P.load(Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Relaxed); + *ptr = 127; + //~^ ERROR: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-1` + } + }); + + // Create the local variable, and initialize it. + // This is not ordered with the store above, so it's definitely UB + // for that thread to access this variable. + let mut val: u8 = 0; + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory. + // If we just "pre-date" the write to the beginning of time (since we don't know + // when it actually happened), we'd miss the UB in this test. + // Also, the UB error should point at the write above, not the addr-of here. + P.store(std::ptr::addr_of_mut!(val), Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} diff --git a/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr new file mode 100644 index 00000000000..d84db955a3d --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | *ptr = 127; + | ^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic write on thread `unnamed-ID` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/local_variable_write_race.rs:LL:CC + | +LL | let mut val: u8 = 0; + | ^ + = 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 (of the first span) on thread `unnamed-ID`: + = note: inside closure at $DIR/local_variable_write_race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs index aa383a99bc2..c399616b9ae 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-mem.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-mem.rs @@ -101,6 +101,10 @@ fn test_malloc() { let slice = slice::from_raw_parts(p3 as *const u8, 20); assert_eq!(&slice, &[0_u8; 20]); + // new size way too big (so this doesn't actually realloc). + let p_too_big = libc::realloc(p3, usize::MAX); + assert!(p_too_big.is_null()); + // old size > new size let p4 = libc::realloc(p3, 10); let slice = slice::from_raw_parts(p4 as *const u8, 10); @@ -119,9 +123,13 @@ fn test_malloc() { unsafe { let p1 = libc::realloc(ptr::null_mut(), 20); assert!(!p1.is_null()); - libc::free(p1); } + + unsafe { + let p_too_big = libc::malloc(usize::MAX); + assert!(p_too_big.is_null()); + } } fn test_calloc() { @@ -143,6 +151,9 @@ fn test_calloc() { let slice = slice::from_raw_parts(p4 as *const u8, 4 * 8); assert_eq!(&slice, &[0_u8; 4 * 8]); libc::free(p4); + + let p_too_big = libc::calloc(usize::MAX / 4, 4); + assert!(p_too_big.is_null()); } } diff --git a/src/tools/miri/tests/pass/concurrency/data_race.rs b/src/tools/miri/tests/pass/concurrency/data_race.rs index d31420380a5..34380dfa504 100644 --- a/src/tools/miri/tests/pass/concurrency/data_race.rs +++ b/src/tools/miri/tests/pass/concurrency/data_race.rs @@ -1,6 +1,6 @@ //@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0 -use std::sync::atomic::{fence, AtomicUsize, Ordering}; +use std::sync::atomic::*; use std::thread::spawn; #[derive(Copy, Clone)] @@ -112,9 +112,41 @@ pub fn test_simple_release() { } } +fn test_local_variable_lazy_write() { + static P: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut()); + + // Create the local variable, and initialize it. + // This write happens before the thread is spanwed, so there is no data race. + let mut val: u8 = 0; + + let t1 = std::thread::spawn(|| { + while P.load(Ordering::Relaxed).is_null() { + std::hint::spin_loop(); + } + unsafe { + // Initialize `*P`. + let ptr = P.load(Ordering::Relaxed); + *ptr = 127; + } + }); + + // Actually generate memory for the local variable. + // This is the time its value is actually written to memory: + // that's *after* the thread above was spawned! + // This may hence look like a data race wrt the access in the thread above. + P.store(std::ptr::addr_of_mut!(val), Ordering::Relaxed); + + // Wait for the thread to be done. + t1.join().unwrap(); + + // Read initialized value. + assert_eq!(val, 127); +} + pub fn main() { test_fence_sync(); test_multiple_reads(); test_rmw_no_block(); test_simple_release(); + test_local_variable_lazy_write(); } diff --git a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs index daf75fee8fe..4c0d6f52425 100644 --- a/src/tools/miri/tests/pass/intrinsics/portable-simd.rs +++ b/src/tools/miri/tests/pass/intrinsics/portable-simd.rs @@ -619,7 +619,6 @@ fn simd_intrinsics() { i32x4::from_array([10, 2, 10, 10]) ); assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,); - assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3u32, 1, 0, 2] }), a,); assert_eq!( simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([3u32, 1, 0, 2]) }), a, @@ -629,10 +628,6 @@ fn simd_intrinsics() { i32x4::from_array([4, 2, 1, 10]), ); assert_eq!( - simd_shuffle::<_, _, i32x4>(a, b, const { [7u32, 5, 4, 6] }), - i32x4::from_array([4, 2, 1, 10]), - ); - assert_eq!( simd_shuffle::<_, _, i32x4>(a, b, const { u32x4::from_array([7u32, 5, 4, 6]) }), i32x4::from_array([4, 2, 1, 10]), ); |
