Rust 的編譯器是大多數開發者遇到的最固執己見的程式碼審查員。它的所有權系統、借用檢查器和生命週期強制執行機制消除了困擾 C 和 C++ 程式碼庫的許多類型的 bug。但是,一個能夠防止記憶體錯誤的編譯器並不等於一個全面的品質體系。邏輯錯誤、不安全的依賴鏈、不安全的程式碼區塊誤用、效能反模式以及風格漂移等問題依然存在。 rustc能夠大規模交付可靠 Rust 的團隊,會將編譯器與一套分層的靜態分析工具結合,每個工具都涵蓋品質層面的不同部分。
選擇錯誤的工具組合會浪費持續整合 (CI) 時間,並產生開發者最終會忽略的噪音。而選擇正確的組合則能讓編譯器的嚴格程度感覺像是底線而非上限。本指南中的工具按其實際功能而非字母順序排列,因此團隊可以建立一個涵蓋所有三個品質層面的技術堆疊:程式碼檢查和慣用法、依賴安全性以及針對安全關鍵型或安全敏感型程式碼的深度驗證。
SMART TS XL
即使語言具有強大的安全保障,在現代 Rust 開發中保持品質仍然具有挑戰性。 SMART TS XL 旨在透過提供針對 Rust 獨特特性客製化的深度靜態分析功能,幫助團隊建立可靠、可維護且安全的軟體。它透過及早發現問題、增強一致性並減少人工審查工作量,支援專業的工程工作流程。
鏽蝕的三層靜態分析
了解哪個工具適合哪個場景,可以避免常見的錯誤,例如在可以使用程式碼檢查器(linter)的地方使用形式化驗證器,或在需要安全掃描器的地方依賴程式碼檢查器。每個成熟的 Rust 專案都應該涵蓋所有三個層面。
第一層:除毛和造型 能夠發現違反慣用語法規範的行為、常見錯誤和可維護性問題。工具:Clippy、rustfmt、rust-analyzer。
第二層:依賴性與供應鏈安全 對第三方貨箱進行審核,以發現已知漏洞和違反策略的行為。工具:cargo-audit、cargo-deny、cargo-auditable。
第 3 層:深度驗證 尋找不安全程式碼中的記憶體安全性問題、未定義行為,並形式化證明關鍵函數的屬性。工具:Miri、Kani、MIRAI、Rudra、Creusot、Prusti。
下表將每個主要工具與其所在層級、成本、配置完整性適用性和主要用例進行了對應:
| 工具 | 層 | 價格 | CI適用 | 主要用例 |
|---|---|---|---|---|
| 大眼夾 | 林亭 | 免費/開源軟體 | 可以 | 慣用語法檢查、風格、常見錯誤 |
| rustfmt | 林亭 | 免費/開源軟體 | 可以 | 程式碼格式強制執行 |
| 生鏽分析儀 | 棉絮/DX | 免費/開源軟體 | 局部的 | IDE診斷,內嵌分析 |
| 貨物審計 | 依賴性安全 | 免費/開源軟體 | 可以 | 已知的箱子安全漏洞 |
| 貨物拒收 | 依賴性安全 | 免費/開源軟體 | 可以 | 許可證、副本、通知 |
| 貨物審計 | 依賴性安全 | 免費/開源軟體 | 可以 | 將依賴關係資料嵌入二進位檔案中 |
| 美裡 | 深度驗證 | 免費/開源軟體 | 選擇性 | 不安全程式碼中的未定義行為 |
| 卡尼 | 深度驗證 | 免費/開源軟體 | 選擇性 | 形式化驗證、模型檢查 |
| MIRAI | 深度驗證 | 免費/開源軟體 | 選擇性 | 抽象解釋,污點分析 |
| 魯德拉 | 深度驗證 | 免費/開源軟體 | 研究 | 不安全 Rust 中的記憶體安全漏洞 |
| 塞姆格雷普 | 交叉 | 免費版 + 付費版 | 可以 | 自訂安全模式,多語言 |
| 聲納雲 | 交叉 | 免費版 + 付費版 | 可以 | 持續品質門、儀錶板 |
第一層:程式碼檢查、樣式和開發者體驗
大眼夾
Clippy 是 Rust 靜態分析的權威入門工具。它隨官方 Rust 工具鏈一起發布,提供超過 700 條程式碼檢查建議,涵蓋正確性、效能、風格、複雜度和限制等方面。它是大多數 Rust 團隊日常使用的工具,原因顯而易見:它能夠捕捉真正的 bug,而不僅僅是風格方面的意見。
打壞
# Run all lints including pedantic and nursery groups
cargo clippy -- -W clippy::all -W clippy::pedantic
# Fail CI on any warning
cargo clippy -- -D warnings
# Check specific lint group
cargo clippy -- -W clippy::correctness -W clippy::suspicious
Clippy 的 lint 分類值得詳細了解:
| 項目類別 | 它捕獲了什麼 |
|---|---|
correctness | 幾乎可以肯定有誤的程式碼(務必否認) |
suspicious | 這段程式碼很可能是錯的,或者非常出乎意料。 |
style | 非慣用語模式,但有明顯改進 |
complexity | 不必要的複雜結構 |
performance | 程式碼可以編譯,但運行速度比預期慢。 |
pedantic | 嚴格的指導方針,帶有主觀色彩(選擇性啟用) |
restriction | 您可能希望在特定情況下強制執行的規則 |
nursery | 新棉絮可能會產生假陽性結果。 |
貨物檢查與 Clippy: cargo check 它無需生成二進位檔案即可驗證類型正確性和編譯情況。速度快,適用於建置驗證。 cargo clippy 運行 cargo check 以及所有 lint 分析。對於 CI,請運行 cargo check 為了快速編譯回饋和 cargo clippy -- -D warnings 作為獨立的質量把關環節,它們不可互換。 cargo check 不會發現習慣用語問題,而且 cargo clippy 速度較慢。
配置 Clippy 通過 clippy.toml 或者,內聯屬性可以讓團隊控制噪音:
湯姆
# clippy.toml
avoid-breaking-exported-api = false
msrv = "1.70"
銹
// Suppress a lint for one function with documented reason
#[allow(clippy::too_many_arguments)]
fn complex_setup(...) { ... }
Clippy 不涵蓋以下內容:跨模組的深度資料流分析、依賴項中的安全漏洞掃描、形式化正確性證明或自訂組織特定規則。這些需要其他層級的工具。
rustfmt
rustfmt 使用以下方式在整個程式碼庫中強制執行一致的格式: cargo fmt。 “ rustfmt.toml 設定檔設定項目範圍的樣式規則。在持續整合(CI)中, cargo fmt -- --check 如果任何檔案需要重新格式化,則以非零代碼退出,使其成為一個乾淨的品質門控程序,無需任何配置開銷:
打壞
# Check formatting without modifying files (CI mode)
cargo fmt -- --check
# Apply formatting (developer mode)
cargo fmt
rust分析器和IDE集成
rust-analyzer 是 Rust 的語言伺服器協定 (LSP) 實現,它在任何相容 LSP 的編輯器中提供即時診斷、程式碼補全、跳到定義以及 Clippy 內聯警告。它取代了已棄用的 RLS(Rust 語言伺服器),並且應該成為新專案中唯一使用的語言伺服器。
從靜態分析的角度來看,rust-analyzer 會在開發者輸入程式碼時直接顯示 Clippy lint,從而在引入程式碼時立即提供關於樣式和正確性問題的回饋,而無需單獨執行終端命令:
JSON
// VS Code settings.json: enable Clippy via rust-analyzer
{
"rust-analyzer.check.command": "clippy",
"rust-analyzer.check.extraArgs": [
"--", "-W", "clippy::all", "-W", "clippy::pedantic"
]
}
rust-analyzer 還提供了推斷類型、借用生命週期和參數名稱的內嵌提示,這對於在不查看定義的情況下審查不熟悉的程式碼非常有用。
第二層:依賴關係與供應鏈安全
貨物審計
貨物審計檢查 Cargo.lock 使用 RustSec 安全漏洞資料庫對文件進行比對,識別直接和傳遞相依性中已知的 CVE 漏洞。它是每個 Rust 專案在持續整合 (CI) 環境中都應該運行的最低限度相依性安全工具。
打壞
# Install
cargo install cargo-audit
# Run audit
cargo audit
# Ignore a specific advisory (document the reason in comments)
cargo audit --ignore RUSTSEC-2024-0001
# JSON output for pipeline integration
cargo audit --json | jq '.vulnerabilities'
cargo-audit 僅涵蓋已知的、已發布的安全公告。它無法偵測您自身程式碼中的漏洞、RustSec 資料庫中尚未收錄的問題,也無法偵測政策違規行為,例如未經授權的授權。
貨物拒收
cargo-deny 將相依性管理功能從已知的 CVE 擴展到許可證合規性、重複 crate 偵測以及自訂禁止/允許策略。對於有合規性要求的組織而言,它是一個更全面的工具:
湯姆
# deny.toml
[advisories]
vulnerability = "deny"
unmaintained = "warn"
[licenses]
allow = ["MIT", "Apache-2.0", "ISC", "BSD-2-Clause", "BSD-3-Clause"]
deny = ["GPL-2.0"]
copyleft = "warn"
[bans]
multiple-versions = "warn"
打壞
cargo install cargo-deny
cargo deny check
貨物審計
cargo-auditable 將完整的依賴關係樹作為結構化元資料嵌入到編譯後的 Rust 二進位檔案中,並放置在專用的連結器部分。這使得在無需存取原始程式碼的情況下審核已部署的二進位檔案成為可能,這對於部署後的安全審查和供應鏈透明度非常有價值:
打壞
cargo install cargo-auditable
cargo auditable build --release
# The binary now contains auditable dependency metadata
# Audit a binary directly:
cargo audit bin ./target/release/my-service
第三層:深度驗證
這一層的工具需要更多的設定、更專業的技能和更長的分析時間。它們並非適用於每個程式碼庫中的每個函數。它們對於不安全程式碼、加密實作、處理不受信任輸入的解析器邏輯以及任何需要證明而非測試其正確性的程式碼都至關重要。
Miri:未定義行為偵測
Miri 是 Rust 中級中間表示 (MIR) 的解釋器,它以一種能夠檢測編譯器允許但違反 Rust 安全保證的未定義行為的方式來執行程式碼:不安全區塊中的越界記憶體存取、釋放後使用、未對齊的指標解引用、多執行緒不安全程式碼中的資料競爭以及違反 Rust 別名模型的行為。
打壞
# Install Miri (requires nightly)
rustup +nightly component add miri
# Run tests under Miri
cargo +nightly miri test
# Enable strict aliasing validation
MIRIFLAGS="-Zmiri-strict-provenance" cargo +nightly miri test
Miri檢測到了什麼:未定義行為 unsafe 阻塞、記憶體存取違規、釋放後使用、未對齊存取、偵錯版本中的整數溢位、不安全並發程式碼中的資料競爭。
美里不涵蓋的內容:安全程式碼中的邏輯錯誤,不涉及未定義行為、依賴性漏洞、程式碼樣式或效能問題。
CI 集成Miri 的運作速度比其他軟體慢 10-50 倍 cargo test選擇性地對包含以下模組的模組運行它: unsafe 代碼,或按每晚的計劃進行維護,而不是每次提交都進行維護:
雅姆
- name: Miri on unsafe modules
run: |
rustup +nightly component add miri
cargo +nightly miri test --package my-unsafe-crate
Kani:模型檢查和形式化驗證
Kani 由 Amazon Web Services 開發,是一個模型檢查器,它透過窮舉執行路徑直到預設邊界,來形式化地驗證 Rust 程式碼的屬性。 Miri 運行實際的測試案例並找到特定的錯誤,而 Kani 則證明或反駁屬性在其分析範圍內所有輸入的有效性。
Kani 需要編寫驗證框架:定義輸入空間和要驗證的屬性的函數:
銹
#[cfg(kani)]
mod verification {
use super::*;
#[kani::proof]
fn verify_add_no_overflow() {
let a: u32 = kani::any();
let b: u32 = kani::any();
if a.checked_add(b).is_some() {
let result = safe_add(a, b);
assert!(result == a + b);
}
}
}
打壞
cargo install --locked kani-verifier
cargo kani setup
cargo kani
最適合用於:安全關鍵功能、協定實作、金融或密碼程式碼中的算術運算,以及任何需要證明(而不僅僅是測試)正確性屬性的功能。
MIRAI:摘要解釋與污點分析
MIRAI 由 Facebook Research 開發,它使用抽象解釋來分析 Rust 的 MIR。它執行過程間分析,追蹤值如何在函數呼叫中流動,檢測潛在的 panic、契約違反以及污點在程式碼中的傳播。
銹
use mirai_annotations::*;
fn divide(a: i32, b: i32) -> i32 {
precondition!(b != 0); // MIRAI verifies all callers satisfy this
a / b
}
MIRAI 需要每日 Rust 編譯器,並且設置曲線陡峭,因此最適合具有專門的安全工程能力或以研究為導向的品質要求的團隊。
Rudra:不安全函式庫程式碼中的記憶體安全
Rudra 會對整個程序進行分析,檢測 Rust 所有權模型特有的記憶體安全漏洞:Send/Sync trait 的安全違規、允許不合理生命週期延長的更高類型生命週期問題,以及不安全程式碼中的 panic 安全問題。它最初由研究人員開發,作為編譯器插件運行,需要特定的 nightly 版本。建議針對包含不安全內部機制的庫 crate 定期運行 Rudra,而不是每次提交都運行。
克勒索與普魯斯蒂:演繹驗證
Creusot 和 Prusti 是演繹驗證工具,用來證明 Rust 程式的數學屬性。兩者都需要形式化規範(前提條件、後置條件、循環不變量),並使用自動定理證明器來驗證實作是否符合這些規範。它們針對的是 Rust 安全代碼的一個特定子集,並且需要具備形式化方法的專業知識。適用於受監管行業、密碼庫開發,或任何需要數學正確性證明作為合約或監管要求的場景。
值得包含的其他工具
Semgrep 用於自訂安全模式
Semgrep 提供基於模式的靜態分析,可同時跨多種語言運行。對於 Rust,它使團隊能夠編寫自訂規則,以強制執行組織安全性策略和 Clippy 無法表達的程式碼庫特定模式:
雅姆
# Custom rule: flag .unwrap() in production paths
rules:
- id: no-unwrap-in-production
pattern: $X.unwrap()
message: "Use proper error handling instead of .unwrap()"
languages: [rust]
severity: WARNING
Semgrep 還提供了一個託管規則註冊表,其中包含由社群維護的 Rust 安全規則。
SonarCloud / SonarQube 用於連續品質閘控
SonarCloud 提供持續的程式碼品質分析,包括儀錶板、趨勢追蹤和拉取請求標記。它對 Rust 的支援涵蓋了常見的錯誤模式、安全熱點和程式碼異味。對於已經在使用 SonarCloud 處理其他語言的企業團隊來說,將 Rust 加入到同一管線中,可以實現整個技術堆疊的統一品質可見度。
建立分層 CI/CD 流水線
以下 GitHub Actions 工作流程為希望在不進行過度設計的情況下全面涵蓋 Rust 品質的團隊提供了一個實用的起點:
雅姆
# .github/workflows/quality.yml
name: Code Quality and Security
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- name: Check formatting
run: cargo fmt -- --check
- name: Clippy (treat warnings as errors)
run: cargo clippy -- -D warnings
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Install security tools
run: |
cargo install cargo-audit
cargo install cargo-deny
- name: Dependency audit
run: cargo audit --deny warnings
- name: License and policy check
run: cargo deny check
verify:
runs-on: ubuntu-latest
# Scheduled or manually triggered, not on every push
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
components: miri
- name: Miri on unsafe modules
run: cargo +nightly miri test --package my-unsafe-crate
您應該使用哪種工具?決策指南
啟動一個新的 Rust 項目Clippy + rustfmt + cargo-audit。五分鐘內即可完成配置,能夠捕捉團隊遇到的絕大多數品質和安全問題。
生產服務及其外部依賴項:除了 CVE 之外,還增加了貨物拒收功能,用於許可證合規性和供應鏈政策執行。
內部結構不安全的庫對於包含不安全程式碼的模組,請將 Miri 新增至測試套件。定期運行 Rudra。
安全關鍵型或加密代碼為最關鍵的功能編寫 Kani 驗證框架。如果團隊具備形式化方法的專業知識,可以考慮使用 Creusot 或 Prusti。
以安全為中心的組織:為組織安全策略新增自訂規則的 Semgrep,並在發布版本中新增 cargo-auditable。
為更大的團隊提供持續的可見性:SonarCloud 用於趨勢追蹤、拉取請求裝飾和品質門禁以及開源工具。
多語言企業環境 Rust 與 COBOL、Java 或其他遺留語言互動的地方:單語言 Rust 工具無法跨越語言邊界。 SMART TS XL 提供涵蓋整個系統的跨語言分析。
當 Rust 靜態分析遇上企業系統
在運行 COBOL、Java、PL/I 或 RPG 等程式語言的大型主機或傳統平台上,Rust 越來越多地被用於開發新的服務。在這些環境中,靜態分析的範圍遠超過任何 Rust 專用工具所能及。 Rust 微服務可能呼叫 COBOL 程式、寫入共享資料庫,或使用傳統批次系統產生的事件。企業架構師關注的品質和依賴性分析需要同時涵蓋所有這些系統。
SMART TS XL 它透過提供跨語言的依賴關係分析來彌補這一差距,分析範圍涵蓋整個應用程式組合。 Clippy 和 cargo-audit 只能辨識 Rust, SMART TS XL 它描繪了 Rust 服務如何依賴共享資料結構、遺留程式和企業 API,以及更改任何這些依賴項會產生什麼影響。這使其成為首選工具。 影響分析 以及 傳統系統現代化規劃 在 Rust 只是眾多程式語言之一的環境中。
對於在大型企業程式碼庫中逐步採用 Rust 的團隊而言, SMART TS XL“ 靜態程式碼分析 它提供了必要的結構可見性,以便在進行可能影響其他語言編寫的元件的變更之前,了解 Rust 元件如何融入更大的系統。如同在以下背景所考察的: 依賴關係圖和應用程式風險在擴展系統之前繪製完整的依賴關係圖,可以將順利進行的變更與那些導致組件故障(因為沒有人想到要測試這些組件)的變更區分開來。
分層法是關鍵。
Rust 中的靜態分析並非只取決於工具的選擇。它是一個層層遞進的過程,從編譯器提供的免費功能開始,並根據程式碼的風險狀況向外擴展。 Clippy 和 rustfmt 是基礎。對於任何包含外部依賴的項目,cargo-audit 都是必不可少的。 Miri 適用於任何包含不安全程式碼的項目。 Kani 和形式化驗證工具則用於那些容不得絲毫錯誤的函數。
真正能做到這一點的團隊會將靜態分析整合到開發流程中:編輯器內聯 Clippy,每次 CI 運行都使用 cargo-audit,以及在夜間任務中使用 Miri 來捕獲僅靠測試無法發現的問題。結果不僅僅是減少了 bug,更重要的是,它讓團隊對程式碼庫充滿信心,從而能夠快速地進行更改,因為他們知道開發人員和生產環境之間的分析層正在正常工作。