关于 rust-sanitizers-miri
面向 Agent 的 Rust 运行时安全验证技能,介绍使用 sanitizers 和 Miri 检查代码。内容涵盖工具配置、测试执行、报告解读及 CI 集成。
主要功能
- 01运行 ASan、TSan、MSan 和 UBSan
- 02用 Miri 检查 unsafe Rust
- 03解读 sanitizer 报告
- 04配置 Miri 参数
- 05在 CI 中集成 Miri 测试
适用场景
- 01排查 unsafe Rust 中的未定义行为
- 02用 sanitizer 查找内存错误
- 03诊断 Rust 测试中的数据竞争
- 04在 CI 中添加 Miri 检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill rust-sanitizers-miri安装后在 Claude Code 中输入/rust-sanitizers-miri确认已加载。
附带文件references/miri-ub-patterns.md
详细介绍
Rust Sanitizers 和 Miri
用途
指导 Agent 对 Rust 进行运行时安全验证:通过 RUSTFLAGS 使用 ASan/TSan/MSan/UBSan,使用 Miri 检测 unsafe 代码中的编译时 UB,并解读 Sanitizer 报告。
触发条件
- “如何在 Rust 代码上运行 AddressSanitizer?”
- “如何使用 Miri 检查我的 unsafe Rust?”
- “如何在 Rust 程序上运行 ThreadSanitizer?”
- “我的 unsafe Rust 可能存在 UB,该如何检测?”
- “如何解读 Rust ASan 报告?”
- “可以在 stable 上运行 Rust Sanitizer 吗?”
工作流
1. Rust 中的 Sanitizer(需要 nightly)
Rust Sanitizer 需要 nightly 和兼容的平台:
# Install nightly
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
# AddressSanitizer (Linux, macOS)
RUSTFLAGS="-Z sanitizer=address" \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu
# ThreadSanitizer (Linux)
RUSTFLAGS="-Z sanitizer=thread" \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu
# MemorySanitizer (Linux, requires all-instrumented build)
RUSTFLAGS="-Z sanitizer=memory -Zsanitizer-memory-track-origins" \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu
# UndefinedBehaviorSanitizer
RUSTFLAGS="-Z sanitizer=undefined" \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu
-Zbuild-std 会使用 Sanitizer 重新构建标准库,这对于获得准确结果是必要的。
2. stable Sanitizer 的替代方案
对于 stable Rust,可使用 cross 工具搭配预配置了 Sanitizer 的 Docker 镜像,或在包含 nightly 的镜像中通过 Docker 容器运行 cargo test。
或者,无需 nightly 即可进行更简单的 UB 检查:
# cargo-sanitize (wrapper)
cargo install cargo-sanitize
cargo sanitize address
3. 解读 Rust 中的 ASan 输出
==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000050
READ of size 4 at 0x602000000050 thread T0
#0 0x401234 in myapp::module::function /src/main.rs:15
#1 0x401567 in myapp::main /src/main.rs:42
0x602000000050 is located 0 bytes after a 40-byte region allocated at:
#0 0x... in alloc::alloc::alloc ...
#1 0x... in myapp::create_buffer /src/main.rs:10
Rust 特有模式:
| ASan 错误 | 可能的 Rust 原因 |
|---|---|
heap-buffer-overflow | unsafe 切片访问越界 |
use-after-free | Vec 重新分配后使用 unsafe 指针 |
stack-use-after-return | 返回局部变量的引用 |
heap-use-after-free | drop() 或 Box::from_raw 后使用对象 |
4. Miri——未定义行为解释器
Miri 会解释 Rust MIR,并检测 Sanitizer 可能遗漏的 UB:
# Install Miri (requires nightly)
rustup +nightly component add miri
# Run tests under Miri
cargo +nightly miri test
# Run specific test
cargo +nightly miri test test_name
# Run a binary under Miri
cargo +nightly miri run
# Run with Stacked Borrows model (strict aliasing)
MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test
# Disable isolation (allow file I/O, randomness)
MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri test
5. Miri 能检测什么
// 1. Dangling pointer use
unsafe {
let x = Box::new(42);
let ptr = Box::into_raw(x);
let _ = Box::from_raw(ptr); // drop
let _val = *ptr; // Miri: use of dangling pointer
}
// 2. Invalid enum discriminant
let x: u8 = 3;
let e = unsafe { std::mem::transmute::<u8, MyEnum>(x) };
// Miri: enum value has invalid tag
// 3. Uninitialized memory read
let uninit: MaybeUninit<u32> = MaybeUninit::uninit();
let val = unsafe { uninit.assume_init() }; // Miri: reading uninitialized bytes
// 4. Stacked borrows violation
let mut x = 5u32;
let ptr = &mut x as *mut u32;
let _ref = &x; // shared reference
unsafe { *ptr = 10; } // Miri: mutable access while shared borrow exists
// 5. Data races (with threads)
// Miri simulates sequential execution and detects races via Stacked Borrows
6. Rust 的 ThreadSanitizer
RUSTFLAGS="-Z sanitizer=thread" \
RUST_TEST_THREADS=8 \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu 2>&1 | head -50
TSan 输出:
WARNING: ThreadSanitizer: data race (pid=12345)
Write of size 4 at 0x7f... by thread T2 (mutexes: write M1):
#0 myapp::counter::increment src/counter.rs:10
Previous read of size 4 at 0x7f... by thread T1:
#0 myapp::counter::get src/counter.rs:5
7. 通过 MIRIFLAGS 配置 Miri
| 标志 | 作用 |
|---|---|
-Zmiri-disable-isolation | 允许 I/O、时钟和随机数 |
-Zmiri-strict-provenance | 严格的指针来源规则(比 LLVM 更严格) |
-Zmiri-symbolic-alignment-check | 更严格的对齐检查 |
-Zmiri-check-number-validity | 检查浮点数/整数的有效性 |
-Zmiri-num-cpus=N | 模拟 N 个 CPU(用于并发) |
-Zmiri-seed=N | 随机调度的种子 |
-Zmiri-ignore-leaks | 抑制内存泄漏错误 |
-Zmiri-tag-raw-pointers | 跟踪原始指针来源 |
8. 集成到 CI
# GitHub Actions
- name: Miri
run: |
rustup toolchain install nightly
rustup +nightly component add miri
cargo +nightly miri test
env:
MIRIFLAGS: "-Zmiri-disable-isolation"
- name: ASan (nightly)
run: |
rustup component add rust-src --toolchain nightly
RUSTFLAGS="-Z sanitizer=address" \
cargo +nightly test -Zbuild-std \
--target x86_64-unknown-linux-gnu
相关技能
- 使用
skills/rust/rust-debugging调试 Rust panic(GDB/LLDB) - 使用
skills/runtimes/sanitizers了解 C/C++ Sanitizer 的用法和对比 - 使用
skills/rust/rust-unsafe了解 unsafe Rust 模式和审查清单 - 使用
skills/runtimes/fuzzing生成可触发 Sanitizer 错误的输入
评论
支持 Markdown