Skip to content

Commit 18cee9d

Browse files
committed
Add docs and little clean ups
1 parent ff32cf5 commit 18cee9d

File tree

1 file changed

+79
-2
lines changed

1 file changed

+79
-2
lines changed

src/lib.rs

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
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+
114
pub use arbitrary;
215

316
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)]
619
fn rust_fuzzer_test_input(input: &[u8]);
720
}
821

22+
#[doc(hidden)]
923
#[export_name = "LLVMFuzzerTestOneInput"]
1024
pub 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"]
2439
pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize {
2540
// 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
3651
0
3752
}
3853

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) {} }
39114
#[macro_export]
40115
macro_rules! fuzz_target {
41116
(|$bytes:ident| $body:block) => {
@@ -44,9 +119,11 @@ macro_rules! fuzz_target {
44119
$body
45120
}
46121
};
122+
47123
(|$data:ident: &[u8]| $body:block) => {
48124
fuzz_target!(|$data| $body);
49125
};
126+
50127
(|$data:ident: $dty: ty| $body:block) => {
51128
#[no_mangle]
52129
pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) {

0 commit comments

Comments
 (0)