reenable some tests that work now, and organize them better with directories
This commit is contained in:
parent
d4b78b36ab
commit
1907782b64
26 changed files with 114 additions and 143 deletions
15
tests/compile-fail/stacked_borrows/alias_through_mutation.rs
Normal file
15
tests/compile-fail/stacked_borrows/alias_through_mutation.rs
Normal 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
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
11
tests/compile-fail/stacked_borrows/illegal_write.rs
Normal file
11
tests/compile-fail/stacked_borrows/illegal_write.rs
Normal 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_ = ⌖
|
||||
evil(ref_); // invalidates shared ref
|
||||
let _x = *ref_; //~ ERROR should be frozen
|
||||
}
|
||||
10
tests/compile-fail/stacked_borrows/illegal_write2.rs
Normal file
10
tests/compile-fail/stacked_borrows/illegal_write2.rs
Normal 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
|
||||
}
|
||||
22
tests/compile-fail/stacked_borrows/pointer_smuggling.rs
Normal file
22
tests/compile-fail/stacked_borrows/pointer_smuggling.rs
Normal 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
|
||||
}
|
||||
21
tests/compile-fail/stacked_borrows/shared_confusion.rs
Normal file
21
tests/compile-fail/stacked_borrows/shared_confusion.rs
Normal 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));
|
||||
}
|
||||
|
|
@ -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 = ⌖
|
||||
// do a reborrow, but we keep the lock
|
||||
safe::safe(&*target);
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
16
tests/compile-fail/validity/transmute_through_ptr.rs
Normal file
16
tests/compile-fail/validity/transmute_through_ptr.rs
Normal 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
|
||||
}
|
||||
12
tests/compile-fail/validity/undef.rs
Normal file
12
tests/compile-fail/validity/undef.rs
Normal 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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue