Auto merge of #2314 - RalfJung:unsized, r=RalfJung
adjust for removed unsized_locals The Miri side of https://github.com/rust-lang/rust/pull/98831
This commit is contained in:
commit
64dec227bd
@ -1 +1 @@
|
|||||||
7665c3543079ebc3710b676d0fd6951bedfd4b29
|
8824d131619e58a38bde8bcf56401629b91a204a
|
||||||
|
@ -169,7 +169,7 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
write!(f, "{:?}", sb)?;
|
write!(f, "{:?}", sb)?;
|
||||||
}
|
}
|
||||||
Tag::Wildcard => {
|
Tag::Wildcard => {
|
||||||
write!(f, "[Wildcard]")?;
|
write!(f, "[wildcard]")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,11 +35,13 @@ fn binary_ptr_op(
|
|||||||
Immediate::Scalar(l) => (l.check_init()?.to_bits(size)?, 0),
|
Immediate::Scalar(l) => (l.check_init()?.to_bits(size)?, 0),
|
||||||
Immediate::ScalarPair(l1, l2) =>
|
Immediate::ScalarPair(l1, l2) =>
|
||||||
(l1.check_init()?.to_bits(size)?, l2.check_init()?.to_bits(size)?),
|
(l1.check_init()?.to_bits(size)?, l2.check_init()?.to_bits(size)?),
|
||||||
|
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
|
||||||
};
|
};
|
||||||
let right = match **right {
|
let right = match **right {
|
||||||
Immediate::Scalar(r) => (r.check_init()?.to_bits(size)?, 0),
|
Immediate::Scalar(r) => (r.check_init()?.to_bits(size)?, 0),
|
||||||
Immediate::ScalarPair(r1, r2) =>
|
Immediate::ScalarPair(r1, r2) =>
|
||||||
(r1.check_init()?.to_bits(size)?, r2.check_init()?.to_bits(size)?),
|
(r1.check_init()?.to_bits(size)?, r2.check_init()?.to_bits(size)?),
|
||||||
|
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
|
||||||
};
|
};
|
||||||
let res = match bin_op {
|
let res = match bin_op {
|
||||||
Eq => left == right,
|
Eq => left == right,
|
||||||
|
@ -68,12 +68,12 @@ fn call_intrinsic(
|
|||||||
"volatile_load" => {
|
"volatile_load" => {
|
||||||
let [place] = check_arg_count(args)?;
|
let [place] = check_arg_count(args)?;
|
||||||
let place = this.deref_operand(place)?;
|
let place = this.deref_operand(place)?;
|
||||||
this.copy_op(&place.into(), dest)?;
|
this.copy_op(&place.into(), dest, /*allow_transmute*/ false)?;
|
||||||
}
|
}
|
||||||
"volatile_store" => {
|
"volatile_store" => {
|
||||||
let [place, dest] = check_arg_count(args)?;
|
let [place, dest] = check_arg_count(args)?;
|
||||||
let place = this.deref_operand(place)?;
|
let place = this.deref_operand(place)?;
|
||||||
this.copy_op(dest, &place.into())?;
|
this.copy_op(dest, &place.into(), /*allow_transmute*/ false)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"write_bytes" | "volatile_set_memory" => {
|
"write_bytes" | "volatile_set_memory" => {
|
||||||
|
25
tests/fail/data_race/stack_pop_race.rs
Normal file
25
tests/fail/data_race/stack_pop_race.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// ignore-windows: Concurrency on Windows is not supported yet.
|
||||||
|
// compile-flags: -Zmiri-preemption-rate=0
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
struct MakeSend(*const i32);
|
||||||
|
unsafe impl Send for MakeSend {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
race(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Using an argument for the ptr to point to, since those do not get StorageDead.
|
||||||
|
fn race(local: i32) {
|
||||||
|
let ptr = MakeSend(&local as *const i32);
|
||||||
|
thread::spawn(move || {
|
||||||
|
let ptr = ptr;
|
||||||
|
let _val = unsafe { *ptr.0 };
|
||||||
|
});
|
||||||
|
// Make the other thread go first so that it does not UAF.
|
||||||
|
thread::yield_now();
|
||||||
|
// Deallocating the local (when `main` returns)
|
||||||
|
// races with the read in the other thread.
|
||||||
|
// Make sure the error points at this function's end, not just the call site.
|
||||||
|
} //~ERROR Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>`
|
20
tests/fail/data_race/stack_pop_race.stderr
Normal file
20
tests/fail/data_race/stack_pop_race.stderr
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
error: Undefined Behavior: Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
|
||||||
|
--> $DIR/stack_pop_race.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | }
|
||||||
|
| ^ Data race detected between Deallocate on thread `main` and Read on thread `<unnamed>` at ALLOC
|
||||||
|
|
|
||||||
|
= 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 `race` at $DIR/stack_pop_race.rs:LL:CC
|
||||||
|
note: inside `main` at $DIR/stack_pop_race.rs:LL:CC
|
||||||
|
--> $DIR/stack_pop_race.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | race(0);
|
||||||
|
| ^^^^^^^
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
23
tests/fail/unsized-local.rs
Normal file
23
tests/fail/unsized-local.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#![feature(unsized_locals)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pub trait Foo {
|
||||||
|
fn foo(self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct A;
|
||||||
|
|
||||||
|
impl Foo for A {
|
||||||
|
fn foo(self) -> String {
|
||||||
|
format!("hello")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = *(Box::new(A) as Box<dyn Foo>); //~ERROR unsized locals are not supported
|
||||||
|
assert_eq!(x.foo(), format!("hello"));
|
||||||
|
|
||||||
|
// I'm not sure whether we want this to work
|
||||||
|
let x = Box::new(A) as Box<dyn Foo>;
|
||||||
|
assert_eq!(x.foo(), format!("hello"));
|
||||||
|
}
|
14
tests/fail/unsized-local.stderr
Normal file
14
tests/fail/unsized-local.stderr
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
error: unsupported operation: unsized locals are not supported
|
||||||
|
--> $DIR/unsized-local.rs:LL:CC
|
||||||
|
|
|
||||||
|
LL | let x = *(Box::new(A) as Box<dyn Foo>);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsized locals are not supported
|
||||||
|
|
|
||||||
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
|
||||||
|
= note: backtrace:
|
||||||
|
= note: inside `main` at $DIR/unsized-local.rs:LL:CC
|
||||||
|
|
||||||
|
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
@ -1,6 +1,3 @@
|
|||||||
#![feature(unsized_locals, unsized_fn_params)]
|
|
||||||
#![allow(incomplete_features)]
|
|
||||||
|
|
||||||
fn ref_box_dyn() {
|
fn ref_box_dyn() {
|
||||||
struct Struct(i32);
|
struct Struct(i32);
|
||||||
|
|
||||||
@ -75,6 +72,9 @@ fn new(w: Box<dyn MyTrait + 'static>) -> Whatever {
|
|||||||
assert!(unsafe { DROPPED });
|
assert!(unsafe { DROPPED });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Disabled for now: unsized locals are not supported,
|
||||||
|
// their current MIR encoding is just not great.
|
||||||
|
/*
|
||||||
fn unsized_dyn() {
|
fn unsized_dyn() {
|
||||||
pub trait Foo {
|
pub trait Foo {
|
||||||
fn foo(self) -> String;
|
fn foo(self) -> String;
|
||||||
@ -95,7 +95,6 @@ fn foo(self) -> String {
|
|||||||
let x = Box::new(A) as Box<dyn Foo>;
|
let x = Box::new(A) as Box<dyn Foo>;
|
||||||
assert_eq!(x.foo(), format!("hello"));
|
assert_eq!(x.foo(), format!("hello"));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unsized_dyn_autoderef() {
|
fn unsized_dyn_autoderef() {
|
||||||
pub trait Foo {
|
pub trait Foo {
|
||||||
fn foo(self) -> String;
|
fn foo(self) -> String;
|
||||||
@ -140,12 +139,9 @@ fn foo(mut self) -> String {
|
|||||||
let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
|
let x = Box::new(|| "hello".to_owned()) as Box<dyn FnMut() -> String>;
|
||||||
assert_eq!(&x.foo() as &str, "hello");
|
assert_eq!(&x.foo() as &str, "hello");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
ref_box_dyn();
|
ref_box_dyn();
|
||||||
box_box_trait();
|
box_box_trait();
|
||||||
|
|
||||||
// "exotic" receivers
|
|
||||||
unsized_dyn();
|
|
||||||
unsized_dyn_autoderef();
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// If we are careful, we can exploit data layout...
|
// If we are careful, we can exploit data layout...
|
||||||
|
// This is a tricky case since we are transmuting a ScalarPair type to a non-ScalarPair type.
|
||||||
let raw = unsafe { std::mem::transmute::<&[u8], [*const u8; 2]>(&[42]) };
|
let raw = unsafe { std::mem::transmute::<&[u8], [*const u8; 2]>(&[42]) };
|
||||||
let ptr: *const u8 = unsafe { std::mem::transmute_copy(&raw) };
|
let ptr: *const u8 = unsafe { std::mem::transmute_copy(&raw) };
|
||||||
assert_eq!(unsafe { *ptr }, 42);
|
assert_eq!(unsafe { *ptr }, 42);
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#![feature(unsized_tuple_coercion)]
|
|
||||||
use std::mem;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let x: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
|
||||||
let y: &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
|
|
||||||
let mut a = [y, x];
|
|
||||||
a.sort();
|
|
||||||
assert_eq!(a, [x, y]);
|
|
||||||
|
|
||||||
assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
|
|
||||||
assert_eq!(mem::size_of_val(x), 16);
|
|
||||||
}
|
|
36
tests/pass/unsized.rs
Normal file
36
tests/pass/unsized.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#![feature(unsized_tuple_coercion)]
|
||||||
|
#![feature(unsized_fn_params)]
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
fn unsized_tuple() {
|
||||||
|
let x: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
|
||||||
|
let y: &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
|
||||||
|
let mut a = [y, x];
|
||||||
|
a.sort();
|
||||||
|
assert_eq!(a, [x, y]);
|
||||||
|
|
||||||
|
assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
|
||||||
|
assert_eq!(mem::size_of_val(x), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsized_params() {
|
||||||
|
pub fn f0(_f: dyn FnOnce()) {}
|
||||||
|
pub fn f1(_s: str) {}
|
||||||
|
pub fn f2(_x: i32, _y: [i32]) {}
|
||||||
|
pub fn f3(_p: dyn Send) {}
|
||||||
|
|
||||||
|
let c: Box<dyn FnOnce()> = Box::new(|| {});
|
||||||
|
f0(*c);
|
||||||
|
let foo = "foo".to_string().into_boxed_str();
|
||||||
|
f1(*foo);
|
||||||
|
let sl: Box<[i32]> = [0, 1, 2].to_vec().into_boxed_slice();
|
||||||
|
f2(5, *sl);
|
||||||
|
let p: Box<dyn Send> = Box::new((1, 2));
|
||||||
|
f3(*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsized_tuple();
|
||||||
|
unsized_params();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user