Raw Pointers, Pointer Provenance & Strict Aliasing
What Unsafe Rust Actually Does
A common misconception is that writing unsafe turns off the Rust compiler. In reality, unsafe simply gives the software engineer access to five superpowers:
- Dereferencing raw pointers (
*const T,*mut T) - Calling unsafe functions or foreign FFI exports (e.g. CUDA Driver API)
- Implementing unsafe traits (e.g.
SendandSync) - Mutating mutable static variables or accessing
unionfields - Accessing fields of
#[repr(packed)]structs
Pointer Provenance & Stacked Borrows
Modern compilers do not treat memory pointers as raw integers. Every pointer carries invisible provenance: metadata tracking which memory allocation it originated from and what borrowing permissions it possesses. Violating the Stacked Borrows or Tree Borrows model triggers instant UB:
// UNSOUND EXAMPLE: Violating aliasing rules through integer casting
let mut val: u32 = 10;
let ptr = &mut val as *mut u32;
// Deriving a shared reference
let ref_val = &val;
// Writing through ptr while ref_val is live violates the Stacked Borrows stack!
unsafe { *ptr = 20; }
println!("{}", ref_val); // UB: ref_val was invalidated by write through ptr!
Validating Invariants with Miri & Rust 2024 Unsafe Rules
Miri is an interpreter that executes Rust Mid-level Intermediate Representation (MIR) and validates every memory access against the Stacked Borrows and Tree Borrows (-Zmiri-tree-borrows) aliasing models. Furthermore, the Rust 2024 Edition hardened unsafe ergonomics across three compiler rules:
unsafe_op_in_unsafe_fn(Warn-by-Default): Marking a functionunsafe fnonly declares caller preconditions; performing raw pointer dereferences or FFI calls inside its body now requires an explicit innerunsafe { ... }block.unsafe externBlocks: Declaring foreign C/CUDA signatures (including native C-variadicextern "C" fn(..., args: core::ffi::VaList)stabilized in Rust 1.99) requiresunsafe extern "C" { ... }because mismatched ABI signatures cause immediate UB.- Unsafe Linker Attributes: Symbol-altering attributes must be wrapped as
#[unsafe(no_mangle)],#[unsafe(link_section = "...")], or#[unsafe(export_name = "...")]; bare#[no_mangle]is a hard compile error in Rust 2024.
Run Miri interpreter with Stacked Borrows validation to catch pointer provenance violations and out-of-bounds access.