| // Copyright 2019 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| //! Support crate for writing fuzzers in Chrome OS. |
| //! |
| //! The major features provided by this crate are: |
| //! |
| //! * The [`fuzz_target`] macro which wraps the body of the fuzzing code with |
| //! all with all the boilerplate needed to build and run it as a fuzzer on |
| //! Chrome OS infrastructure. |
| //! * The [`FuzzRng`] type that provides a random number generator using fuzzer |
| //! input as the source of its randomness. Fuzzers that need to generate |
| //! structured data can use this type in conjunction with the [`rand`] crate |
| //! to generate the data they need. |
| //! |
| //! # Getting Started |
| //! |
| //! To use this crate add it as a dependency to the fuzzer's `Cargo.toml` along |
| //! with the crate to be fuzzed: |
| //! |
| //! ```Cargo.toml |
| //! [dependencies] |
| //! cros_fuzz = "*" |
| //! your_crate = "*" |
| //! ``` |
| //! |
| //! Then use the [`fuzz_target`] macro to write the body of the fuzzer. All |
| //! fuzzers should use the `#![no_main]` crate attribute as the main function |
| //! will be provided by the fuzzer runtime. |
| //! |
| //! ```rust,ignore |
| //! #![no_main] |
| //! |
| //! use cros_fuzz::fuzz_target; |
| //! use your_crate::some_function; |
| //! |
| //! fuzz_target!(|data: &[u8]| { |
| //! some_function(data); |
| //! }); |
| //! ``` |
| //! |
| //! [`FuzzRng`]: rand/struct.FuzzRng.html |
| //! [`fuzz_target`]: macro.fuzz_target.html |
| //! [`rand`]: https://docs.rs/rand |
| |
| pub mod rand; |
| |
| /// The main macro for writing a fuzzer. The fuzzer runtime will repeatedly |
| /// call the body of `fuzz_target!` with a slice of pseudo-random bytes, until |
| /// your program hits an error condition (segfault, panic, etc). |
| /// |
| /// # Examples |
| /// |
| /// ``` |
| /// use std::str; |
| /// # #[macro_use] extern crate cros_fuzz; |
| /// |
| /// fuzz_target!(|data: &[u8]| { |
| /// let _ = str::from_utf8(data); |
| /// }); |
| /// |
| /// # fn main() { |
| /// # let buf = b"hello, world!"; |
| /// # llvm_fuzzer_test_one_input(buf.as_ptr(), buf.len()); |
| /// # } |
| /// ``` |
| #[macro_export] |
| macro_rules! fuzz_target { |
| (|$bytes:ident| $body:block) => { |
| use std::panic; |
| use std::process; |
| use std::slice; |
| |
| #[export_name = "LLVMFuzzerTestOneInput"] |
| fn llvm_fuzzer_test_one_input(data: *const u8, size: usize) -> i32 { |
| // We cannot unwind past ffi boundaries. |
| panic::catch_unwind(|| { |
| // Safe because the libfuzzer runtime will guarantee that `data` is |
| // at least `size` bytes long and that it will be valid for the lifetime |
| // of this function. |
| let $bytes = unsafe { slice::from_raw_parts(data, size) }; |
| |
| $body |
| }) |
| .err() |
| .map(|_| process::abort()); |
| |
| 0 |
| } |
| }; |
| (|$bytes:ident: &[u8]| $body:block) => { |
| fuzz_target!(|$bytes| $body); |
| }; |
| } |