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