about summary refs log tree commit diff
path: root/src/tools/miri/tests
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-09-16 05:06:25 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-09-16 05:06:25 +0000
commit4d824fd5b7101bddd2fdd829e474740838687ead (patch)
tree7e319bfe4e2ca29e601bb7f1c3a1c1ef22faad68 /src/tools/miri/tests
parentffcaa7fddee251f2b7ed2ca62900c2440f25e04f (diff)
parentc16ff44537509ca911ffd3653b17c6187c71831d (diff)
downloadrust-4d824fd5b7101bddd2fdd829e474740838687ead.tar.gz
rust-4d824fd5b7101bddd2fdd829e474740838687ead.zip
Merge from rustc
Diffstat (limited to 'src/tools/miri/tests')
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_alloc_race.rs57
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_alloc_race.stderr20
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_read_race.rs38
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_read_race.stderr20
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_write_race.rs37
-rw-r--r--src/tools/miri/tests/fail/data_race/local_variable_write_race.stderr20
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-mem.rs13
-rw-r--r--src/tools/miri/tests/pass/concurrency/data_race.rs34
-rw-r--r--src/tools/miri/tests/pass/intrinsics/portable-simd.rs5
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]),
         );