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
+
1
14
pub use arbitrary;
2
15
3
16
extern "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 ) ]
6
19
fn rust_fuzzer_test_input ( input : & [ u8 ] ) ;
7
20
}
8
21
22
+ #[ doc( hidden) ]
9
23
#[ export_name = "LLVMFuzzerTestOneInput" ]
10
24
pub fn test_input_wrap ( data : * const u8 , size : usize ) -> i32 {
11
25
let test_input = :: std:: panic:: catch_unwind ( || unsafe {
@@ -20,6 +34,7 @@ pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
20
34
0
21
35
}
22
36
37
+ #[ doc( hidden) ]
23
38
#[ export_name = "LLVMFuzzerInitialize" ]
24
39
pub fn initialize ( _argc : * const isize , _argv : * const * const * const u8 ) -> isize {
25
40
// Registers a panic hook that aborts the process before unwinding.
@@ -36,6 +51,66 @@ pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize
36
51
0
37
52
}
38
53
54
+ /// Define a fuzz target.
55
+ ///
56
+ /// ## Example
57
+ ///
58
+ /// This example takes a `&[u8]` slice and attempts to parse it. The parsing
59
+ /// might fail and return an `Err`, but it shouldn't ever panic or segfault.
60
+ ///
61
+ /// ```no_run
62
+ /// #![no_main]
63
+ ///
64
+ /// use libfuzzer_sys::fuzz_target;
65
+ ///
66
+ /// // Note: `|input|` is short for `|input: &[u8]|`.
67
+ /// fuzz_target!(|input| {
68
+ /// let _result: Result<_, _> = my_crate::parse(input);
69
+ /// });
70
+ /// # mod my_crate { pub fn parse(_: &[u8]) -> Result<(), ()> { unimplemented!() } }
71
+ /// ```
72
+ ///
73
+ /// ## Arbitrary Input Types
74
+ ///
75
+ /// The input is a `&[u8]` slice by default, but you can take arbitrary input
76
+ /// types, as long as the type implements [the `arbitrary` crate's `Arbitrary`
77
+ /// trait](https://docs.rs/arbitrary/*/arbitrary/trait.Arbitrary.html) (which is
78
+ /// also re-exported as `libfuzzer_sys::arbitrary::Arbitrary` for convenience).
79
+ ///
80
+ /// For example, if you wanted to take an arbitrary RGB color, you could do the
81
+ /// following:
82
+ ///
83
+ /// ```no_run
84
+ /// #![no_main]
85
+ ///
86
+ /// use libfuzzer_sys::{arbitrary::{Arbitrary, Unstructured}, fuzz_target};
87
+ ///
88
+ /// #[derive(Debug)]
89
+ /// pub struct Rgb {
90
+ /// r: u8,
91
+ /// g: u8,
92
+ /// b: u8,
93
+ /// }
94
+ ///
95
+ /// impl Arbitrary for Rgb {
96
+ /// fn arbitrary<U>(raw: &mut U) -> Result<Self, U::Error>
97
+ /// where
98
+ /// U: Unstructured + ?Sized
99
+ /// {
100
+ /// let mut buf = [0; 3];
101
+ /// raw.fill_buffer(&mut buf)?;
102
+ /// let r = buf[0];
103
+ /// let g = buf[1];
104
+ /// let b = buf[2];
105
+ /// Ok(Rgb { r, g, b })
106
+ /// }
107
+ /// }
108
+ ///
109
+ /// // Write a fuzz target that works with RGB colors instead of raw bytes.
110
+ /// fuzz_target!(|color: Rgb| {
111
+ /// my_crate::convert_color(color);
112
+ /// });
113
+ /// # mod my_crate { fn convert_color(_: super::Rgb) {} }
39
114
#[ macro_export]
40
115
macro_rules! fuzz_target {
41
116
( |$bytes: ident| $body: block) => {
@@ -44,9 +119,11 @@ macro_rules! fuzz_target {
44
119
$body
45
120
}
46
121
} ;
122
+
47
123
( |$data: ident: & [ u8 ] | $body: block) => {
48
124
fuzz_target!( |$data| $body) ;
49
125
} ;
126
+
50
127
( |$data: ident: $dty: ty| $body: block) => {
51
128
#[ no_mangle]
52
129
pub extern "C" fn rust_fuzzer_test_input( bytes: & [ u8 ] ) {
0 commit comments