310 lines
11 KiB
Rust
310 lines
11 KiB
Rust
//@ check-fail
|
|
|
|
extern "C" {
|
|
// N.B., mutability can be easily incorrect in FFI calls -- as
|
|
// in C, the default is mutable pointers.
|
|
fn ffi(c: *mut u8);
|
|
fn int_ffi(c: *mut i32);
|
|
}
|
|
|
|
fn static_u8() -> &'static u8 {
|
|
&8
|
|
}
|
|
|
|
unsafe fn ref_to_mut() {
|
|
let num = &3i32;
|
|
|
|
let _num = &mut *(num as *const i32 as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(num as *const i32).cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *std::ptr::from_ref(num).cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *std::ptr::from_ref({ num }).cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(num as *const i32).cast::<i32>().cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(num as *const i32).cast::<i32>().cast_mut().cast_const().cast_mut();
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i8);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *std::mem::transmute::<_, *mut i32>(num);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(std::mem::transmute::<_, *mut i32>(num) as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *std::cell::UnsafeCell::raw_get(
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
num as *const i32 as *const std::cell::UnsafeCell<i32>
|
|
);
|
|
|
|
let deferred = num as *const i32 as *mut i32;
|
|
let _num = &mut *deferred;
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
|
|
let _num = &mut *deferred;
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let deferred_rebind = deferred;
|
|
let _num = &mut *deferred_rebind;
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(num as *const _ as usize as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
let _num = &mut *(std::mem::transmute::<_, *mut _>(num as *const i32) as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
|
|
static NUM: &'static i32 = &2;
|
|
let num = NUM as *const i32 as *mut i32;
|
|
let num = num;
|
|
let num = num;
|
|
let _num = &mut *num;
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
|
|
let cell = &std::cell::UnsafeCell::new(0);
|
|
let _num = &mut *(cell as *const _ as *mut i32);
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
|
|
unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T {
|
|
&mut *((this as *const _) as *mut _)
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
}
|
|
|
|
fn as_mut<T>(x: &T) -> &mut T {
|
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
}
|
|
|
|
fn as_mut_i32(x: &i32) -> &mut i32 {
|
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
|
//~^ ERROR casting `&T` to `&mut T` is undefined behavior
|
|
}
|
|
}
|
|
|
|
unsafe fn assign_to_ref() {
|
|
let s = String::from("Hello");
|
|
let a = &s;
|
|
let num = &3i32;
|
|
|
|
*(a as *const _ as *mut _) = String::from("Replaced");
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*(a as *const _ as *mut String) += " world";
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*std::ptr::from_ref(num).cast_mut() += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*std::ptr::from_ref({ num }).cast_mut() += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*{ std::ptr::from_ref(num) }.cast_mut() += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*(std::ptr::from_ref({ num }) as *mut i32) += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*std::mem::transmute::<_, *mut i32>(num) += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*(std::mem::transmute::<_, *mut i32>(num) as *mut i32) += 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
std::ptr::write(
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
std::mem::transmute::<*const i32, *mut i32>(num),
|
|
-1i32,
|
|
);
|
|
*((&std::cell::UnsafeCell::new(0)) as *const _ as *mut i32) = 5;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
|
|
let value = num as *const i32 as *mut i32;
|
|
*value = 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
let value = num as *const i32;
|
|
let value = value as *mut i32;
|
|
*value = 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
let value = num as *const i32 as *mut i32;
|
|
*value = 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
let value_rebind = value;
|
|
*value_rebind = 1;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*(num as *const i32).cast::<i32>().cast_mut() = 2;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
*(num as *const _ as usize as *mut i32) = 2;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
std::ptr::write(value, 2);
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
std::ptr::write_unaligned(value, 2);
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
std::ptr::write_volatile(value, 2);
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
|
|
unsafe fn generic_assign_to_ref<T>(this: &T, a: T) {
|
|
*(this as *const _ as *mut _) = a;
|
|
//~^ ERROR assigning to `&T` is undefined behavior
|
|
}
|
|
}
|
|
|
|
#[repr(align(16))]
|
|
struct I64(i64);
|
|
|
|
#[repr(C)]
|
|
struct Mat3<T> {
|
|
a: Vec3<T>,
|
|
b: Vec3<T>,
|
|
c: Vec3<T>,
|
|
}
|
|
|
|
#[repr(C)]
|
|
struct Vec3<T>(T, T, T);
|
|
|
|
unsafe fn bigger_layout() {
|
|
{
|
|
let num = &mut 3i32;
|
|
|
|
let _num = &*(num as *const i32 as *const i64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
let _num = &mut *(num as *mut i32 as *mut i64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
let _num = &mut *(num as *mut i32 as *mut I64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
std::ptr::write(num as *mut i32 as *mut i64, 2);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
|
|
let _num = &mut *(num as *mut i32);
|
|
}
|
|
|
|
{
|
|
let num = &mut [0i32; 3];
|
|
|
|
let _num = &mut *(num as *mut _ as *mut [i64; 2]);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
std::ptr::write_unaligned(num as *mut _ as *mut [i32; 4], [0, 0, 1, 1]);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
|
|
let _num = &mut *(num as *mut _ as *mut [u32; 3]);
|
|
let _num = &mut *(num as *mut _ as *mut [u32; 2]);
|
|
}
|
|
|
|
{
|
|
let num = &mut [0i32; 3] as &mut [i32];
|
|
|
|
let _num = &mut *(num as *mut _ as *mut i128);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
let _num = &mut *(num as *mut _ as *mut [i64; 4]);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
|
|
let _num = &mut *(num as *mut _ as *mut [u32]);
|
|
let _num = &mut *(num as *mut _ as *mut [i16]);
|
|
}
|
|
|
|
{
|
|
let mat3 = Mat3 { a: Vec3(0i32, 0, 0), b: Vec3(0, 0, 0), c: Vec3(0, 0, 0) };
|
|
|
|
let _num = &mut *(&mat3 as *const _ as *mut [[i64; 3]; 3]);
|
|
//~^ ERROR casting `&T` to `&mut T`
|
|
//~^^ ERROR casting references to a bigger memory layout
|
|
let _num = &*(&mat3 as *const _ as *mut [[i64; 3]; 3]);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
|
|
let _num = &*(&mat3 as *const _ as *mut [[i32; 3]; 3]);
|
|
}
|
|
|
|
{
|
|
let mut l: [u8; 2] = [0,1];
|
|
let w: *mut [u16; 2] = &mut l as *mut [u8; 2] as *mut _;
|
|
let w: *mut [u16] = unsafe {&mut *w};
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
}
|
|
|
|
{
|
|
fn foo() -> [i32; 1] { todo!() }
|
|
|
|
let num = foo();
|
|
let _num = &*(&num as *const i32 as *const i64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
let _num = &*(&foo() as *const i32 as *const i64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
}
|
|
|
|
{
|
|
fn bar(_a: &[i32; 2]) -> &[i32; 1] { todo!() }
|
|
|
|
let num = bar(&[0, 0]);
|
|
let _num = &*(num as *const i32 as *const i64);
|
|
let _num = &*(bar(&[0, 0]) as *const i32 as *const i64);
|
|
}
|
|
|
|
{
|
|
fn foi<T>() -> T { todo!() }
|
|
|
|
let num = foi::<i32>();
|
|
let _num = &*(&num as *const i32 as *const i64);
|
|
//~^ ERROR casting references to a bigger memory layout
|
|
}
|
|
|
|
{
|
|
let x: Box<dyn Send> = Box::new(0i32);
|
|
let _z = unsafe { &*(&*x as *const dyn Send as *const i32) };
|
|
}
|
|
|
|
unsafe fn from_ref(this: &i32) -> &i64 {
|
|
&*(this as *const i32 as *const i64)
|
|
}
|
|
|
|
// https://github.com/rust-lang/rust/issues/124685
|
|
unsafe fn slice_index(array: &mut [u8], offset: usize) {
|
|
let a1 = &mut array[offset];
|
|
let a2 = a1 as *mut u8;
|
|
let a3 = a2 as *mut u64;
|
|
unsafe { *a3 = 3 };
|
|
}
|
|
|
|
unsafe fn field_access(v: &mut Vec3<i32>) {
|
|
let r = &mut v.0;
|
|
let ptr = r as *mut i32 as *mut Vec3<i32>;
|
|
unsafe { *ptr = Vec3(0, 0, 0) }
|
|
}
|
|
|
|
unsafe fn deref(v: &mut Vec3<i32>) {
|
|
let r = &mut v.0;
|
|
let r = &mut *r;
|
|
let ptr = &mut *(r as *mut i32 as *mut Vec3<i32>);
|
|
unsafe { *ptr = Vec3(0, 0, 0) }
|
|
}
|
|
}
|
|
|
|
const RAW_PTR: *mut u8 = 1 as *mut u8;
|
|
unsafe fn no_warn() {
|
|
let num = &3i32;
|
|
let mut_num = &mut 3i32;
|
|
let a = &String::from("ffi");
|
|
|
|
*(num as *const i32 as *mut i32);
|
|
println!("{}", *(num as *const _ as *const i16));
|
|
println!("{}", *(mut_num as *mut _ as *mut i16));
|
|
ffi(a.as_ptr() as *mut _);
|
|
int_ffi(num as *const _ as *mut _);
|
|
int_ffi(&3 as *const _ as *mut _);
|
|
let mut value = 3;
|
|
let value: *const i32 = &mut value;
|
|
*(value as *const i16 as *mut i16) = 42;
|
|
*RAW_PTR = 42; // RAW_PTR is defined outside the function body,
|
|
// make sure we don't ICE on it when trying to
|
|
// determine if we should lint on it or not.
|
|
let cell = &std::cell::UnsafeCell::new(0);
|
|
let _num = &mut *(cell.get() as *mut i32);
|
|
|
|
fn safe_as_mut<T>(x: &std::cell::UnsafeCell<T>) -> &mut T {
|
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
|
}
|
|
|
|
fn cell_as_mut(x: &std::cell::Cell<i32>) -> &mut i32 {
|
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
struct DoesContainUnsafeCell(std::cell::UnsafeCell<i32>);
|
|
fn safe_as_mut2(x: &DoesContainUnsafeCell) -> &mut DoesContainUnsafeCell {
|
|
unsafe { &mut *std::cell::UnsafeCell::raw_get(x as *const _ as *const _) }
|
|
}
|
|
}
|
|
|
|
fn main() {}
|