| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| use {arbitrary::Arbitrary, fuzz::fuzz}; |
| |
| // This is the "library code" tested in this example. |
| #[derive(Arbitrary)] |
| pub struct ToyStruct { |
| n: u8, |
| s: String, |
| } |
| |
| pub fn toy_example(input: ToyStruct) -> Result<u8, &'static str> { |
| if input.n != 42 { |
| return Err("n must be 42"); |
| } |
| let mut chars = input.s.chars(); |
| if chars.next() == Some('H') { |
| if chars.next() == Some('I') { |
| if chars.next() == Some('!') { |
| panic!("it works!"); |
| } |
| } |
| } |
| return Ok(0); |
| } |
| |
| // This is the "fuzzer code" for the library code above. |
| // It can typically be placed alongside that code and will only be compiled when fuzzing. |
| |
| // "Automatic" transform: Use one or more immutable types that implement `Arbitrary` as inputs. |
| #[fuzz] |
| fn toy_example_arbitrary(input1: ToyStruct, input2: ToyStruct) -> Result<u8, &'static str> { |
| let _ = toy_example(input1); |
| toy_example(input2) // Arbitrary return values are okay. |
| } |
| |
| // "Manual" transform: convert a reference to an immutable byte slice to inputs. |
| #[fuzz] |
| fn toy_example_u8(input: &[u8]) { |
| if input.len() == 0 { |
| return; // Early returns are okay. |
| } |
| let n = input[0]; |
| if let Ok(s) = std::str::from_utf8(&input[1..]) { |
| let _ = toy_example(ToyStruct { n, s: s.to_string() }); |
| } |
| } |
| |
| // You can reuse the same name with `[#fuzz]` in different modules. Compare this function with |
| // `helper::toy_example_same_name`. |
| #[fuzz] |
| fn toy_example_same_name(input: String) { |
| use helper; |
| helper::toy_example(helper::add_bang(input)); |
| } |