תמיכה ב-Rust fuzzing ניתנת באמצעות ה-crate libfuzzer-sys
, שמספק קישורים למנוע ה-fuzzing libFuzzer של LLVM. מידע נוסף זמין במאגר libfuzzer-sys וגם בדף הפרויקט LLVM libFuzzer.
המודול rust_fuzz
יוצר קובץ בינארי של fuzzer שמתחיל לבצע fuzzing כשמריצים אותו (בדומה למודול cc_fuzz
). מאחר שה-fuzzer משתמש במנוע ה-fuzzing libFuzzer
, יכול להיות שיידרש מספר ארגומנטים כדי לשלוט ב-fuzzing. הם מפורטים במסמכי התיעוד של libFuzzer.
מודולים מסוג rust_fuzz
הם תוסף למודולים מסוג rust_binary
, ולכן יש להם את אותן תכונות וההנחות. בנוסף, הן מטמיעות הרבה מהתכונות והפונקציונליות של המודולים cc_fuzz
.
כשמפתחים מודולים של rust_fuzz
, הדגל --cfg fuzzing
מופעל. אפשר להשתמש בדגל הזה כדי לתמוך בתכנות מותנית של קוד הספרייה, כדי לשפר את בדיקת ה-fuzzing.
כתיבה של fuzzer בסיסי ב-Rust
אפשר להגדיר מודול fuzz בקובץ build 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
מכיל כלי fuzzing פשוט:
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 */ });
מגדיר את נקודת הכניסה של יעד ה-fuzz שנקראת על ידי מנוע libFuzzer
. הארגומנט data
הוא רצף של בייטים שסופקו על ידי המנוע libFuzzer
, והוא משמש לצורך מניפולציה כקלט כדי לבצע בדיקת fuzz לפונקציה המטורגטת.
בדוגמה הזו של ה-fuzzer, רק אורך הנתונים נבדק כדי לקבוע אם להפעיל את הפונקציה heap_oob
, שהפעלה שלה גורמת לקריאה מחוץ למגבלות. libFuzzer
הוא כלי fuzzing מבוסס-כיסוי, ולכן הוא מתקרב במהירות לאורך הבעיה, מאחר שהוא קובע שה-326 B הראשונים של הנתונים לא יוצרים נתיבים חדשים לביצוע.
הדוגמה הזו נמצאת ב-tree, בכתובת tools/security/fuzzing/example_rust_fuzzer/.
דוגמה מורכבת יותר של fuzzer אחר (שמפעיל fuzzing על יחסי תלות של rustlib
) בתוך העץ מופיעה ב-legacy_blob_fuzzer.
איך כותבים כלי fuzzing מבוססי-מבנה ב-Rust? תוכלו למצוא הנחיות בספר Rust Fuzz, המסמך הרשמי של פרויקט Rust Fuzz.