diff --git a/src/lib.rs b/src/lib.rs index 13b42d8e3c..d52fd00280 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -255,9 +255,26 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> { const STATIC_KIND: Option = Some(MiriMemoryKind::MutStatic); - #[inline(always)] fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool { - ecx.machine.validate + if !ecx.machine.validate { + return false; + } + + // Some functions are whitelisted until we figure out how to fix them. + // We walk up the stack a few frames to also cover their callees. + const WHITELIST: &[&str] = &[ + // Uses mem::uninitialized + "std::ptr::read", + ]; + for frame in ecx.stack().iter() + .rev().take(3) + { + let name = frame.instance.to_string(); + if WHITELIST.iter().any(|white| name.starts_with(white)) { + return false; + } + } + true } /// Returns Ok() when the function was handled, fail otherwise diff --git a/tests/compile-fail/cast_box_int_to_fn_ptr.rs b/tests/compile-fail/cast_box_int_to_fn_ptr.rs index 2a317f579f..cbf370e023 100644 --- a/tests/compile-fail/cast_box_int_to_fn_ptr.rs +++ b/tests/compile-fail/cast_box_int_to_fn_ptr.rs @@ -1,5 +1,5 @@ // Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation fn main() { let b = Box::new(42); diff --git a/tests/compile-fail/cast_int_to_fn_ptr.rs b/tests/compile-fail/cast_int_to_fn_ptr.rs index 29d16e9a42..2a08d9f1f9 100644 --- a/tests/compile-fail/cast_int_to_fn_ptr.rs +++ b/tests/compile-fail/cast_int_to_fn_ptr.rs @@ -1,5 +1,5 @@ // Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation fn main() { let g = unsafe { diff --git a/tests/compile-fail/execute_memory.rs b/tests/compile-fail/execute_memory.rs index bcde13d13e..2f8fea38d8 100644 --- a/tests/compile-fail/execute_memory.rs +++ b/tests/compile-fail/execute_memory.rs @@ -1,5 +1,5 @@ // Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation #![feature(box_syntax)] diff --git a/tests/compile-fail/fn_ptr_offset.rs b/tests/compile-fail/fn_ptr_offset.rs index 0c0590e375..e6d1da1e07 100644 --- a/tests/compile-fail/fn_ptr_offset.rs +++ b/tests/compile-fail/fn_ptr_offset.rs @@ -1,5 +1,5 @@ // Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation use std::mem; diff --git a/tests/compile-fail/invalid_bool.rs b/tests/compile-fail/invalid_bool.rs index 49328ef5d7..af4ad67a4f 100644 --- a/tests/compile-fail/invalid_bool.rs +++ b/tests/compile-fail/invalid_bool.rs @@ -1,9 +1,3 @@ -//ignore-test FIXME: do some basic validation of invariants for all values in flight -//This does currently not get caught becuase it compiles to SwitchInt, which -//has no knowledge about data invariants. - fn main() { - let b = unsafe { std::mem::transmute::(2) }; - if b { unreachable!() } else { unreachable!() } //~ ERROR constant evaluation error - //~^ NOTE invalid boolean value read + let _b = unsafe { std::mem::transmute::(2) }; //~ ERROR encountered 2, but expected something in the range 0..=1 } diff --git a/tests/compile-fail/invalid_bool2.rs b/tests/compile-fail/invalid_bool2.rs index 47c4e8b410..2348c62559 100644 --- a/tests/compile-fail/invalid_bool2.rs +++ b/tests/compile-fail/invalid_bool2.rs @@ -1,3 +1,6 @@ +// Validation makes this fail in the wrong place +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation + fn main() { let b = unsafe { std::mem::transmute::(2) }; let _x = b == true; //~ ERROR invalid boolean value read diff --git a/tests/compile-fail/invalid_char.rs b/tests/compile-fail/invalid_char.rs new file mode 100644 index 0000000000..3ff0ed60f6 --- /dev/null +++ b/tests/compile-fail/invalid_char.rs @@ -0,0 +1,8 @@ +fn main() { + assert!(std::char::from_u32(-1_i32 as u32).is_none()); + let _ = match unsafe { std::mem::transmute::(-1) } { //~ ERROR encountered 4294967295, but expected something in the range 0..=1114111 + 'a' => {true}, + 'b' => {false}, + _ => {true}, + }; +} diff --git a/tests/compile-fail/match_char2.rs b/tests/compile-fail/invalid_char2.rs similarity index 65% rename from tests/compile-fail/match_char2.rs rename to tests/compile-fail/invalid_char2.rs index 786dd813a1..5de2d073f3 100644 --- a/tests/compile-fail/match_char2.rs +++ b/tests/compile-fail/invalid_char2.rs @@ -1,3 +1,6 @@ +// Validation makes this fail in the wrong place +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation + fn main() { assert!(std::char::from_u32(-1_i32 as u32).is_none()); let c = unsafe { std::mem::transmute::(-1) }; diff --git a/tests/compile-fail/invalid_enum_discriminant.rs b/tests/compile-fail/invalid_enum_discriminant.rs index 94c100b9ef..543a797d44 100644 --- a/tests/compile-fail/invalid_enum_discriminant.rs +++ b/tests/compile-fail/invalid_enum_discriminant.rs @@ -1,17 +1,8 @@ -// Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 - #[repr(C)] pub enum Foo { A, B, C, D } fn main() { - let f = unsafe { std::mem::transmute::(42) }; - match f { - Foo::A => {}, //~ ERROR invalid enum discriminant - Foo::B => {}, - Foo::C => {}, - Foo::D => {}, - } + let _f = unsafe { std::mem::transmute::(42) }; //~ ERROR encountered invalid enum discriminant 42 } diff --git a/tests/compile-fail/invalid_enum_discriminant2.rs b/tests/compile-fail/invalid_enum_discriminant2.rs index 5a5a20c486..ea94081693 100644 --- a/tests/compile-fail/invalid_enum_discriminant2.rs +++ b/tests/compile-fail/invalid_enum_discriminant2.rs @@ -1,5 +1,5 @@ // Validation makes this fail in the wrong place -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation // error-pattern: invalid enum discriminant diff --git a/tests/compile-fail/match_char.rs b/tests/compile-fail/match_char.rs deleted file mode 100644 index e7fee1e3e3..0000000000 --- a/tests/compile-fail/match_char.rs +++ /dev/null @@ -1,13 +0,0 @@ -//ignore-test FIXME: do some basic validation of invariants for all values in flight -//This does currently not get caught becuase it compiles to SwitchInt, which -//has no knowledge about data invariants. - -fn main() { - assert!(std::char::from_u32(-1_i32 as u32).is_none()); - let _ = match unsafe { std::mem::transmute::(-1) } { //~ ERROR constant evaluation error - //~^ NOTE tried to interpret an invalid 32-bit value as a char: 4294967295 - 'a' => {true}, - 'b' => {false}, - _ => {true}, - }; -} diff --git a/tests/compile-fail/never_say_never.rs b/tests/compile-fail/never_say_never.rs index fd76ecbd15..9821723deb 100644 --- a/tests/compile-fail/never_say_never.rs +++ b/tests/compile-fail/never_say_never.rs @@ -1,5 +1,5 @@ // This should fail even without validation -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation #![feature(never_type)] #![allow(unreachable_code)] diff --git a/tests/compile-fail/never_transmute_humans.rs b/tests/compile-fail/never_transmute_humans.rs index 7652cdfdd3..c5c53d4231 100644 --- a/tests/compile-fail/never_transmute_humans.rs +++ b/tests/compile-fail/never_transmute_humans.rs @@ -1,5 +1,5 @@ // This should fail even without validation -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation #![feature(never_type)] #![allow(unreachable_code)] diff --git a/tests/compile-fail/never_transmute_void.rs b/tests/compile-fail/never_transmute_void.rs index 9329cd3659..11fc0f068d 100644 --- a/tests/compile-fail/never_transmute_void.rs +++ b/tests/compile-fail/never_transmute_void.rs @@ -1,5 +1,5 @@ // This should fail even without validation -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation #![feature(never_type)] #![allow(unreachable_code)] diff --git a/tests/compile-fail/reference_to_packed.rs b/tests/compile-fail/reference_to_packed.rs index 946a6b89a7..d18f314c8a 100644 --- a/tests/compile-fail/reference_to_packed.rs +++ b/tests/compile-fail/reference_to_packed.rs @@ -1,5 +1,5 @@ // This should fail even without validation -// compile-flags: -Zmir-emit-validate=0 +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation #![allow(dead_code, unused_variables)] diff --git a/tests/compile-fail/storage_dead_dangling.rs b/tests/compile-fail/storage_dead_dangling.rs index 6abae2069f..69917dce85 100644 --- a/tests/compile-fail/storage_dead_dangling.rs +++ b/tests/compile-fail/storage_dead_dangling.rs @@ -1,3 +1,6 @@ +// This should fail even without validation +// compile-flags: -Zmir-emit-validate=0 -Zmiri-disable-validation + static mut LEAK: usize = 0; fn fill(v: &mut i32) { diff --git a/tests/compile-fail/validation_cast_fn_ptr1.rs b/tests/compile-fail/validation_cast_fn_ptr1.rs new file mode 100644 index 0000000000..82f2d10ee4 --- /dev/null +++ b/tests/compile-fail/validation_cast_fn_ptr1.rs @@ -0,0 +1,10 @@ +fn main() { + // Cast a function pointer such that on a call, the argument gets transmuted + // from raw ptr to reference. This is ABI-compatible, so it's not the call that + // should fail, but validation should. + fn f(_x: &i32) { } + + let g: fn(*const i32) = unsafe { std::mem::transmute(f as fn(&i32)) }; + + g(0usize as *const i32) //~ ERROR encountered 0, but expected something greater or equal to 1 +} diff --git a/tests/compile-fail/validation_cast_fn_ptr2.rs b/tests/compile-fail/validation_cast_fn_ptr2.rs new file mode 100644 index 0000000000..2f3b91a53e --- /dev/null +++ b/tests/compile-fail/validation_cast_fn_ptr2.rs @@ -0,0 +1,10 @@ +fn main() { + // Cast a function pointer such that when returning, the return value gets transmuted + // from raw ptr to reference. This is ABI-compatible, so it's not the call that + // should fail, but validation should. + fn f() -> *const i32 { 0usize as *const i32 } + + let g: fn() -> &'static i32 = unsafe { std::mem::transmute(f as fn() -> *const i32) }; + + let _x = g(); //~ ERROR encountered 0, but expected something greater or equal to 1 +} diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 43989a49b3..82a2144a33 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -64,7 +64,6 @@ fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, need_fullm flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs config.src_base = PathBuf::from(path.to_string()); flags.push("-Zmir-emit-validate=1".to_owned()); - flags.push("-Zmiri-disable-validation".to_owned()); config.target_rustcflags = Some(flags.join(" ")); config.target = target.to_owned(); config.host = host.to_owned(); @@ -103,8 +102,6 @@ fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir: flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs if have_fullmir() { flags.push("-Zmiri-start-fn".to_owned()); - // start-fn uses ptr::read, and so fails validation - flags.push("-Zmiri-disable-validation".to_owned()); } if opt { flags.push("-Zmir-opt-level=3".to_owned()); diff --git a/tests/run-pass/call_drop_through_owned_slice.rs b/tests/run-pass/call_drop_through_owned_slice.rs index b0e336c048..3ec6be65ed 100644 --- a/tests/run-pass/call_drop_through_owned_slice.rs +++ b/tests/run-pass/call_drop_through_owned_slice.rs @@ -1,6 +1,3 @@ -// FIXME validation disabled because ptr::read uses mem::uninitialized -// compile-flags: -Zmiri-disable-validation - struct Bar; static mut DROP_COUNT: usize = 0; diff --git a/tests/run-pass/issue-29746.rs b/tests/run-pass/issue-29746.rs index 94ca146db1..61c601ac6a 100644 --- a/tests/run-pass/issue-29746.rs +++ b/tests/run-pass/issue-29746.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME validation disabled because ptr::read uses mem::uninitialized -// compile-flags: -Zmiri-disable-validation - // zip!(a1,a2,a3,a4) is equivalent to: // a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4)) macro_rules! zip { diff --git a/tests/run-pass/sendable-class.rs b/tests/run-pass/sendable-class.rs index 7ca4e1a908..66f0c84e23 100644 --- a/tests/run-pass/sendable-class.rs +++ b/tests/run-pass/sendable-class.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME validation disabled because ptr::read uses mem::uninitialized -// compile-flags: -Zmiri-disable-validation - // Test that a class with only sendable fields can be sent use std::sync::mpsc::channel; diff --git a/tests/run-pass/unique-send.rs b/tests/run-pass/unique-send.rs index 8a48d331f4..7644da08e4 100644 --- a/tests/run-pass/unique-send.rs +++ b/tests/run-pass/unique-send.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// FIXME validation disabled because ptr::read uses mem::uninitialized -// compile-flags: -Zmiri-disable-validation - #![feature(box_syntax)] use std::sync::mpsc::channel;