Moduł rozmywania

Testowanie fuzzingowe w Rust jest obsługiwane przez pakiet libfuzzer-sys, który zapewnia powiązania z silnikiem testowania fuzzingowego libFuzzer LLVM. Więcej informacji znajdziesz w repozytorium libfuzzer-sys oraz na stronie projektu LLVM libFuzzer.

Moduł rust_fuzz tworzy plik binarny narzędzia fuzzingowego, które rozpoczyna fuzzing po uruchomieniu (podobnie jak moduły cc_fuzz). Fuzzer korzysta z libFuzzer silnika fuzzingu, dlatego może przyjmować wiele argumentów do sterowania fuzzingiem. Są one wymienione w dokumentacji libFuzzer.

Moduły rust_fuzz są rozszerzeniem modułów rust_binary, dlatego mają te same właściwości i wymagania. Wiele z nich ma takie same właściwości i funkcje jak moduły cc_fuzz.

Podczas tworzenia rust_fuzzmodułów--cfg fuzzing emitowany jest flaga, która może być używana do obsługi kompilacji warunkowej kodu biblioteki w celu ulepszenia testowania fuzzingowego.

Pisanie podstawowego narzędzia do fuzzingu w Rust

Moduł fuzzingu możesz zdefiniować w pliku kompilacji Android.bp za pomocą tego kodu:

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",
}

Plik fuzzer.rs zawiera prosty program do testowania:

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();
    }
});

Tutaj fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); określa punkt wejścia do testu fuzzingowego wywoływany przez silnik libFuzzer. Argument data to sekwencja bajtów dostarczana przez silnik libFuzzer, która ma być manipulowana jako dane wejściowe do testowania funkcji docelowej.

W tym przykładzie narzędzia do testowania fuzzingowego sprawdzana jest tylko długość danych, aby określić, czy wywołać funkcję heap_oob, której wywołanie powoduje odczyt poza zakresem. libFuzzer to narzędzie do fuzzingu opartego na pokryciu, więc szybko zbiega się do problematycznej długości, ponieważ stwierdza, że pierwsze 326 B danych nie powoduje nowych ścieżek wykonania.

Ten przykład znajdziesz w repozytorium pod adresem tools/security/fuzzing/example_rust_fuzzer/. Aby zobaczyć nieco bardziej złożony przykład innego fuzzera (który fuzzuje rustlibzależność) w drzewie, zapoznaj się z legacy_blob_fuzzer.

Wskazówki dotyczące pisania fuzz testerów Rust uwzględniających strukturę znajdziesz w książce Rust Fuzz, czyli oficjalnej dokumentacji projektu Rust Fuzz.