1+ //! Bindings to [libFuzzer](http://llvm.org/docs/LibFuzzer.html): a runtime for
2+ //! coverage-guided fuzzing.
3+ //!
4+ //! See [the `cargo-fuzz`
5+ //! guide](https://rust-fuzz.github.io/book/cargo-fuzz.html) for a usage
6+ //! tutorial.
7+ //!
8+ //! The main export of this crate is [the `fuzz_target!`
9+ //! macro](./macro.fuzz_target.html), which allows you to define targets for
10+ //! libFuzzer to exercise.
11+
12+ #![ deny( missing_docs, missing_debug_implementations) ]
13+
114pub use arbitrary;
215
316extern "C" {
4- #! [ allow ( improper_ctypes ) ] // we do not actually cross the FFI bound here
5-
17+ // We do not actually cross the FFI bound here.
18+ # [ allow ( improper_ctypes ) ]
619 fn rust_fuzzer_test_input ( input : & [ u8 ] ) ;
720}
821
22+ #[ doc( hidden) ]
923#[ export_name = "LLVMFuzzerTestOneInput" ]
1024pub fn test_input_wrap ( data : * const u8 , size : usize ) -> i32 {
1125 let test_input = :: std:: panic:: catch_unwind ( || unsafe {
@@ -20,6 +34,7 @@ pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
2034 0
2135}
2236
37+ #[ doc( hidden) ]
2338#[ export_name = "LLVMFuzzerInitialize" ]
2439pub fn initialize ( _argc : * const isize , _argv : * const * const * const u8 ) -> isize {
2540 // Registers a panic hook that aborts the process before unwinding.
@@ -38,6 +53,66 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
3853 0
3954}
4055
56+ /// Define a fuzz target.
57+ ///
58+ /// ## Example
59+ ///
60+ /// This example takes a `&[u8]` slice and attempts to parse it. The parsing
61+ /// might fail and return an `Err`, but it shouldn't ever panic or segfault.
62+ ///
63+ /// ```no_run
64+ /// #![no_main]
65+ ///
66+ /// use libfuzzer_sys::fuzz_target;
67+ ///
68+ /// // Note: `|input|` is short for `|input: &[u8]|`.
69+ /// fuzz_target!(|input| {
70+ /// let _result: Result<_, _> = my_crate::parse(input);
71+ /// });
72+ /// # mod my_crate { pub fn parse(_: &[u8]) -> Result<(), ()> { unimplemented!() } }
73+ /// ```
74+ ///
75+ /// ## Arbitrary Input Types
76+ ///
77+ /// The input is a `&[u8]` slice by default, but you can take arbitrary input
78+ /// types, as long as the type implements [the `arbitrary` crate's `Arbitrary`
79+ /// trait](https://docs.rs/arbitrary/*/arbitrary/trait.Arbitrary.html) (which is
80+ /// also re-exported as `libfuzzer_sys::arbitrary::Arbitrary` for convenience).
81+ ///
82+ /// For example, if you wanted to take an arbitrary RGB color, you could do the
83+ /// following:
84+ ///
85+ /// ```no_run
86+ /// #![no_main]
87+ ///
88+ /// use libfuzzer_sys::{arbitrary::{Arbitrary, Unstructured}, fuzz_target};
89+ ///
90+ /// #[derive(Debug)]
91+ /// pub struct Rgb {
92+ /// r: u8,
93+ /// g: u8,
94+ /// b: u8,
95+ /// }
96+ ///
97+ /// impl Arbitrary for Rgb {
98+ /// fn arbitrary<U>(raw: &mut U) -> Result<Self, U::Error>
99+ /// where
100+ /// U: Unstructured + ?Sized
101+ /// {
102+ /// let mut buf = [0; 3];
103+ /// raw.fill_buffer(&mut buf)?;
104+ /// let r = buf[0];
105+ /// let g = buf[1];
106+ /// let b = buf[2];
107+ /// Ok(Rgb { r, g, b })
108+ /// }
109+ /// }
110+ ///
111+ /// // Write a fuzz target that works with RGB colors instead of raw bytes.
112+ /// fuzz_target!(|color: Rgb| {
113+ /// my_crate::convert_color(color);
114+ /// });
115+ /// # mod my_crate { fn convert_color(_: super::Rgb) {} }
41116#[ macro_export]
42117macro_rules! fuzz_target {
43118 ( |$bytes: ident| $body: block) => {
@@ -46,9 +121,11 @@ macro_rules! fuzz_target {
46121 $body
47122 }
48123 } ;
124+
49125 ( |$data: ident: & [ u8 ] | $body: block) => {
50126 fuzz_target!( |$data| $body) ;
51127 } ;
128+
52129 ( |$data: ident: $dty: ty| $body: block) => {
53130 #[ no_mangle]
54131 pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) {
0 commit comments