وحدات Fuzz

تتوفّر ميزة اختبار التشويش في Rust من خلال حزمة libfuzzer-sys التي توفّر روابط لمحرك اختبار التشويش libFuzzer من LLVM. لمزيد من المعلومات، يُرجى الاطّلاع على مستودع 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 بايت من البيانات لا تؤدي إلى مسارات تنفيذ جديدة.

يمكنك العثور على هذا المثال في الشجرة على المسار tools/security/fuzzing/example_rust_fuzzer/‎. للاطّلاع على مثال أكثر تعقيدًا قليلاً لمموّه آخر (يُجري تمويهًا لملف rustlib تابع) في الشجرة، يمكنك الاطّلاع على legacy_blob_fuzzer.

للحصول على إرشادات حول كيفية كتابة أدوات فحص غير واضح لبرامج Rust تراعي البنية، راجِع كتاب Rust Fuzz، وهو المستند الرسمي لمشروع Rust Fuzz.