Mô-đun tìm lỗi mã nguồn

Tính năng kiểm thử ngẫu nhiên Rust được hỗ trợ thông qua thùng libfuzzer-sys. Thùng này cung cấp các liên kết đến công cụ kiểm thử ngẫu nhiên libFuzzer của LLVM. Để biết thêm thông tin, hãy xem kho lưu trữ libfuzzer-sys cũng như trang dự án LLVM libFuzzer.

Mô-đun rust_fuzz tạo ra một tệp nhị phân fuzzer bắt đầu fuzzing khi được chạy (tương tự như các mô-đun cc_fuzz). Vì trình kiểm thử lỗi dựa trên công cụ kiểm thử lỗi libFuzzer, nên trình kiểm thử lỗi này có thể nhận một số đối số để kiểm soát quá trình kiểm thử lỗi. Các giá trị này được liệt kê trong tài liệu libFuzzer.

Các mô-đun rust_fuzz là phần mở rộng của các mô-đun rust_binary, do đó, chúng có cùng các thuộc tính và điểm cần cân nhắc. Ngoài ra, các mô-đun này triển khai nhiều thuộc tính và chức năng giống như các mô-đun cc_fuzz.

Khi tạo các mô-đun rust_fuzz, cờ --cfg fuzzing sẽ được phát ra. Cờ này có thể dùng để hỗ trợ việc biên dịch có điều kiện mã thư viện nhằm cải thiện khả năng kiểm thử ngẫu nhiên.

Viết trình kiểm thử fuzz cơ bản bằng Rust

Bạn có thể xác định một mô-đun kiểm thử ngẫu nhiên trong tệp bản dựng Android.bp bằng mã này:

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

Tệp fuzzer.rs chứa một trình kiểm thử đơn giản:

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

Ở đây, fuzz_target!(|data: &[u8]| { /* fuzz using data here */ }); xác định điểm truy cập fuzz-target do công cụ libFuzzer gọi. Đối số data là một chuỗi byte do công cụ libFuzzer cung cấp để được thao tác dưới dạng đầu vào nhằm làm mờ hàm mục tiêu.

Trong trình kiểm thử fuzzing này, chỉ độ dài của dữ liệu được kiểm tra để xác định xem có gọi hàm heap_oob hay không. Việc gọi hàm này sẽ dẫn đến việc đọc ngoài phạm vi. libFuzzer là một trình kiểm thử fuzzing dựa trên phạm vi, vì vậy, trình này nhanh chóng hội tụ vào độ dài có vấn đề khi xác định rằng 326 B dữ liệu đầu tiên không dẫn đến các đường dẫn thực thi mới.

Tìm ví dụ này trong cây tại tools/security/fuzzing/example_rust_fuzzer/. Để xem một ví dụ phức tạp hơn một chút về một trình kiểm thử fuzz khác (kiểm thử fuzz một phần phụ thuộc rustlib) trong cây, hãy xem legacy_blob_fuzzer.

Để biết hướng dẫn về cách viết trình kiểm thử fuzz Rust có nhận biết cấu trúc, hãy xem sách Rust Fuzz, tài liệu chính thức cho dự án Rust Fuzz.