//! The `Arbitrary` trait crate. //! //! This trait provides an [`Arbitrary`](./trait.Arbitrary.html) trait to //! produce well-typed, structured values, from raw, byte buffers. It is //! generally intended to be used with fuzzers like AFL or libFuzzer. See the //! [`Arbitrary`](./trait.Arbitrary.html) trait's documentation for details on //! automatically deriving, implementing, and/or using the trait.
use core::array; use core::cell::{Cell, RefCell, UnsafeCell}; use core::iter; use core::mem; use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize}; use core::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize}; use core::ops::{Range, RangeBounds, RangeFrom, RangeInclusive, RangeTo, RangeToInclusive}; use core::str; use core::time::Duration; use std::borrow::{Cow, ToOwned}; use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; use std::ffi::{CString, OsString}; use std::hash::BuildHasher; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::ops::Bound; use std::path::PathBuf; use std::rc::Rc; use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize}; use std::sync::{Arc, Mutex};
/// Generate arbitrary structured values from raw, unstructured data. /// /// The `Arbitrary` trait allows you to generate valid structured values, like /// `HashMap`s, or ASTs, or `MyTomlConfig`, or any other data structure from /// raw, unstructured bytes provided by a fuzzer. /// /// # Deriving `Arbitrary` /// /// Automatically deriving the `Arbitrary` trait is the recommended way to /// implement `Arbitrary` for your types. /// /// Using the custom derive requires that you enable the `"derive"` cargo /// feature in your `Cargo.toml`: /// /// ```toml /// [dependencies] /// arbitrary = { version = "1", features = ["derive"] } /// ``` /// /// Then, you add the `#[derive(Arbitrary)]` annotation to your `struct` or /// `enum` type definition: /// /// ``` /// # #[cfg(feature = "derive")] mod foo { /// use arbitrary::Arbitrary; /// use std::collections::HashSet; /// /// #[derive(Arbitrary)] /// pub struct AddressBook { /// friends: HashSet<Friend>, /// } /// /// #[derive(Arbitrary, Hash, Eq, PartialEq)] /// pub enum Friend { /// Buddy { name: String }, /// Pal { age: usize }, /// } /// # } /// ``` /// /// Every member of the `struct` or `enum` must also implement `Arbitrary`. /// /// # Implementing `Arbitrary` By Hand /// /// Implementing `Arbitrary` mostly involves nested calls to other `Arbitrary` /// arbitrary implementations for each of your `struct` or `enum`'s members. But /// sometimes you need some amount of raw data, or you need to generate a /// variably-sized collection type, or something of that sort. The /// [`Unstructured`][crate::Unstructured] type helps you with these tasks. /// /// ``` /// # #[cfg(feature = "derive")] mod foo { /// # pub struct MyCollection<T> { _t: std::marker::PhantomData<T> } /// # impl<T> MyCollection<T> { /// # pub fn new() -> Self { MyCollection { _t: std::marker::PhantomData } } /// # pub fn insert(&mut self, element: T) {} /// # } /// use arbitrary::{Arbitrary, Result, Unstructured}; /// /// impl<'a, T> Arbitrary<'a> for MyCollection<T> /// where /// T: Arbitrary<'a>, /// { /// fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { /// // Get an iterator of arbitrary `T`s. /// let iter = u.arbitrary_iter::<T>()?; /// /// // And then create a collection! /// let mut my_collection = MyCollection::new(); /// for elem_result in iter { /// let elem = elem_result?; /// my_collection.insert(elem); /// } /// /// Ok(my_collection) /// } /// } /// # } /// ``` pubtrait Arbitrary<'a>: Sized { /// Generate an arbitrary value of `Self` from the given unstructured data. /// /// Calling `Arbitrary::arbitrary` requires that you have some raw data, /// perhaps given to you by a fuzzer like AFL or libFuzzer. You wrap this /// raw data in an `Unstructured`, and then you can call `<MyType as /// Arbitrary>::arbitrary` to construct an arbitrary instance of `MyType` /// from that unstructured data. /// /// Implementations may return an error if there is not enough data to /// construct a full instance of `Self`, or they may fill out the rest of /// `Self` with dummy values. Using dummy values when the underlying data is /// exhausted can help avoid accidentally "defeating" some of the fuzzer's /// mutations to the underlying byte stream that might otherwise lead to /// interesting runtime behavior or new code coverage if only we had just a /// few more bytes. However, it also requires that implementations for /// recursive types (e.g. `struct Foo(Option<Box<Foo>>)`) avoid infinite /// recursion when the underlying data is exhausted. /// /// ``` /// # #[cfg(feature = "derive")] fn foo() { /// use arbitrary::{Arbitrary, Unstructured}; /// /// #[derive(Arbitrary)] /// pub struct MyType { /// // ... /// } /// /// // Get the raw data from the fuzzer or wherever else. /// # let get_raw_data_from_fuzzer = || &[]; /// let raw_data: &[u8] = get_raw_data_from_fuzzer(); /// /// // Wrap that raw data in an `Unstructured`. /// let mut unstructured = Unstructured::new(raw_data); /// /// // Generate an arbitrary instance of `MyType` and do stuff with it. /// if let Ok(value) = MyType::arbitrary(&mut unstructured) { /// # let do_stuff = |_| {}; /// do_stuff(value); /// } /// # } /// ``` /// /// See also the documentation for [`Unstructured`][crate::Unstructured]. fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self>;
/// Generate an arbitrary value of `Self` from the entirety of the given /// unstructured data. /// /// This is similar to Arbitrary::arbitrary, however it assumes that it is /// the last consumer of the given data, and is thus able to consume it all /// if it needs. See also the documentation for /// [`Unstructured`][crate::Unstructured]. fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<Self> { Self::arbitrary(&mut u)
}
/// Get a size hint for how many bytes out of an `Unstructured` this type /// needs to construct itself. /// /// This is useful for determining how many elements we should insert when /// creating an arbitrary collection. /// /// The return value is similar to /// [`Iterator::size_hint`][iterator-size-hint]: it returns a tuple where /// the first element is a lower bound on the number of bytes required, and /// the second element is an optional upper bound. /// /// The default implementation return `(0, None)` which is correct for any /// type, but not ultimately that useful. Using `#[derive(Arbitrary)]` will /// create a better implementation. If you are writing an `Arbitrary` /// implementation by hand, and your type can be part of a dynamically sized /// collection (such as `Vec`), you are strongly encouraged to override this /// default with a better implementation. The /// [`size_hint`][crate::size_hint] module will help with this task. /// /// ## Invariant /// /// It must be possible to construct every possible output using only inputs /// of lengths bounded by these parameters. This applies to both /// [`Arbitrary::arbitrary`] and [`Arbitrary::arbitrary_take_rest`]. /// /// This is trivially true for `(0, None)`. To restrict this further, it /// must be proven that all inputs that are now excluded produced redundant /// outputs which are still possible to produce using the reduced input /// space. /// /// ## The `depth` Parameter /// /// If you 100% know that the type you are implementing `Arbitrary` for is /// not a recursive type, or your implementation is not transitively calling /// any other `size_hint` methods, you can ignore the `depth` parameter. /// Note that if you are implementing `Arbitrary` for a generic type, you /// cannot guarantee the lack of type recursion! /// /// Otherwise, you need to use /// [`arbitrary::size_hint::recursion_guard(depth)`][crate::size_hint::recursion_guard] /// to prevent potential infinite recursion when calculating size hints for /// potentially recursive types: /// /// ``` /// use arbitrary::{Arbitrary, Unstructured, size_hint}; /// /// // This can potentially be a recursive type if `L` or `R` contain /// // something like `Box<Option<MyEither<L, R>>>`! /// enum MyEither<L, R> { /// Left(L), /// Right(R), /// } /// /// impl<'a, L, R> Arbitrary<'a> for MyEither<L, R> /// where /// L: Arbitrary<'a>, /// R: Arbitrary<'a>, /// { /// fn arbitrary(u: &mut Unstructured) -> arbitrary::Result<Self> { /// // ... /// # unimplemented!() /// } /// /// fn size_hint(depth: usize) -> (usize, Option<usize>) { /// // Protect against potential infinite recursion with /// // `recursion_guard`. /// size_hint::recursion_guard(depth, |depth| { /// // If we aren't too deep, then `recursion_guard` calls /// // this closure, which implements the natural size hint. /// // Don't forget to use the new `depth` in all nested /// // `size_hint` calls! We recommend shadowing the /// // parameter, like what is done here, so that you can't /// // accidentally use the wrong depth. /// size_hint::or( /// <L as Arbitrary>::size_hint(depth), /// <R as Arbitrary>::size_hint(depth), /// ) /// }) /// } /// } /// ``` /// /// [iterator-size-hint]: https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.size_hint #[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { let _ = depth;
(0, None)
}
}
impl<'a> Arbitrary<'a> for char { fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { use std::char; // The highest unicode code point is 0x11_FFFF const CHAR_END: u32 = 0x11_0000; // The size of the surrogate blocks const SURROGATES_START: u32 = 0xD800; letmut c = <u32 as Arbitrary<'a>>::arbitrary(u)? % CHAR_END; iflet Some(c) = char::from_u32(c) {
Ok(c)
} else { // We found a surrogate, wrap and try again
c -= SURROGATES_START;
Ok(char::from_u32(c)
.expect("Generated character should be valid! This is a bug in arbitrary-rs"))
}
}
#[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { crate::size_hint::and_all(&[
<$last as Arbitrary>::size_hint(depth),
$( <$xs as Arbitrary>::size_hint(depth) ),*
])
}
}
};
}
arbitrary_tuple!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z);
// Helper to safely create arrays since the standard library doesn't // provide one yet. Shouldn't be necessary in the future. struct ArrayGuard<T, const N: usize> {
dst: *mut T,
initialized: usize,
}
impl<T, const N: usize> Drop for ArrayGuard<T, N> { fn drop(&mutself) {
debug_assert!(self.initialized <= N); let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized); unsafe {
core::ptr::drop_in_place(initialized_part);
}
}
}
impl<'a, A> Arbitrary<'a> for Cow<'a, A> where
A: ToOwned + ?Sized,
<A as ToOwned>::Owned: Arbitrary<'a>,
{ fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
Arbitrary::arbitrary(u).map(Cow::Owned)
}
#[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { crate::size_hint::recursion_guard(depth, |depth| {
<<A as ToOwned>::Owned as Arbitrary>::size_hint(depth)
})
}
}
fn arbitrary_str<'a>(u: &mut Unstructured<'a>, size: usize) -> Result<&'a str> { match str::from_utf8(u.peek_bytes(size).unwrap()) {
Ok(s) => {
u.bytes(size).unwrap();
Ok(s)
}
Err(e) => { let i = e.valid_up_to(); let valid = u.bytes(i).unwrap(); let s = unsafe {
debug_assert!(str::from_utf8(valid).is_ok());
str::from_utf8_unchecked(valid)
};
Ok(s)
}
}
}
impl<'a> Arbitrary<'a> for &'a str { fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { let size = u.arbitrary_len::<u8>()?;
arbitrary_str(u, size)
}
fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<Self> { let size = u.len();
arbitrary_str(&mut u, size)
}
/// Assert that the given expected values are all generated. /// /// Exhaustively enumerates all buffers up to length 10 containing the /// following bytes: `0x00`, `0x01`, `0x61` (aka ASCII 'a'), and `0xff` fn assert_generates<T>(expected_values: impl IntoIterator<Item = T>) where
T: Clone + std::fmt::Debug + std::hash::Hash + Eq + for<'a> Arbitrary<'a>,
{ let expected_values: HashSet<_> = expected_values.into_iter().collect(); letmut arbitrary_expected = expected_values.clone(); letmut arbitrary_take_rest_expected = expected_values;
let bytes = [0, 1, b'a', 0xff]; let max_len = 10;
letmut buf = Vec::with_capacity(max_len);
letmut g = exhaustigen::Gen::new(); while !g.done() { let len = g.gen(max_len);
buf.clear();
buf.extend(
std::iter::repeat_with(|| { let index = g.gen(bytes.len() - 1);
bytes[index]
})
.take(len),
);
letmut u = Unstructured::new(&buf); let val = T::arbitrary(&mut u).unwrap();
arbitrary_expected.remove(&val);
let u = Unstructured::new(&buf); let val = T::arbitrary_take_rest(u).unwrap();
arbitrary_take_rest_expected.remove(&val);
if arbitrary_expected.is_empty() && arbitrary_take_rest_expected.is_empty() { return;
}
}
panic!( "failed to generate all expected values!\n\n\
T::arbitrary did not generate: {arbitrary_expected:#?}\n\n\
T::arbitrary_take_rest did not generate {arbitrary_take_rest_expected:#?}"
)
}
/// Generates an arbitrary `T`, and checks that the result is consistent with the /// `size_hint()` reported by `T`. fn checked_arbitrary<'a, T: Arbitrary<'a>>(u: &mut Unstructured<'a>) -> Result<T> { let (min, max) = T::size_hint(0);
let len_before = u.len(); let result = T::arbitrary(u);
#[test] fn arbitrary_for_bytes() { let x = [1, 2, 3, 4, 4]; letmut buf = Unstructured::new(&x); let expected = &[1, 2, 3, 4]; let actual = checked_arbitrary::<&[u8]>(&mut buf).unwrap();
assert_eq!(expected, actual);
}
#[test] fn arbitrary_take_rest_for_bytes() { let x = [1, 2, 3, 4]; let buf = Unstructured::new(&x); let expected = &[1, 2, 3, 4]; let actual = checked_arbitrary_take_rest::<&[u8]>(buf).unwrap();
assert_eq!(expected, actual);
}
// Cannot consume all but can consume part of the input
assert_eq!(
checked_arbitrary_take_rest::<String>(Unstructured::new(&[1, 0xFF, 2])).unwrap(), "\x01"
);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.