// Copyright © 2019 The Rust Fuzz Project Developers. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! 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. #![deny(bad_style)] #![deny(missing_docs)] #![deny(future_incompatible)] #![deny(nonstandard_style)] #![deny(rust_2018_compatibility)] #![deny(rust_2018_idioms)] #![deny(unused)] #[cfg(feature = "derive_arbitrary")] pub use derive_arbitrary::*; mod error; pub use error::*; pub mod unstructured; #[doc(inline)] pub use unstructured::Unstructured; pub mod size_hint; 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::{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, /// } /// /// #[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: std::marker::PhantomData } /// # impl MyCollection { /// # 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 /// where /// T: Arbitrary<'a>, /// { /// fn arbitrary(u: &mut Unstructured<'a>) -> Result { /// // Get an iterator of arbitrary `T`s. /// let iter = u.arbitrary_iter::()?; /// /// // 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) /// } /// } /// # } /// ``` pub trait 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 `::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>)`) 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; /// 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::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>>`! /// enum MyEither { /// Left(L), /// Right(R), /// } /// /// impl<'a, L, R> Arbitrary<'a> for MyEither /// where /// L: Arbitrary<'a>, /// R: Arbitrary<'a>, /// { /// fn arbitrary(u: &mut Unstructured) -> arbitrary::Result { /// // ... /// # unimplemented!() /// } /// /// fn size_hint(depth: usize) -> (usize, Option) { /// // 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( /// ::size_hint(depth), /// ::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) { let _ = depth; (0, None) } } impl<'a> Arbitrary<'a> for () { fn arbitrary(_: &mut Unstructured<'a>) -> Result { Ok(()) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) } } impl<'a> Arbitrary<'a> for bool { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(>::arbitrary(u)? & 1 == 1) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } macro_rules! impl_arbitrary_for_integers { ( $( $ty:ty: $unsigned:ty; )* ) => { $( impl<'a> Arbitrary<'a> for $ty { fn arbitrary(u: &mut Unstructured<'a>) -> Result { let mut buf = [0; mem::size_of::<$ty>()]; u.fill_buffer(&mut buf)?; let mut x: $unsigned = 0; for i in 0..mem::size_of::<$ty>() { x |= buf[i] as $unsigned << (i * 8); } Ok(x as $ty) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { let n = mem::size_of::<$ty>(); (n, Some(n)) } } )* } } impl_arbitrary_for_integers! { u8: u8; u16: u16; u32: u32; u64: u64; u128: u128; usize: usize; i8: u8; i16: u16; i32: u32; i64: u64; i128: u128; isize: usize; } macro_rules! impl_arbitrary_for_floats { ( $( $ty:ident : $unsigned:ty; )* ) => { $( impl<'a> Arbitrary<'a> for $ty { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?)) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { <$unsigned as Arbitrary<'a>>::size_hint(depth) } } )* } } impl_arbitrary_for_floats! { f32: u32; f64: u64; } impl<'a> Arbitrary<'a> for char { fn arbitrary(u: &mut Unstructured<'a>) -> Result { 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; let mut c = >::arbitrary(u)? % CHAR_END; if let 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) { >::size_hint(depth) } } impl<'a> Arbitrary<'a> for AtomicBool { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a> Arbitrary<'a> for AtomicIsize { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a> Arbitrary<'a> for AtomicUsize { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } macro_rules! impl_range { ( $range:ty, $value_closure:expr, $value_ty:ty, $fun:ident($fun_closure:expr), $size_hint_closure:expr ) => { impl<'a, A> Arbitrary<'a> for $range where A: Arbitrary<'a> + Clone + PartialOrd, { fn arbitrary(u: &mut Unstructured<'a>) -> Result { let value: $value_ty = Arbitrary::arbitrary(u)?; Ok($fun(value, $fun_closure)) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { $size_hint_closure(depth) } } }; } impl_range!( Range, |r: &Range| (r.start.clone(), r.end.clone()), (A, A), bounded_range(|(a, b)| a..b), |depth| crate::size_hint::and( ::size_hint(depth), ::size_hint(depth) ) ); impl_range!( RangeFrom, |r: &RangeFrom| r.start.clone(), A, unbounded_range(|a| a..), |depth| ::size_hint(depth) ); impl_range!( RangeInclusive, |r: &RangeInclusive| (r.start().clone(), r.end().clone()), (A, A), bounded_range(|(a, b)| a..=b), |depth| crate::size_hint::and( ::size_hint(depth), ::size_hint(depth) ) ); impl_range!( RangeTo, |r: &RangeTo| r.end.clone(), A, unbounded_range(|b| ..b), |depth| ::size_hint(depth) ); impl_range!( RangeToInclusive, |r: &RangeToInclusive| r.end.clone(), A, unbounded_range(|b| ..=b), |depth| ::size_hint(depth) ); pub(crate) fn bounded_range(bounds: (I, I), cb: CB) -> R where CB: Fn((I, I)) -> R, I: PartialOrd, R: RangeBounds, { let (mut start, mut end) = bounds; if start > end { mem::swap(&mut start, &mut end); } cb((start, end)) } pub(crate) fn unbounded_range(bound: I, cb: CB) -> R where CB: Fn(I) -> R, R: RangeBounds, { cb(bound) } impl<'a> Arbitrary<'a> for Duration { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(Self::new( ::arbitrary(u)?, u.int_in_range(0..=999_999_999)?, )) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( ::size_hint(depth), ::size_hint(depth), ) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Option { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(if >::arbitrary(u)? { Some(Arbitrary::arbitrary(u)?) } else { None }) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( ::size_hint(depth), crate::size_hint::or((0, Some(0)), ::size_hint(depth)), ) } } impl<'a, A: Arbitrary<'a>, B: Arbitrary<'a>> Arbitrary<'a> for std::result::Result { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(if >::arbitrary(u)? { Ok(::arbitrary(u)?) } else { Err(::arbitrary(u)?) }) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::and( ::size_hint(depth), crate::size_hint::or( ::size_hint(depth), ::size_hint(depth), ), ) } } macro_rules! arbitrary_tuple { () => {}; ($last: ident $($xs: ident)*) => { arbitrary_tuple!($($xs)*); impl<'a, $($xs: Arbitrary<'a>,)* $last: Arbitrary<'a>> Arbitrary<'a> for ($($xs,)* $last,) { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) } #[allow(unused_mut, non_snake_case)] fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { $(let $xs = $xs::arbitrary(&mut u)?;)* let $last = $last::arbitrary_take_rest(u)?; Ok(($($xs,)* $last,)) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { 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 { dst: *mut T, initialized: usize, } impl Drop for ArrayGuard { fn drop(&mut self) { 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); } } } fn try_create_array(mut cb: F) -> Result<[T; N]> where F: FnMut(usize) -> Result, { let mut array: mem::MaybeUninit<[T; N]> = mem::MaybeUninit::uninit(); let array_ptr = array.as_mut_ptr(); let dst = array_ptr as _; let mut guard: ArrayGuard = ArrayGuard { dst, initialized: 0, }; unsafe { for (idx, value_ptr) in (*array.as_mut_ptr()).iter_mut().enumerate() { core::ptr::write(value_ptr, cb(idx)?); guard.initialized += 1; } mem::forget(guard); Ok(array.assume_init()) } } impl<'a, T, const N: usize> Arbitrary<'a> for [T; N] where T: Arbitrary<'a>, { #[inline] fn arbitrary(u: &mut Unstructured<'a>) -> Result { try_create_array(|_| >::arbitrary(u)) } #[inline] fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result { let mut array = Self::arbitrary(&mut u)?; if let Some(last) = array.last_mut() { *last = Arbitrary::arbitrary_take_rest(u)?; } Ok(array) } #[inline] fn size_hint(d: usize) -> (usize, Option) { crate::size_hint::and_all(&array::from_fn::<_, N, _>(|_| { ::size_hint(d) })) } } impl<'a> Arbitrary<'a> for &'a [u8] { fn arbitrary(u: &mut Unstructured<'a>) -> Result { let len = u.arbitrary_len::()?; u.bytes(len) } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { Ok(u.take_rest()) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Vec { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, K: Arbitrary<'a> + Ord, V: Arbitrary<'a>> Arbitrary<'a> for BTreeMap { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a> + Ord> Arbitrary<'a> for BTreeSet { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Bound { fn arbitrary(u: &mut Unstructured<'a>) -> Result { match u.int_in_range::(0..=2)? { 0 => Ok(Bound::Included(A::arbitrary(u)?)), 1 => Ok(Bound::Excluded(A::arbitrary(u)?)), 2 => Ok(Bound::Unbounded), _ => unreachable!(), } } #[inline] fn size_hint(depth: usize) -> (usize, Option) { size_hint::or( size_hint::and((1, Some(1)), A::size_hint(depth)), (1, Some(1)), ) } } impl<'a, A: Arbitrary<'a> + Ord> Arbitrary<'a> for BinaryHeap { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, K: Arbitrary<'a> + Eq + ::std::hash::Hash, V: Arbitrary<'a>, S: BuildHasher + Default> Arbitrary<'a> for HashMap { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a> + Eq + ::std::hash::Hash, S: BuildHasher + Default> Arbitrary<'a> for HashSet { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for LinkedList { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for VecDeque { fn arbitrary(u: &mut Unstructured<'a>) -> Result { u.arbitrary_iter()?.collect() } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { u.arbitrary_take_rest_iter()?.collect() } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a, A> Arbitrary<'a> for Cow<'a, A> where A: ToOwned + ?Sized, ::Owned: Arbitrary<'a>, { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Cow::Owned) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, |depth| { <::Owned as Arbitrary>::size_hint(depth) }) } } impl<'a> Arbitrary<'a> for &'a str { fn arbitrary(u: &mut Unstructured<'a>) -> Result { let size = u.arbitrary_len::()?; 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) } } } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { let bytes = u.take_rest(); str::from_utf8(bytes).map_err(|_| Error::IncorrectFormat) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, None) } } impl<'a> Arbitrary<'a> for String { fn arbitrary(u: &mut Unstructured<'a>) -> Result { <&str as Arbitrary>::arbitrary(u).map(Into::into) } fn arbitrary_take_rest(u: Unstructured<'a>) -> Result { <&str as Arbitrary>::arbitrary_take_rest(u).map(Into::into) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { <&str as Arbitrary>::size_hint(depth) } } impl<'a> Arbitrary<'a> for CString { fn arbitrary(u: &mut Unstructured<'a>) -> Result { as Arbitrary>::arbitrary(u).map(|mut x| { x.retain(|&c| c != 0); Self::new(x).unwrap() }) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { as Arbitrary>::size_hint(depth) } } impl<'a> Arbitrary<'a> for OsString { fn arbitrary(u: &mut Unstructured<'a>) -> Result { ::arbitrary(u).map(From::from) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) } } impl<'a> Arbitrary<'a> for PathBuf { fn arbitrary(u: &mut Unstructured<'a>) -> Result { ::arbitrary(u).map(From::from) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, ::size_hint) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<[A]> { fn arbitrary(u: &mut Unstructured<'a>) -> Result { as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_slice()) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { as Arbitrary>::size_hint(depth) } } impl<'a> Arbitrary<'a> for Box { fn arbitrary(u: &mut Unstructured<'a>) -> Result { ::arbitrary(u).map(|x| x.into_boxed_str()) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { ::size_hint(depth) } } // impl Arbitrary for Box { // fn arbitrary(u: &mut Unstructured<'_>) -> Result { // ::arbitrary(u).map(|x| x.into_boxed_c_str()) // } // } // impl Arbitrary for Box { // fn arbitrary(u: &mut Unstructured<'_>) -> Result { // ::arbitrary(u).map(|x| x.into_boxed_osstr()) // // } // } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Arc { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, ::size_hint) } } impl<'a> Arbitrary<'a> for Arc { fn arbitrary(u: &mut Unstructured<'a>) -> Result { <&str as Arbitrary>::arbitrary(u).map(Into::into) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { <&str as Arbitrary>::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Rc { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { crate::size_hint::recursion_guard(depth, ::size_hint) } } impl<'a> Arbitrary<'a> for Rc { fn arbitrary(u: &mut Unstructured<'a>) -> Result { <&str as Arbitrary>::arbitrary(u).map(Into::into) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { <&str as Arbitrary>::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Cell { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for RefCell { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for UnsafeCell { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Mutex { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(Self::new) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for iter::Empty { fn arbitrary(_: &mut Unstructured<'a>) -> Result { Ok(iter::empty()) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::marker::PhantomData { fn arbitrary(_: &mut Unstructured<'a>) -> Result { Ok(::std::marker::PhantomData) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (0, Some(0)) } } impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::num::Wrapping { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Arbitrary::arbitrary(u).map(::std::num::Wrapping) } #[inline] fn size_hint(depth: usize) -> (usize, Option) { >::size_hint(depth) } } macro_rules! implement_nonzero_int { ($nonzero:ty, $int:ty) => { impl<'a> Arbitrary<'a> for $nonzero { fn arbitrary(u: &mut Unstructured<'a>) -> Result { match Self::new(<$int as Arbitrary<'a>>::arbitrary(u)?) { Some(n) => Ok(n), None => Err(Error::IncorrectFormat), } } #[inline] fn size_hint(depth: usize) -> (usize, Option) { <$int as Arbitrary<'a>>::size_hint(depth) } } }; } implement_nonzero_int! { NonZeroI8, i8 } implement_nonzero_int! { NonZeroI16, i16 } implement_nonzero_int! { NonZeroI32, i32 } implement_nonzero_int! { NonZeroI64, i64 } implement_nonzero_int! { NonZeroI128, i128 } implement_nonzero_int! { NonZeroIsize, isize } implement_nonzero_int! { NonZeroU8, u8 } implement_nonzero_int! { NonZeroU16, u16 } implement_nonzero_int! { NonZeroU32, u32 } implement_nonzero_int! { NonZeroU64, u64 } implement_nonzero_int! { NonZeroU128, u128 } implement_nonzero_int! { NonZeroUsize, usize } impl<'a> Arbitrary<'a> for Ipv4Addr { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(Ipv4Addr::from(u32::arbitrary(u)?)) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (4, Some(4)) } } impl<'a> Arbitrary<'a> for Ipv6Addr { fn arbitrary(u: &mut Unstructured<'a>) -> Result { Ok(Ipv6Addr::from(u128::arbitrary(u)?)) } #[inline] fn size_hint(_depth: usize) -> (usize, Option) { (16, Some(16)) } } #[cfg(test)] mod test { use super::*; /// 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 { let (min, max) = T::size_hint(0); let len_before = u.len(); let result = T::arbitrary(u); let consumed = len_before - u.len(); if let Some(max) = max { assert!( consumed <= max, "incorrect maximum size: indicated {}, actually consumed {}", max, consumed ); } if result.is_ok() { assert!( consumed >= min, "incorrect minimum size: indicated {}, actually consumed {}", min, consumed ); } result } /// Like `checked_arbitrary()`, but calls `arbitrary_take_rest()` instead of `arbitrary()`. fn checked_arbitrary_take_rest<'a, T: Arbitrary<'a>>(u: Unstructured<'a>) -> Result { let (min, _) = T::size_hint(0); let len_before = u.len(); let result = T::arbitrary_take_rest(u); if result.is_ok() { assert!( len_before >= min, "incorrect minimum size: indicated {}, worked with {}", min, len_before ); } result } #[test] fn finite_buffer_fill_buffer() { let x = [1, 2, 3, 4]; let mut rb = Unstructured::new(&x); let mut z = [0; 2]; rb.fill_buffer(&mut z).unwrap(); assert_eq!(z, [1, 2]); rb.fill_buffer(&mut z).unwrap(); assert_eq!(z, [3, 4]); rb.fill_buffer(&mut z).unwrap(); assert_eq!(z, [0, 0]); } #[test] fn arbitrary_for_integers() { let x = [1, 2, 3, 4]; let mut buf = Unstructured::new(&x); let expected = 1 | (2 << 8) | (3 << 16) | (4 << 24); let actual = checked_arbitrary::(&mut buf).unwrap(); assert_eq!(expected, actual); } #[test] fn arbitrary_for_bytes() { let x = [1, 2, 3, 4, 4]; let mut 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); } #[test] fn arbitrary_collection() { let x = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 12, ]; assert_eq!( checked_arbitrary::<&[u8]>(&mut Unstructured::new(&x)).unwrap(), &[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3] ); assert_eq!( checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[2, 4, 6, 8, 1] ); assert_eq!( checked_arbitrary::>(&mut Unstructured::new(&x)).unwrap(), &[84148994] ); assert_eq!( checked_arbitrary::(&mut Unstructured::new(&x)).unwrap(), "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x01\x02\x03" ); } #[test] fn arbitrary_take_rest() { let x = [1, 2, 3, 4]; assert_eq!( checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&x)).unwrap(), &[1, 2, 3, 4] ); assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[1, 2, 3, 4] ); assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&x)).unwrap(), &[0x4030201] ); assert_eq!( checked_arbitrary_take_rest::(Unstructured::new(&x)).unwrap(), "\x01\x02\x03\x04" ); assert_eq!( checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&[])).unwrap(), &[] ); assert_eq!( checked_arbitrary_take_rest::>(Unstructured::new(&[])).unwrap(), &[] ); } #[test] fn size_hint_for_tuples() { assert_eq!( (7, Some(7)), <(bool, u16, i32) as Arbitrary<'_>>::size_hint(0) ); assert_eq!((1, None), <(u8, Vec) as Arbitrary>::size_hint(0)); } } /// Multiple conflicting arbitrary attributes are used on the same field: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// struct Point { /// #[arbitrary(value = 2)] /// #[arbitrary(value = 2)] /// x: i32, /// } /// ``` /// /// An unknown attribute: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// struct Point { /// #[arbitrary(unknown_attr)] /// x: i32, /// } /// ``` /// /// An unknown attribute with a value: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// struct Point { /// #[arbitrary(unknown_attr = 13)] /// x: i32, /// } /// ``` /// /// `value` without RHS: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// struct Point { /// #[arbitrary(value)] /// x: i32, /// } /// ``` /// /// `with` without RHS: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// struct Point { /// #[arbitrary(with)] /// x: i32, /// } /// ``` /// /// Multiple conflicting bounds at the container-level: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// #[arbitrary(bound = "T: Default")] /// #[arbitrary(bound = "T: Default")] /// struct Point { /// #[arbitrary(default)] /// x: T, /// } /// ``` /// /// Multiple conflicting bounds in a single bound attribute: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// #[arbitrary(bound = "T: Default, T: Default")] /// struct Point { /// #[arbitrary(default)] /// x: T, /// } /// ``` /// /// Multiple conflicting bounds in multiple bound attributes: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// #[arbitrary(bound = "T: Default", bound = "T: Default")] /// struct Point { /// #[arbitrary(default)] /// x: T, /// } /// ``` /// /// Too many bounds supplied: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// #[arbitrary(bound = "T: Default")] /// struct Point { /// x: i32, /// } /// ``` /// /// Too many bounds supplied across multiple attributes: /// ```compile_fail /// #[derive(::arbitrary::Arbitrary)] /// #[arbitrary(bound = "T: Default")] /// #[arbitrary(bound = "U: Default")] /// struct Point { /// #[arbitrary(default)] /// x: T, /// } /// ``` #[cfg(all(doctest, feature = "derive"))] pub struct CompileFailTests;