From 34685044f9d6c01a87a05fde9778586079965958 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 9 Aug 2017 18:01:10 -0700 Subject: [PATCH] add a bunch of compile-fail tests for validation --- .../compile-fail/validation_aliasing_mut4.rs | 13 +++++++++++ .../validation_buggy_split_at_mut.rs | 22 +++++++++++++++++++ .../compile-fail/validation_illegal_write.rs | 15 +++++++++++++ .../validation_pointer_smuggling.rs | 20 +++++++++++++++++ tests/compile-fail/validation_recover1.rs | 16 ++++++++++++++ tests/compile-fail/validation_recover2.rs | 14 ++++++++++++ tests/compile-fail/validation_recover3.rs | 15 +++++++++++++ 7 files changed, 115 insertions(+) create mode 100644 tests/compile-fail/validation_aliasing_mut4.rs create mode 100644 tests/compile-fail/validation_buggy_split_at_mut.rs create mode 100644 tests/compile-fail/validation_illegal_write.rs create mode 100644 tests/compile-fail/validation_pointer_smuggling.rs create mode 100644 tests/compile-fail/validation_recover1.rs create mode 100644 tests/compile-fail/validation_recover2.rs create mode 100644 tests/compile-fail/validation_recover3.rs diff --git a/tests/compile-fail/validation_aliasing_mut4.rs b/tests/compile-fail/validation_aliasing_mut4.rs new file mode 100644 index 00000000000..3dac55aeaac --- /dev/null +++ b/tests/compile-fail/validation_aliasing_mut4.rs @@ -0,0 +1,13 @@ +#![allow(unused_variables)] + +mod safe { + use std::cell::Cell; + + // Make sure &mut UnsafeCell also has a lock to it + pub fn safe(x: &mut Cell, y: &i32) {} //~ ERROR: in conflict with lock WriteLock +} + +fn main() { + let x = &mut 0 as *mut _; + unsafe { safe::safe(&mut *(x as *mut _), &*x) }; +} diff --git a/tests/compile-fail/validation_buggy_split_at_mut.rs b/tests/compile-fail/validation_buggy_split_at_mut.rs new file mode 100644 index 00000000000..9e67b2a4ab1 --- /dev/null +++ b/tests/compile-fail/validation_buggy_split_at_mut.rs @@ -0,0 +1,22 @@ +#![allow(unused_variables)] + +mod safe { + use std::slice::from_raw_parts_mut; + + pub fn split_at_mut(self_: &mut [T], mid: usize) -> (&mut [T], &mut [T]) { + let len = self_.len(); + let ptr = self_.as_mut_ptr(); + + unsafe { + assert!(mid <= len); + + (from_raw_parts_mut(ptr, len - mid), // BUG: should be "mid" instead of "len - mid" + from_raw_parts_mut(ptr.offset(mid as isize), len - mid)) + } + } +} + +fn main() { + let mut array = [1,2,3,4]; + let _x = safe::split_at_mut(&mut array, 0); //~ ERROR: in conflict with lock WriteLock +} diff --git a/tests/compile-fail/validation_illegal_write.rs b/tests/compile-fail/validation_illegal_write.rs new file mode 100644 index 00000000000..1432f4cc9f1 --- /dev/null +++ b/tests/compile-fail/validation_illegal_write.rs @@ -0,0 +1,15 @@ +#![allow(unused_variables)] + +mod safe { + pub(crate) fn safe(x: &u32) { + let x : &mut u32 = unsafe { &mut *(x as *const _ as *mut _) }; + *x = 42; //~ ERROR: in conflict with lock ReadLock + } +} + +fn main() { + let target = &mut 42; + let target_ref = ⌖ + // do a reborrow, but we keep the lock + safe::safe(&*target); +} diff --git a/tests/compile-fail/validation_pointer_smuggling.rs b/tests/compile-fail/validation_pointer_smuggling.rs new file mode 100644 index 00000000000..3320d2a89d3 --- /dev/null +++ b/tests/compile-fail/validation_pointer_smuggling.rs @@ -0,0 +1,20 @@ +#![allow(unused_variables)] + +static mut PTR: *mut u8 = 0 as *mut _; + +fn fun1(x: &mut u8) { + unsafe { + PTR = x; + } +} + +fn fun2() { + // Now we use a pointer we are not allowed to use + let _x = unsafe { *PTR }; //~ ERROR: in conflict with lock WriteLock +} + +fn main() { + let mut val = 0; + fun1(&mut val); + fun2(); +} diff --git a/tests/compile-fail/validation_recover1.rs b/tests/compile-fail/validation_recover1.rs new file mode 100644 index 00000000000..55c38a694c5 --- /dev/null +++ b/tests/compile-fail/validation_recover1.rs @@ -0,0 +1,16 @@ +#![allow(unused_variables)] + +#[repr(u32)] +enum Bool { True } + +mod safe { + pub(crate) fn safe(x: &mut super::Bool) { + let x = x as *mut _ as *mut u32; + unsafe { *x = 44; } // out-of-bounds enum discriminant + } +} + +fn main() { + let mut x = Bool::True; + safe::safe(&mut x); //~ ERROR: invalid enum discriminant +} diff --git a/tests/compile-fail/validation_recover2.rs b/tests/compile-fail/validation_recover2.rs new file mode 100644 index 00000000000..756be9fde6f --- /dev/null +++ b/tests/compile-fail/validation_recover2.rs @@ -0,0 +1,14 @@ +#![allow(unused_variables)] + +mod safe { + // This makes a ref that was passed to us via &mut alias with things it should not alias with + pub(crate) fn safe(x: &mut &u32, target: &mut u32) { + unsafe { *x = &mut *(target as *mut _); } + } +} + +fn main() { + let target = &mut 42; + let mut target_alias = &42; // initial dummy value + safe::safe(&mut target_alias, target); //~ ERROR: in conflict with lock ReadLock +} diff --git a/tests/compile-fail/validation_recover3.rs b/tests/compile-fail/validation_recover3.rs new file mode 100644 index 00000000000..afe6fe7c0bb --- /dev/null +++ b/tests/compile-fail/validation_recover3.rs @@ -0,0 +1,15 @@ +#![allow(unused_variables)] + +mod safe { + pub(crate) fn safe(x: *mut u32) { + unsafe { *x = 42; } //~ ERROR: in conflict with lock WriteLock + } +} + +fn main() { + let target = &mut 42u32; + let target2 = target as *mut _; + drop(&mut *target); // reborrow + // Now make sure we still got the lock + safe::safe(target2); +}