reenable some tests that work now, and organize them better with directories

This commit is contained in:
Ralf Jung 2018-10-17 16:55:59 +02:00
parent d4b78b36ab
commit 1907782b64
26 changed files with 114 additions and 143 deletions

View file

@ -0,0 +1,15 @@
#![allow(unused_variables)]
// This makes a ref that was passed to us via &mut alias with things it should not alias with
fn retarget(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
retarget(&mut target_alias, target);
// now `target_alias` points to the same thing as `target`
*target = 13;
let _val = *target_alias; //~ ERROR should be frozen
}

View file

@ -1,22 +1,17 @@
// ignore-test validation_op is disabled
#![allow(unused_variables)]
// For some reason, the error location is different when using fullmir
// error-pattern: in conflict with lock WriteLock
mod safe {
use std::slice::from_raw_parts_mut;
pub fn as_mut_slice<T>(self_: &Vec<T>) -> &mut [T] {
unsafe {
from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len())
from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) //~ ERROR shared borrow for mutation
}
}
}
fn main() {
let v = vec![0,1,2];
let v1_ = safe::as_mut_slice(&v);
let v2_ = safe::as_mut_slice(&v);
let v1 = safe::as_mut_slice(&v);
let v2 = safe::as_mut_slice(&v);
}

View file

@ -1,5 +1,3 @@
// ignore-test validation_op is disabled
#![allow(unused_variables)]
mod safe {
@ -20,5 +18,7 @@ mod safe {
fn main() {
let mut array = [1,2,3,4];
let _x = safe::split_at_mut(&mut array, 0); //~ ERROR: in conflict with lock WriteLock
let (a, b) = safe::split_at_mut(&mut array, 0);
a[1] = 5; //~ ERROR does not exist on the stack
b[1] = 6;
}

View file

@ -0,0 +1,11 @@
fn evil(x: &u32) {
let x : &mut u32 = unsafe { &mut *(x as *const _ as *mut _) };
*x = 42; // mutating shared ref without `UnsafeCell`
}
fn main() {
let target = 42;
let ref_ = &target;
evil(ref_); // invalidates shared ref
let _x = *ref_; //~ ERROR should be frozen
}

View file

@ -0,0 +1,10 @@
#![allow(unused_variables)]
fn main() {
let target = &mut 42;
let target2 = target as *mut _;
drop(&mut *target); // reborrow
// Now make sure our ref is still the only one
unsafe { *target2 = 13; } // invalidate our ref
let _val = *target; //~ ERROR does not exist on the stack
}

View file

@ -0,0 +1,22 @@
#![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 };
}
fn main() {
let val = &mut 0; // FIXME: This should also work with a local variable, but currently it does not.
fun1(val);
*val = 2; // this invalidates any raw ptrs `fun1` might have created.
fun2(); // if they now use a raw ptr they break our reference
*val = 3; //~ ERROR does not exist on the stack
}

View file

@ -0,0 +1,21 @@
#![allow(unused_variables)]
use std::cell::RefCell;
fn test(r: &mut RefCell<i32>) {
let x = &*r; // not freezing because interior mutability
let mut x_ref = x.borrow_mut();
let x_inner : &mut i32 = &mut *x_ref; // Uniq reference
let x_evil = x_inner as *mut _;
{
let x_inner_shr = &*x_inner; // frozen
let y = &*r; // outer ref, not freezing
let x_inner_shr2 = &*x_inner; // freezing again
}
// Our old raw should be dead by now
unsafe { *x_evil = 0; } // this falls back to some Raw higher up the stack
*x_inner = 12; //~ ERROR does not exist on the stack
}
fn main() {
test(&mut RefCell::new(0));
}

View file

@ -1,17 +0,0 @@
// ignore-test validation_op is disabled
#![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 = &target;
// do a reborrow, but we keep the lock
safe::safe(&*target);
}

View file

@ -1,26 +0,0 @@
// ignore-test validation_op is disabled
// Make sure validation can handle many overlapping shared borrows for different parts of a data structure
#![allow(unused_variables)]
use std::cell::RefCell;
fn evil(x: *mut i32) {
unsafe { *x = 0; } //~ ERROR: in conflict with lock WriteLock
}
fn test(r: &mut RefCell<i32>) {
let x = &*r; // releasing write lock, first suspension recorded
let mut x_ref = x.borrow_mut();
let x_inner : &mut i32 = &mut *x_ref; // new inner write lock, with same lifetime as outer lock
{
let x_inner_shr = &*x_inner; // releasing inner write lock, recording suspension
let y = &*r; // second suspension for the outer write lock
let x_inner_shr2 = &*x_inner; // 2nd suspension for inner write lock
}
// If the two locks are mixed up, here we should have a write lock, but we do not.
evil(x_inner as *mut _);
}
fn main() {
test(&mut RefCell::new(0));
}

View file

@ -1,22 +0,0 @@
// ignore-test validation_op is disabled
#![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();
}

View file

@ -1,18 +0,0 @@
// ignore-test validation_op is disabled
#![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
}

View file

@ -1,16 +0,0 @@
// ignore-test validation_op is disabled
#![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
}

View file

@ -1,17 +0,0 @@
// ignore-test validation_op is disabled
#![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);
}

View file

@ -1,16 +0,0 @@
// ignore-test validation_op is disabled
#![allow(unused_variables)]
// error-pattern: attempted to read undefined bytes
mod safe {
use std::mem;
pub(crate) fn make_float() -> f32 {
unsafe { mem::uninitialized() }
}
}
fn main() {
let _x = safe::make_float();
}

View file

@ -0,0 +1,16 @@
#![allow(unused_variables)]
#[repr(u32)]
enum Bool { True }
fn evil(x: &mut Bool) {
let x = x as *mut _ as *mut u32;
unsafe { *x = 44; } // out-of-bounds enum discriminant
}
fn main() {
let mut x = Bool::True;
evil(&mut x);
let _y = x; // reading this ought to be enough to trigger validation
//~^ ERROR invalid enum discriminant 44
}

View file

@ -0,0 +1,12 @@
#![allow(unused_variables)]
// error-pattern: encountered undefined data in pointer
use std::mem;
fn make_raw() -> *const f32 {
unsafe { mem::uninitialized() }
}
fn main() {
let _x = make_raw();
}

View file

@ -63,6 +63,7 @@ fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, need_fullm
flags.push(format!("--sysroot {}", sysroot.display()));
flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
config.src_base = PathBuf::from(path.to_string());
flags.push("-Zmir-opt-level=0".to_owned()); // optimization circumvents some stacked borrow checks
flags.push("-Zmir-emit-validate=1".to_owned());
config.target_rustcflags = Some(flags.join(" "));
config.target = target.to_owned();