25.9 Verifying Unsafe Code: Miri
Since the compiler’s guarantees do not extend into unsafe
blocks, verifying the correctness of unsafe code is crucial. Miri is an experimental interpreter for Rust’s Mid-level Intermediate Representation (MIR). It executes Rust code (including unsafe
blocks) and dynamically checks for certain types of undefined behavior.
Miri can detect violations such as:
- Memory leaks (if enabled).
- Out-of-bounds memory access (pointers and slices).
- Use of uninitialized memory.
- Use-after-free (accessing deallocated memory).
- Invalid pointer alignment.
- Violations of pointer aliasing rules (Stacked Borrows/Tree Borrows).
- Invalid values for types with specific constraints (e.g., using a value other than 0 or 1 for
bool
, invalid enum discriminants). - Invalid
transmute
operations. - Data races (Miri has limited data race detection capabilities, primarily in single-threaded contexts by checking memory model violations).
25.9.1 Using Miri
Miri can be installed as a rustup
component and run via Cargo:
- Install Miri:
rustup component add miri
- Run Miri on your project’s tests:
cargo miri test
- Run Miri on a specific binary target:
cargo miri run --bin your_binary_name
If Miri encounters undefined behavior during execution, it will terminate the program and report an error detailing the violation type and location.
25.9.2 Example: Dangling Pointer Detection
Consider code that incorrectly returns a pointer to a stack variable:
fn create_dangling_pointer() -> *const i32 { let local_var = 100; let ptr = &local_var as *const i32; ptr // Return pointer to `local_var` } // `local_var` goes out of scope here; its stack memory is now invalid. fn main() { let dangling_ptr = create_dangling_pointer(); // Unsafe: Dereferencing a dangling pointer is Undefined Behavior! unsafe { // Miri will likely detect this access as invalid. // Normal compilation might crash, print garbage, or appear to work by chance. println!("Attempting to read dangling pointer: {}", *dangling_ptr); } }
Running this code using cargo miri run
should trigger a Miri error report upon reaching the *dangling_ptr
dereference, indicating an access to invalid memory (specifically, memory previously allocated on the stack frame of create_dangling_pointer
, which no longer exists). Miri helps catch such errors that might otherwise go unnoticed in standard testing.