# Unsafe Code Guidelines
## Rule
Unsafe code MUST be minimized, isolated in dedicated modules, wrapped in safe public APIs, and documented with SAFETY comments explaining why invariants are upheld.
## When Unsafe Is Acceptable
1. FFI (Foreign Function Interface) calls
2. Performance-critical code with proven benchmarks
3. Implementing safe abstractions over raw pointers
4. Interfacing with hardware or OS primitives
## Good Examples
```rust
/// Safe wrapper around an unsafe FFI call.
///
/// # Panics
/// Panics if the buffer is empty.
pub fn compress(data: &[u8]) -> Vec<u8> {
assert!(!data.is_empty(), "input data must not be empty");
let max_len = unsafe {
// SAFETY: max_compressed_size is a pure function that
// only reads the length parameter. No memory access.
ffi::max_compressed_size(data.len())
};
let mut output = vec![0u8; max_len];
let actual_len = unsafe {
// SAFETY: Both pointers are valid for their respective lengths.
// output has at least max_len bytes allocated.
// data is a valid slice with data.len() bytes.
ffi::compress(
data.as_ptr(),
data.len(),
output.as_mut_ptr(),
output.len(),
)
};
output.truncate(actual_len);
output
}
```
## Bad Examples
```rust
// BAD: No safety comment
unsafe { ptr::read(addr) }
// BAD: Unsafe in public API — force users to reason about safety
pub unsafe fn process(ptr: *const u8, len: usize) { ... }
// Wrap in safe API instead
// BAD: Unnecessary unsafe
unsafe {
let v: Vec<i32> = Vec::new(); // Nothing unsafe here!
}
// BAD: Blanket #![allow(unsafe_code)]
```
## Enforcement
- `#![deny(unsafe_code)]` in crate root — force explicit allow per module
- Clippy: `undocumented_unsafe_blocks = "deny"`
- Code review: all unsafe blocks require dedicated reviewer sign-off
- cargo-audit and cargo-geiger for unsafe dependency analysis