ensure atomics happen on mutable allocations, and fix futex test
This commit is contained in:
parent
d630671a33
commit
cd2edbfd09
@ -46,6 +46,7 @@
|
||||
mem,
|
||||
};
|
||||
|
||||
use rustc_ast::Mutability;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_middle::{mir, ty::layout::TyAndLayout};
|
||||
@ -476,6 +477,17 @@ fn atomic_access_check(&self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResul
|
||||
align,
|
||||
CheckInAllocMsg::MemoryAccessTest,
|
||||
)?;
|
||||
// Ensure the allocation is mutable. Even failing (read-only) compare_exchange need mutable
|
||||
// memory on many targets (i.e., they segfault if taht memory is mapped read-only), and
|
||||
// atomic loads can be implemented via compare_exchange on some targets. See
|
||||
// <https://github.com/rust-lang/miri/issues/2463>.
|
||||
// We avoid `get_ptr_alloc` since we do *not* want to run the access hooks -- the actual
|
||||
// access will happen later.
|
||||
let (alloc_id, _offset, _prov) =
|
||||
this.ptr_try_get_alloc_id(place.ptr).expect("there are no zero-sized atomic accesses");
|
||||
if this.get_alloc_mutability(alloc_id)? == Mutability::Not {
|
||||
throw_ub_format!("atomic operations cannot be performed on read-only memory");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
11
tests/fail/concurrency/read_only_atomic_cmpxchg.rs
Normal file
11
tests/fail/concurrency/read_only_atomic_cmpxchg.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Should not rely on the aliasing model for its failure.
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows
|
||||
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
fn main() {
|
||||
static X: i32 = 0;
|
||||
let x = &X as *const i32 as *const AtomicI32;
|
||||
let x = unsafe { &*x };
|
||||
x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err(); //~ERROR: atomic operations cannot be performed on read-only memory
|
||||
}
|
15
tests/fail/concurrency/read_only_atomic_cmpxchg.stderr
Normal file
15
tests/fail/concurrency/read_only_atomic_cmpxchg.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: atomic operations cannot be performed on read-only memory
|
||||
--> $DIR/read_only_atomic_cmpxchg.rs:LL:CC
|
||||
|
|
||||
LL | x.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed).unwrap_err();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory
|
||||
|
|
||||
= 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 `main` at $DIR/read_only_atomic_cmpxchg.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
13
tests/fail/concurrency/read_only_atomic_load.rs
Normal file
13
tests/fail/concurrency/read_only_atomic_load.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// Should not rely on the aliasing model for its failure.
|
||||
//@compile-flags: -Zmiri-disable-stacked-borrows
|
||||
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
fn main() {
|
||||
static X: i32 = 0;
|
||||
let x = &X as *const i32 as *const AtomicI32;
|
||||
let x = unsafe { &*x };
|
||||
// Some targets can implement atomic loads via compare_exchange, so we cannot allow them on
|
||||
// read-only memory.
|
||||
x.load(Ordering::Relaxed); //~ERROR: atomic operations cannot be performed on read-only memory
|
||||
}
|
15
tests/fail/concurrency/read_only_atomic_load.stderr
Normal file
15
tests/fail/concurrency/read_only_atomic_load.stderr
Normal file
@ -0,0 +1,15 @@
|
||||
error: Undefined Behavior: atomic operations cannot be performed on read-only memory
|
||||
--> $DIR/read_only_atomic_load.rs:LL:CC
|
||||
|
|
||||
LL | x.load(Ordering::Relaxed);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ atomic operations cannot be performed on read-only memory
|
||||
|
|
||||
= 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 `main` at $DIR/read_only_atomic_load.rs:LL:CC
|
||||
|
||||
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -130,7 +130,7 @@ fn wait_absolute_timeout() {
|
||||
fn wait_wake() {
|
||||
let start = Instant::now();
|
||||
|
||||
static FUTEX: i32 = 0;
|
||||
static mut FUTEX: i32 = 0;
|
||||
|
||||
let t = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
@ -167,7 +167,7 @@ fn wait_wake() {
|
||||
fn wait_wake_bitset() {
|
||||
let start = Instant::now();
|
||||
|
||||
static FUTEX: i32 = 0;
|
||||
static mut FUTEX: i32 = 0;
|
||||
|
||||
let t = thread::spawn(move || {
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
@ -277,8 +277,8 @@ fn concurrent_wait_wake() {
|
||||
|
||||
// Make sure we got the interesting case (of having woken a thread) at least once, but not *each* time.
|
||||
let woken = WOKEN.load(Ordering::Relaxed);
|
||||
assert!(woken > 0 && woken < rounds);
|
||||
//eprintln!("waking happened {woken} times");
|
||||
assert!(woken > 0 && woken < rounds);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
Loading…
Reference in New Issue
Block a user