Introduction
Miri is an interpreter for Rust that runs your code inside a virtual machine and checks every memory operation for correctness. It catches undefined behavior, use-after-free, out-of-bounds access, data races, and memory leaks that the compiler cannot detect statically — especially in unsafe code blocks.
What Miri Does
- Interprets Rust MIR (Mid-level Intermediate Representation) to execute programs step by step
- Detects undefined behavior including invalid pointer arithmetic, uninitialized reads, and alignment violations
- Finds data races and deadlocks in concurrent code using a simulated thread scheduler
- Reports memory leaks at program exit
- Validates that unsafe code upholds Rust's safety invariants
Architecture Overview
Miri hooks into the Rust compiler at the MIR stage, interpreting instructions rather than compiling them to machine code. It maintains a virtual memory model with provenance tracking for every pointer, catching aliasing violations and out-of-bounds access. Concurrency is simulated with a deterministic scheduler that explores thread interleavings to surface data races.
Self-Hosting & Configuration
- Requires the nightly Rust toolchain; install with
rustup +nightly component add miri - Run via
cargo +nightly miri testorcargo +nightly miri run - Set
MIRIFLAGSfor options like-Zmiri-disable-isolation(allow file I/O) or-Zmiri-seed=N(deterministic scheduling) - Use
-Zmiri-tag-gc=0to disable garbage collection of stacked-borrows tags for debugging - Add
#[cfg(miri)]in tests to skip operations unsupported by the interpreter
Key Features
- Stacked Borrows and Tree Borrows models for validating reference aliasing rules
- Concurrency support with data-race and deadlock detection
- Cross-platform execution — Miri simulates target platforms independent of the host
- Integration with cargo for testing entire projects without code changes
- Leak detection that reports unreleased allocations at program exit
Comparison with Similar Tools
- Valgrind — C/C++ memory checker; Miri is Rust-specific and understands ownership semantics
- AddressSanitizer (ASan) — Runtime instrumentation; Miri catches more UB categories at the cost of speed
- cargo-careful — Enables extra runtime checks in std; less thorough than Miri but faster
- ThreadSanitizer (TSan) — Data-race detector for compiled code; Miri's scheduler is deterministic
FAQ
Q: Is Miri slow? A: Yes — Miri interprets code rather than compiling it, so execution is roughly 1000x slower. It is designed for testing, not production.
Q: Can Miri run all Rust code?
A: Miri supports most language features but cannot execute FFI calls to C libraries or perform real system I/O without -Zmiri-disable-isolation.
Q: Does Miri find all bugs? A: Miri finds many classes of undefined behavior but is not a formal verifier. It checks the specific execution paths that your tests exercise.
Q: Is Miri part of the official Rust project? A: Yes, Miri is maintained under the rust-lang GitHub organization and distributed via rustup.