Unsafe Rust Best Practices
How to Use This List
- Default: no new
unsafe. Require design review + Miri plan. - Inventory all
unsafein repo quarterly.
A - When to Use
- Try safe refactor first. Indices, split_at_mut, std APIs.
- Use established crates (
bytes,zerocopy) before custom unsafe. Battle-tested. - Isolate FFI in dedicated modules. Single audit surface.
- Document invariants on every
unsafe fnand block.# Safetysection. - Prefer safe wrapper types over pub unsafe fn. Harder to misuse.
B - Correctness
- Run
cargo miri teston nightly for unsafe changes. CI scheduled job. - Never dereference null or dangling raw pointers. Validity checks.
- Initialize memory before read (
MaybeUninit). No assume_init early. - Use
repr(C)only with documented layout for FFI. cbindgen/bindgen. - Catch panics at FFI boundary (
catch_unwind). No unwind into C.
C - Process
- Mandatory code review by second unsafe-knowledgeable reviewer. No solo merge.
- Keep unsafe blocks minimal - one line if possible. Narrow scope.
- Track unsafe in ADR when architectural. Future maintainers.
- Fuzz parsers using unsafe buffers. cargo-fuzz for inputs.
- Deny
unsafein application code if policy allows - crate boundary only.
D - Tooling
- Enable clippy pedantic on unsafe modules. extra lints.
- ASan/TSan for mixed Rust/C builds. Native linkage tests.
- Avoid
static mut- useOnceLock, atomics, mutex. Rust 2024 guidance. - Audit
transmute,from_raw_parts,uncheckedusage. High risk APIs. - Re-run Miri after dependency upgrades touching unsafe.
FAQs
zero unsafe app?
Valid goal for business logic teams.who can write unsafe?
Trained subset + review.unsafe in tests?
Ok if miri covers.allow unsafe_code lint?
#![deny(unsafe_code)] crate attr.bindgen safety?
Every extern needs wrapper.inline asm?
Document clobbers fully.no_std unsafe?
More common - extra care.miri missing ub?
Still need human review.semver unsafe?
Unsafe API still public contract.learn more?
Rustonomicon, Rust Reference UB chapter.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.