libfuzzer_sys

Macro fuzz_target

Source
macro_rules! fuzz_target {
    (|$bytes:ident| $body:expr) => { ... };
    (|$data:ident: &[u8]| $body:expr) => { ... };
    (|$data:ident: $dty:ty| $body:expr) => { ... };
    (|$data:ident: $dty:ty| -> $rty:ty $body:block) => { ... };
}
Expand description

Define a fuzz target.

§Example

This example takes a &[u8] slice and attempts to parse it. The parsing might fail and return an Err, but it shouldn’t ever panic or segfault.

#![no_main]

use libfuzzer_sys::fuzz_target;

// Note: `|input|` is short for `|input: &[u8]|`.
fuzz_target!(|input| {
    let _result: Result<_, _> = my_crate::parse(input);
});

§Rejecting Inputs

It may be desirable to reject some inputs, i.e. to not add them to the corpus.

For example, when fuzzing an API consisting of parsing and other logic, one may want to allow only those inputs into the corpus that parse successfully. To indicate whether an input should be kept in or rejected from the corpus, return either Corpus::Keep or Corpus::Reject from your fuzz target. The default behavior (e.g. if () is returned) is to keep the input in the corpus.

For example:

#![no_main]

use libfuzzer_sys::{Corpus, fuzz_target};

fuzz_target!(|input: String| -> Corpus {
    let parts: Vec<&str> = input.splitn(2, '=').collect();
    if parts.len() != 2 {
        return Corpus::Reject;
    }

    let key = parts[0];
    let value = parts[1];
    let _result: Result<_, _> = my_crate::parse(key, value);
    Corpus::Keep
});

§Arbitrary Input Types

The input is a &[u8] slice by default, but you can take arbitrary input types, as long as the type implements the arbitrary crate’s Arbitrary trait (which is also re-exported as libfuzzer_sys::arbitrary::Arbitrary for convenience).

For example, if you wanted to take an arbitrary RGB color, you could do the following:

#![no_main]

use libfuzzer_sys::{arbitrary::{Arbitrary, Error, Unstructured}, fuzz_target};

#[derive(Debug)]
pub struct Rgb {
    r: u8,
    g: u8,
    b: u8,
}

impl<'a> Arbitrary<'a> for Rgb {
    fn arbitrary(raw: &mut Unstructured<'a>) -> Result<Self, Error> {
        let mut buf = [0; 3];
        raw.fill_buffer(&mut buf)?;
        let r = buf[0];
        let g = buf[1];
        let b = buf[2];
        Ok(Rgb { r, g, b })
    }
}

// Write a fuzz target that works with RGB colors instead of raw bytes.
fuzz_target!(|color: Rgb| {
    my_crate::convert_color(color);
});

You can also enable the arbitrary crate’s custom derive via this crate’s "arbitrary-derive" cargo feature.