| #![feature(strict_provenance)] |
| use std::mem; |
| use std::ptr::{self, addr_of}; |
| |
| fn basic_raw() { |
| let mut x = 12; |
| let x = &mut x; |
| |
| assert_eq!(*x, 12); |
| |
| let raw = x as *mut i32; |
| unsafe { |
| *raw = 42; |
| } |
| |
| assert_eq!(*x, 42); |
| |
| let raw = x as *mut i32; |
| unsafe { |
| *raw = 12; |
| } |
| *x = 23; |
| |
| assert_eq!(*x, 23); |
| } |
| |
| fn assign_overlapping() { |
| // Test an assignment where LHS and RHS alias. |
| // In Mir, that's UB (see `fail/overlapping_assignment.rs`), but in surface Rust this is allowed. |
| let mut mem = [0u32; 4]; |
| let ptr = &mut mem as *mut [u32; 4]; |
| unsafe { *ptr = *ptr }; |
| } |
| |
| fn deref_invalid() { |
| unsafe { |
| // `addr_of!(*ptr)` is never UB. |
| let _val = addr_of!(*ptr::without_provenance::<i32>(0)); |
| let _val = addr_of!(*ptr::without_provenance::<i32>(1)); // not aligned |
| |
| // Similarly, just mentioning the place is fine. |
| let _ = *ptr::without_provenance::<i32>(0); |
| let _ = *ptr::without_provenance::<i32>(1); |
| } |
| } |
| |
| fn deref_partially_dangling() { |
| let x = (1, 13); |
| let xptr = &x as *const _ as *const (i32, i32, i32); |
| let val = unsafe { (*xptr).1 }; |
| assert_eq!(val, 13); |
| } |
| |
| fn deref_too_big_slice() { |
| unsafe { |
| let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); |
| // `&*slice` would complain that the slice is too big, but in a raw pointer this is fine. |
| let _val = addr_of!(*slice); |
| } |
| } |
| |
| fn main() { |
| basic_raw(); |
| assign_overlapping(); |
| deref_invalid(); |
| deref_partially_dangling(); |
| deref_too_big_slice(); |
| } |