Rust 模糊測試是透過 libfuzzer-sys
Crate 支援,該 Crate 提供 LLVM 的 libFuzzer 模糊測試引擎繫結。詳情請參閱 libfuzzer-sys 存放區和 LLVM libFuzzer 專案頁面。
rust_fuzz
模組會產生模糊測試器二進位檔,該檔案會在執行時開始模糊測試 (類似於 cc_fuzz
模組)。由於模糊測試器會運用 libFuzzer
模糊測試引擎,因此可以採用多個引數來控制模糊測試。這些項目列在 libFuzzer 說明文件中。
rust_fuzz
模組是 rust_binary
模組的擴充功能,因此具有相同的屬性和注意事項。此外,這些模組實作的許多屬性和功能,都與 cc_fuzz
模組相同。
建構 rust_fuzz
模組時,系統會發出 --cfg fuzzing
標記,可用於支援程式庫程式碼的條件式編譯,以改善模糊測試。
撰寫基本的 Rust 模糊測試器
您可以在 Android.bp
建構檔案中,使用下列程式碼定義模糊測試模組:
rust_fuzz {
name: "example_rust_fuzzer",
srcs: ["fuzzer.rs"],
// Config for running the target on fuzzing infrastructure can be set under
// fuzz_config. This shares the same properties as cc_fuzz's fuzz_config.
fuzz_config: {
fuzz_on_haiku_device: true,
fuzz_on_haiku_host: false,
},
// Path to a corpus of sample inputs, optional. See https://llvm.org/docs/LibFuzzer.html#corpus
corpus: ["testdata/*"],
// Path to a dictionary of sample byte sequences, optional. See https://llvm.org/docs/LibFuzzer.html#dictionaries
dictionary: "example_rust_fuzzer.dict",
}
fuzzer.rs
檔案包含簡單的模糊測試器:
fn heap_oob() {
let xs = vec![0, 1, 2, 3];
let val = unsafe { *xs.as_ptr().offset(4) };
println!("Out-of-bounds heap value: {}", val);
}
fuzz_target!(|data: &[u8]| {
let magic_number = 327;
if data.len() == magic_number {
heap_oob();
}
});
其中 fuzz_target!(|data: &[u8]| { /* fuzz using data here */ });
會定義 libFuzzer
引擎呼叫的模糊測試目標進入點。data
引數是由 libFuzzer
引擎提供的位元組序列,可做為模糊測試目標函式的輸入內容。
在本例中,模糊測試器只會檢查資料長度,判斷是否要呼叫 heap_oob
函式,而呼叫該函式會導致超出範圍的讀取作業。libFuzzer
是以涵蓋範圍為導向的模糊測試器,因此會快速收斂至有問題的長度,因為它判斷前 326 B 的資料不會產生新的執行路徑。
在樹狀結構中,這個範例位於 tools/security/fuzzing/example_rust_fuzzer/。
如要查看另一個稍微複雜的模糊測試器範例 (模糊測試樹狀結構中的依附元件),請參閱 legacy_blob_fuzzer。rustlib
如需如何編寫結構感知 Rust Fuzzer 的指南,請參閱 Rust Fuzz 書籍,這是 Rust Fuzz 專案的官方文件。