• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //! Support crate for writing fuzzers in Chrome OS.
6 //!
7 //! The major features provided by this crate are:
8 //!
9 //! * The [`fuzz_target`] macro which wraps the body of the fuzzing code with
10 //!   all with all the boilerplate needed to build and run it as a fuzzer on
11 //!   Chrome OS infrastructure.
12 //! * The [`FuzzRng`] type that provides a random number generator using fuzzer
13 //!   input as the source of its randomness.  Fuzzers that need to generate
14 //!   structured data can use this type in conjunction with the [`rand`] crate
15 //!   to generate the data they need.
16 //!
17 //! # Getting Started
18 //!
19 //! To use this crate add it as a dependency to the fuzzer's `Cargo.toml` along
20 //! with the crate to be fuzzed:
21 //!
22 //! ```Cargo.toml
23 //! [dependencies]
24 //! cros_fuzz = "*"
25 //! your_crate = "*"
26 //! ```
27 //!
28 //! Then use the [`fuzz_target`] macro to write the body of the fuzzer.  All
29 //! fuzzers should use the `#![no_main]` crate attribute as the main function
30 //! will be provided by the fuzzer runtime.
31 //!
32 //! ```rust,ignore
33 //! #![no_main]
34 //!
35 //! use cros_fuzz::fuzz_target;
36 //! use your_crate::some_function;
37 //!
38 //! fuzz_target!(|data: &[u8]| {
39 //!     some_function(data);
40 //! });
41 //! ```
42 //!
43 //! [`FuzzRng`]: rand/struct.FuzzRng.html
44 //! [`fuzz_target`]: macro.fuzz_target.html
45 //! [`rand`]: https://docs.rs/rand
46 
47 pub mod rand;
48 
49 /// The main macro for writing a fuzzer.  The fuzzer runtime will repeatedly
50 /// call the body of `fuzz_target!` with a slice of pseudo-random bytes, until
51 /// your program hits an error condition (segfault, panic, etc).
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use std::str;
57 /// # #[macro_use] extern crate cros_fuzz;
58 ///
59 /// fuzz_target!(|data: &[u8]| {
60 ///     let _ = str::from_utf8(data);
61 /// });
62 ///
63 /// # fn main() {
64 /// #    let buf = b"hello, world!";
65 /// #    llvm_fuzzer_test_one_input(buf.as_ptr(), buf.len());
66 /// # }
67 /// ```
68 #[macro_export]
69 macro_rules! fuzz_target {
70     (|$bytes:ident| $body:block) => {
71         use std::panic;
72         use std::process;
73         use std::slice;
74 
75         #[export_name = "LLVMFuzzerTestOneInput"]
76         fn llvm_fuzzer_test_one_input(data: *const u8, size: usize) -> i32 {
77             // We cannot unwind past ffi boundaries.
78             panic::catch_unwind(|| {
79                 // Safe because the libfuzzer runtime will guarantee that `data` is
80                 // at least `size` bytes long and that it will be valid for the lifetime
81                 // of this function.
82                 let $bytes = unsafe { slice::from_raw_parts(data, size) };
83 
84                 $body
85             })
86             .err()
87             .map(|_| process::abort());
88 
89             0
90         }
91     };
92     (|$bytes:ident: &[u8]| $body:block) => {
93         fuzz_target!(|$bytes| $body);
94     };
95 }
96