1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
|
//@ 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() {}
|