diff options
Diffstat (limited to 'third_party/rust/arbitrary/src')
-rw-r--r-- | third_party/rust/arbitrary/src/error.rs | 53 | ||||
-rw-r--r-- | third_party/rust/arbitrary/src/lib.rs | 1393 | ||||
-rw-r--r-- | third_party/rust/arbitrary/src/size_hint.rs | 124 | ||||
-rw-r--r-- | third_party/rust/arbitrary/src/unstructured.rs | 1031 |
4 files changed, 2601 insertions, 0 deletions
diff --git a/third_party/rust/arbitrary/src/error.rs b/third_party/rust/arbitrary/src/error.rs new file mode 100644 index 0000000000..1d3df2a22e --- /dev/null +++ b/third_party/rust/arbitrary/src/error.rs @@ -0,0 +1,53 @@ +use std::{error, fmt}; + +/// An enumeration of buffer creation errors +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum Error { + /// No choices were provided to the Unstructured::choose call + EmptyChoose, + /// There was not enough underlying data to fulfill some request for raw + /// bytes. + NotEnoughData, + /// The input bytes were not of the right format + IncorrectFormat, +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Error::EmptyChoose => write!( + f, + "`arbitrary::Unstructured::choose` must be given a non-empty set of choices" + ), + Error::NotEnoughData => write!( + f, + "There is not enough underlying raw data to construct an `Arbitrary` instance" + ), + Error::IncorrectFormat => write!( + f, + "The raw data is not of the correct format to construct this type" + ), + } + } +} + +impl error::Error for Error {} + +/// A `Result` with the error type fixed as `arbitrary::Error`. +/// +/// Either an `Ok(T)` or `Err(arbitrary::Error)`. +pub type Result<T, E = Error> = std::result::Result<T, E>; + +#[cfg(test)] +mod tests { + // Often people will import our custom `Result` type because 99.9% of + // results in a file will be `arbitrary::Result` but then have that one last + // 0.1% that want to have a custom error type. Don't make them prefix that + // 0.1% as `std::result::Result`; instead, let `arbitrary::Result` have an + // overridable error type. + #[test] + fn can_use_custom_error_types_with_result() -> super::Result<(), String> { + Ok(()) + } +} diff --git a/third_party/rust/arbitrary/src/lib.rs b/third_party/rust/arbitrary/src/lib.rs new file mode 100644 index 0000000000..dfaebd0775 --- /dev/null +++ b/third_party/rust/arbitrary/src/lib.rs @@ -0,0 +1,1393 @@ +// Copyright © 2019 The Rust Fuzz Project Developers. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<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) +/// } +/// } +/// # } +/// ``` +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 `<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 () { + fn arbitrary(_: &mut Unstructured<'a>) -> Result<Self> { + Ok(()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, Some(0)) + } +} + +impl<'a> Arbitrary<'a> for bool { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Ok(<u8 as Arbitrary<'a>>::arbitrary(u)? & 1 == 1) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <u8 as Arbitrary<'a>>::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<Self> { + 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<usize>) { + 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<Self> { + Ok(Self::from_bits(<$unsigned as Arbitrary<'a>>::arbitrary(u)?)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <$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<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; + let mut c = <u32 as Arbitrary<'a>>::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<usize>) { + <u32 as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for AtomicBool { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <bool as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for AtomicIsize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <isize as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for AtomicUsize { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <usize as Arbitrary<'a>>::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<Self> { + let value: $value_ty = Arbitrary::arbitrary(u)?; + Ok($fun(value, $fun_closure)) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + $size_hint_closure(depth) + } + } + }; +} + +impl_range!( + Range<A>, + |r: &Range<A>| (r.start.clone(), r.end.clone()), + (A, A), + bounded_range(|(a, b)| a..b), + |depth| crate::size_hint::and( + <A as Arbitrary>::size_hint(depth), + <A as Arbitrary>::size_hint(depth) + ) +); +impl_range!( + RangeFrom<A>, + |r: &RangeFrom<A>| r.start.clone(), + A, + unbounded_range(|a| a..), + |depth| <A as Arbitrary>::size_hint(depth) +); +impl_range!( + RangeInclusive<A>, + |r: &RangeInclusive<A>| (r.start().clone(), r.end().clone()), + (A, A), + bounded_range(|(a, b)| a..=b), + |depth| crate::size_hint::and( + <A as Arbitrary>::size_hint(depth), + <A as Arbitrary>::size_hint(depth) + ) +); +impl_range!( + RangeTo<A>, + |r: &RangeTo<A>| r.end.clone(), + A, + unbounded_range(|b| ..b), + |depth| <A as Arbitrary>::size_hint(depth) +); +impl_range!( + RangeToInclusive<A>, + |r: &RangeToInclusive<A>| r.end.clone(), + A, + unbounded_range(|b| ..=b), + |depth| <A as Arbitrary>::size_hint(depth) +); + +pub(crate) fn bounded_range<CB, I, R>(bounds: (I, I), cb: CB) -> R +where + CB: Fn((I, I)) -> R, + I: PartialOrd, + R: RangeBounds<I>, +{ + let (mut start, mut end) = bounds; + if start > end { + mem::swap(&mut start, &mut end); + } + cb((start, end)) +} + +pub(crate) fn unbounded_range<CB, I, R>(bound: I, cb: CB) -> R +where + CB: Fn(I) -> R, + R: RangeBounds<I>, +{ + cb(bound) +} + +impl<'a> Arbitrary<'a> for Duration { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Ok(Self::new( + <u64 as Arbitrary>::arbitrary(u)?, + u.int_in_range(0..=999_999_999)?, + )) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::and( + <u64 as Arbitrary>::size_hint(depth), + <u32 as Arbitrary>::size_hint(depth), + ) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Option<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Ok(if <bool as Arbitrary<'a>>::arbitrary(u)? { + Some(Arbitrary::arbitrary(u)?) + } else { + None + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::and( + <bool as Arbitrary>::size_hint(depth), + crate::size_hint::or((0, Some(0)), <A as Arbitrary>::size_hint(depth)), + ) + } +} + +impl<'a, A: Arbitrary<'a>, B: Arbitrary<'a>> Arbitrary<'a> for std::result::Result<A, B> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Ok(if <bool as Arbitrary<'a>>::arbitrary(u)? { + Ok(<A as Arbitrary>::arbitrary(u)?) + } else { + Err(<B as Arbitrary>::arbitrary(u)?) + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::and( + <bool as Arbitrary>::size_hint(depth), + crate::size_hint::or( + <A as Arbitrary>::size_hint(depth), + <B as Arbitrary>::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<Self> { + Ok(($($xs::arbitrary(u)?,)* Arbitrary::arbitrary(u)?,)) + } + + #[allow(unused_mut, non_snake_case)] + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<Self> { + $(let $xs = $xs::arbitrary(&mut u)?;)* + let $last = $last::arbitrary_take_rest(u)?; + Ok(($($xs,)* $last,)) + } + + #[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(&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<F, T, const N: usize>(mut cb: F) -> Result<[T; N]> +where + F: FnMut(usize) -> Result<T>, +{ + 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<T, N> = 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<Self> { + try_create_array(|_| <T as Arbitrary<'a>>::arbitrary(u)) + } + + #[inline] + fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<Self> { + 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<usize>) { + crate::size_hint::and_all(&array::from_fn::<_, N, _>(|_| { + <T as Arbitrary>::size_hint(d) + })) + } +} + +impl<'a> Arbitrary<'a> for &'a [u8] { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + let len = u.arbitrary_len::<u8>()?; + u.bytes(len) + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + Ok(u.take_rest()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Vec<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, K: Arbitrary<'a> + Ord, V: Arbitrary<'a>> Arbitrary<'a> for BTreeMap<K, V> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a> + Ord> Arbitrary<'a> for BTreeSet<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Bound<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + match u.int_in_range::<u8>(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<usize>) { + 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<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, K: Arbitrary<'a> + Eq + ::std::hash::Hash, V: Arbitrary<'a>, S: BuildHasher + Default> + Arbitrary<'a> for HashMap<K, V, S> +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a> + Eq + ::std::hash::Hash, S: BuildHasher + Default> Arbitrary<'a> + for HashSet<A, S> +{ + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for LinkedList<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for VecDeque<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + u.arbitrary_iter()?.collect() + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + u.arbitrary_take_rest_iter()?.collect() + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +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) + }) + } +} + +impl<'a> Arbitrary<'a> for &'a str { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + let size = u.arbitrary_len::<u8>()?; + 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<Self> { + let bytes = u.take_rest(); + str::from_utf8(bytes).map_err(|_| Error::IncorrectFormat) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, None) + } +} + +impl<'a> Arbitrary<'a> for String { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> { + <&str as Arbitrary>::arbitrary_take_rest(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <&str as Arbitrary>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for CString { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <Vec<u8> as Arbitrary>::arbitrary(u).map(|mut x| { + x.retain(|&c| c != 0); + Self::new(x).unwrap() + }) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <Vec<u8> as Arbitrary>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for OsString { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <String as Arbitrary>::arbitrary(u).map(From::from) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <String as Arbitrary>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for PathBuf { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <OsString as Arbitrary>::arbitrary(u).map(From::from) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <OsString as Arbitrary>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<[A]> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <Vec<A> as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_slice()) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <Vec<A> as Arbitrary>::size_hint(depth) + } +} + +impl<'a> Arbitrary<'a> for Box<str> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <String as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_str()) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <String as Arbitrary>::size_hint(depth) + } +} + +// impl Arbitrary for Box<CStr> { +// fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { +// <CString as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_c_str()) +// } +// } + +// impl Arbitrary for Box<OsStr> { +// fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> { +// <OsString as Arbitrary>::arbitrary(u).map(|x| x.into_boxed_osstr()) +// +// } +// } + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Arc<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) + } +} + +impl<'a> Arbitrary<'a> for Arc<str> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <&str as Arbitrary>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Rc<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) + } +} + +impl<'a> Arbitrary<'a> for Rc<str> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + <&str as Arbitrary>::arbitrary(u).map(Into::into) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <&str as Arbitrary>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Cell<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <A as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for RefCell<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <A as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for UnsafeCell<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <A as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Mutex<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(Self::new) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <A as Arbitrary<'a>>::size_hint(depth) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for iter::Empty<A> { + fn arbitrary(_: &mut Unstructured<'a>) -> Result<Self> { + Ok(iter::empty()) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, Some(0)) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::marker::PhantomData<A> { + fn arbitrary(_: &mut Unstructured<'a>) -> Result<Self> { + Ok(::std::marker::PhantomData) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (0, Some(0)) + } +} + +impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::num::Wrapping<A> { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Arbitrary::arbitrary(u).map(::std::num::Wrapping) + } + + #[inline] + fn size_hint(depth: usize) -> (usize, Option<usize>) { + <A as Arbitrary<'a>>::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<Self> { + 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<usize>) { + <$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<Self> { + Ok(Ipv4Addr::from(u32::arbitrary(u)?)) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (4, Some(4)) + } +} + +impl<'a> Arbitrary<'a> for Ipv6Addr { + fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + Ok(Ipv6Addr::from(u128::arbitrary(u)?)) + } + + #[inline] + fn size_hint(_depth: usize) -> (usize, Option<usize>) { + (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<T> { + 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<T> { + 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::<i32>(&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::<Vec<u8>>(&mut Unstructured::new(&x)).unwrap(), + &[2, 4, 6, 8, 1] + ); + assert_eq!( + checked_arbitrary::<Vec<u32>>(&mut Unstructured::new(&x)).unwrap(), + &[84148994] + ); + assert_eq!( + checked_arbitrary::<String>(&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::<Vec<u8>>(Unstructured::new(&x)).unwrap(), + &[1, 2, 3, 4] + ); + assert_eq!( + checked_arbitrary_take_rest::<Vec<u32>>(Unstructured::new(&x)).unwrap(), + &[0x4030201] + ); + assert_eq!( + checked_arbitrary_take_rest::<String>(Unstructured::new(&x)).unwrap(), + "\x01\x02\x03\x04" + ); + + assert_eq!( + checked_arbitrary_take_rest::<&[u8]>(Unstructured::new(&[])).unwrap(), + &[] + ); + assert_eq!( + checked_arbitrary_take_rest::<Vec<u8>>(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<u8>) 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<T: Default> { +/// #[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<T: Default> { +/// #[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<T: Default> { +/// #[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<T: Default> { +/// #[arbitrary(default)] +/// x: T, +/// } +/// ``` +#[cfg(all(doctest, feature = "derive"))] +pub struct CompileFailTests; diff --git a/third_party/rust/arbitrary/src/size_hint.rs b/third_party/rust/arbitrary/src/size_hint.rs new file mode 100644 index 0000000000..045c148a29 --- /dev/null +++ b/third_party/rust/arbitrary/src/size_hint.rs @@ -0,0 +1,124 @@ +//! Utilities for working with and combining the results of +//! [`Arbitrary::size_hint`][crate::Arbitrary::size_hint]. + +/// Protects against potential infinite recursion when calculating size hints +/// due to indirect type recursion. +/// +/// When the depth is not too deep, calls `f` with `depth + 1` to calculate the +/// size hint. +/// +/// Otherwise, returns the default size hint: `(0, None)`. +#[inline] +pub fn recursion_guard( + depth: usize, + f: impl FnOnce(usize) -> (usize, Option<usize>), +) -> (usize, Option<usize>) { + const MAX_DEPTH: usize = 20; + if depth > MAX_DEPTH { + (0, None) + } else { + f(depth + 1) + } +} + +/// Take the sum of the `lhs` and `rhs` size hints. +#[inline] +pub fn and(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) { + let lower = lhs.0 + rhs.0; + let upper = lhs.1.and_then(|lhs| rhs.1.map(|rhs| lhs + rhs)); + (lower, upper) +} + +/// Take the sum of all of the given size hints. +/// +/// If `hints` is empty, returns `(0, Some(0))`, aka the size of consuming +/// nothing. +#[inline] +pub fn and_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) { + hints.iter().copied().fold((0, Some(0)), and) +} + +/// Take the minimum of the lower bounds and maximum of the upper bounds in the +/// `lhs` and `rhs` size hints. +#[inline] +pub fn or(lhs: (usize, Option<usize>), rhs: (usize, Option<usize>)) -> (usize, Option<usize>) { + let lower = std::cmp::min(lhs.0, rhs.0); + let upper = lhs + .1 + .and_then(|lhs| rhs.1.map(|rhs| std::cmp::max(lhs, rhs))); + (lower, upper) +} + +/// Take the maximum of the `lhs` and `rhs` size hints. +/// +/// If `hints` is empty, returns `(0, Some(0))`, aka the size of consuming +/// nothing. +#[inline] +pub fn or_all(hints: &[(usize, Option<usize>)]) -> (usize, Option<usize>) { + if let Some(head) = hints.first().copied() { + hints[1..].iter().copied().fold(head, or) + } else { + (0, Some(0)) + } +} + +#[cfg(test)] +mod tests { + #[test] + fn and() { + assert_eq!((5, Some(5)), super::and((2, Some(2)), (3, Some(3)))); + assert_eq!((5, None), super::and((2, Some(2)), (3, None))); + assert_eq!((5, None), super::and((2, None), (3, Some(3)))); + assert_eq!((5, None), super::and((2, None), (3, None))); + } + + #[test] + fn or() { + assert_eq!((2, Some(3)), super::or((2, Some(2)), (3, Some(3)))); + assert_eq!((2, None), super::or((2, Some(2)), (3, None))); + assert_eq!((2, None), super::or((2, None), (3, Some(3)))); + assert_eq!((2, None), super::or((2, None), (3, None))); + } + + #[test] + fn and_all() { + assert_eq!((0, Some(0)), super::and_all(&[])); + assert_eq!( + (7, Some(7)), + super::and_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, Some(1)), (2, Some(2)), (4, None)]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, Some(1)), (2, None), (4, Some(4))]) + ); + assert_eq!( + (7, None), + super::and_all(&[(1, None), (2, Some(2)), (4, Some(4))]) + ); + } + + #[test] + fn or_all() { + assert_eq!((0, Some(0)), super::or_all(&[])); + assert_eq!( + (1, Some(4)), + super::or_all(&[(1, Some(1)), (2, Some(2)), (4, Some(4))]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, Some(1)), (2, Some(2)), (4, None)]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, Some(1)), (2, None), (4, Some(4))]) + ); + assert_eq!( + (1, None), + super::or_all(&[(1, None), (2, Some(2)), (4, Some(4))]) + ); + } +} diff --git a/third_party/rust/arbitrary/src/unstructured.rs b/third_party/rust/arbitrary/src/unstructured.rs new file mode 100644 index 0000000000..0bfdff2881 --- /dev/null +++ b/third_party/rust/arbitrary/src/unstructured.rs @@ -0,0 +1,1031 @@ +// Copyright © 2019 The Rust Fuzz Project Developers. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Wrappers around raw, unstructured bytes. + +use crate::{Arbitrary, Error, Result}; +use std::marker::PhantomData; +use std::ops::ControlFlow; +use std::{mem, ops}; + +/// A source of unstructured data. +/// +/// An `Unstructured` helps `Arbitrary` implementations interpret raw data +/// (typically provided by a fuzzer) as a "DNA string" that describes how to +/// construct the `Arbitrary` type. The goal is that a small change to the "DNA +/// string" (the raw data wrapped by an `Unstructured`) results in a small +/// change to the generated `Arbitrary` instance. This helps a fuzzer +/// efficiently explore the `Arbitrary`'s input space. +/// +/// `Unstructured` is deterministic: given the same raw data, the same series of +/// API calls will return the same results (modulo system resource constraints, +/// like running out of memory). However, `Unstructured` does not guarantee +/// anything beyond that: it makes not guarantee that it will yield bytes from +/// the underlying data in any particular order. +/// +/// You shouldn't generally need to use an `Unstructured` unless you are writing +/// a custom `Arbitrary` implementation by hand, instead of deriving it. Mostly, +/// you should just be passing it through to nested `Arbitrary::arbitrary` +/// calls. +/// +/// # Example +/// +/// Imagine you were writing a color conversion crate. You might want to write +/// fuzz tests that take a random RGB color and assert various properties, run +/// functions and make sure nothing panics, etc. +/// +/// Below is what translating the fuzzer's raw input into an `Unstructured` and +/// using that to generate an arbitrary RGB color might look like: +/// +/// ``` +/// # #[cfg(feature = "derive")] fn foo() { +/// use arbitrary::{Arbitrary, Unstructured}; +/// +/// /// An RGB color. +/// #[derive(Arbitrary)] +/// pub struct Rgb { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// +/// // Get the raw bytes from the fuzzer. +/// # let get_input_from_fuzzer = || &[]; +/// let raw_data: &[u8] = get_input_from_fuzzer(); +/// +/// // Wrap it in an `Unstructured`. +/// let mut unstructured = Unstructured::new(raw_data); +/// +/// // Generate an `Rgb` color and run our checks. +/// if let Ok(rgb) = Rgb::arbitrary(&mut unstructured) { +/// # let run_my_color_conversion_checks = |_| {}; +/// run_my_color_conversion_checks(rgb); +/// } +/// # } +/// ``` +pub struct Unstructured<'a> { + data: &'a [u8], +} + +impl<'a> Unstructured<'a> { + /// Create a new `Unstructured` from the given raw data. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let u = Unstructured::new(&[1, 2, 3, 4]); + /// ``` + pub fn new(data: &'a [u8]) -> Self { + Unstructured { data } + } + + /// Get the number of remaining bytes of underlying data that are still + /// available. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3]); + /// + /// // Initially have three bytes of data. + /// assert_eq!(u.len(), 3); + /// + /// // Generating a `bool` consumes one byte from the underlying data, so + /// // we are left with two bytes afterwards. + /// let _ = bool::arbitrary(&mut u); + /// assert_eq!(u.len(), 2); + /// ``` + #[inline] + pub fn len(&self) -> usize { + self.data.len() + } + + /// Is the underlying unstructured data exhausted? + /// + /// `unstructured.is_empty()` is the same as `unstructured.len() == 0`. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// // Initially, we are not empty. + /// assert!(!u.is_empty()); + /// + /// // Generating a `u32` consumes all four bytes of the underlying data, so + /// // we become empty afterwards. + /// let _ = u32::arbitrary(&mut u); + /// assert!(u.is_empty()); + /// ``` + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Generate an arbitrary instance of `A`. + /// + /// This is simply a helper method that is equivalent to `<A as + /// Arbitrary>::arbitrary(self)`. This helper is a little bit more concise, + /// and can be used in situations where Rust's type inference will figure + /// out what `A` should be. + /// + /// # Example + /// + /// ``` + /// # #[cfg(feature="derive")] fn foo() -> arbitrary::Result<()> { + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// #[derive(Arbitrary)] + /// struct MyType { + /// // ... + /// } + /// + /// fn do_stuff(value: MyType) { + /// # let _ = value; + /// // ... + /// } + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// // Rust's type inference can figure out that `value` should be of type + /// // `MyType` here: + /// let value = u.arbitrary()?; + /// do_stuff(value); + /// # Ok(()) } + /// ``` + pub fn arbitrary<A>(&mut self) -> Result<A> + where + A: Arbitrary<'a>, + { + <A as Arbitrary<'a>>::arbitrary(self) + } + + /// Get the number of elements to insert when building up a collection of + /// arbitrary `ElementType`s. + /// + /// This uses the [`<ElementType as + /// Arbitrary>::size_hint`][crate::Arbitrary::size_hint] method to smartly + /// choose a length such that we most likely have enough underlying bytes to + /// construct that many arbitrary `ElementType`s. + /// + /// This should only be called within an `Arbitrary` implementation. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Result, Unstructured}; + /// # pub struct MyCollection<T> { _t: std::marker::PhantomData<T> } + /// # impl<T> MyCollection<T> { + /// # pub fn with_capacity(capacity: usize) -> Self { MyCollection { _t: std::marker::PhantomData } } + /// # pub fn insert(&mut self, element: T) {} + /// # } + /// + /// impl<'a, T> Arbitrary<'a> for MyCollection<T> + /// where + /// T: Arbitrary<'a>, + /// { + /// fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { + /// // Get the number of `T`s we should insert into our collection. + /// let len = u.arbitrary_len::<T>()?; + /// + /// // And then create a collection of that length! + /// let mut my_collection = MyCollection::with_capacity(len); + /// for _ in 0..len { + /// let element = T::arbitrary(u)?; + /// my_collection.insert(element); + /// } + /// + /// Ok(my_collection) + /// } + /// } + /// ``` + pub fn arbitrary_len<ElementType>(&mut self) -> Result<usize> + where + ElementType: Arbitrary<'a>, + { + let byte_size = self.arbitrary_byte_size()?; + let (lower, upper) = <ElementType as Arbitrary>::size_hint(0); + let elem_size = upper.unwrap_or(lower * 2); + let elem_size = std::cmp::max(1, elem_size); + Ok(byte_size / elem_size) + } + + fn arbitrary_byte_size(&mut self) -> Result<usize> { + if self.data.is_empty() { + Ok(0) + } else if self.data.len() == 1 { + self.data = &[]; + Ok(0) + } else { + // Take lengths from the end of the data, since the `libFuzzer` folks + // found that this lets fuzzers more efficiently explore the input + // space. + // + // https://github.com/rust-fuzz/libfuzzer-sys/blob/0c450753/libfuzzer/utils/FuzzedDataProvider.h#L92-L97 + + // We only consume as many bytes as necessary to cover the entire + // range of the byte string. + // Note: We cast to u64 so we don't overflow when checking std::u32::MAX + 4 on 32-bit archs + let len = if self.data.len() as u64 <= std::u8::MAX as u64 + 1 { + let bytes = 1; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u8, for_size.iter().copied())?.0 as usize + } else if self.data.len() as u64 <= std::u16::MAX as u64 + 2 { + let bytes = 2; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u16, for_size.iter().copied())?.0 as usize + } else if self.data.len() as u64 <= std::u32::MAX as u64 + 4 { + let bytes = 4; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u32, for_size.iter().copied())?.0 as usize + } else { + let bytes = 8; + let max_size = self.data.len() - bytes; + let (rest, for_size) = self.data.split_at(max_size); + self.data = rest; + Self::int_in_range_impl(0..=max_size as u64, for_size.iter().copied())?.0 as usize + }; + + Ok(len) + } + } + + /// Generate an integer within the given range. + /// + /// Do not use this to generate the size of a collection. Use + /// `arbitrary_len` instead. + /// + /// # Panics + /// + /// Panics if `range.start > range.end`. That is, the given range must be + /// non-empty. + /// + /// # Example + /// + /// ``` + /// use arbitrary::{Arbitrary, Unstructured}; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// let x: i32 = u.int_in_range(-5_000..=-1_000) + /// .expect("constructed `u` with enough bytes to generate an `i32`"); + /// + /// assert!(-5_000 <= x); + /// assert!(x <= -1_000); + /// ``` + pub fn int_in_range<T>(&mut self, range: ops::RangeInclusive<T>) -> Result<T> + where + T: Int, + { + let (result, bytes_consumed) = Self::int_in_range_impl(range, self.data.iter().cloned())?; + self.data = &self.data[bytes_consumed..]; + Ok(result) + } + + fn int_in_range_impl<T>( + range: ops::RangeInclusive<T>, + mut bytes: impl Iterator<Item = u8>, + ) -> Result<(T, usize)> + where + T: Int, + { + let start = *range.start(); + let end = *range.end(); + assert!( + start <= end, + "`arbitrary::Unstructured::int_in_range` requires a non-empty range" + ); + + // When there is only one possible choice, don't waste any entropy from + // the underlying data. + if start == end { + return Ok((start, 0)); + } + + // From here on out we work with the unsigned representation. All of the + // operations performed below work out just as well whether or not `T` + // is a signed or unsigned integer. + let start = start.to_unsigned(); + let end = end.to_unsigned(); + + let delta = end.wrapping_sub(start); + debug_assert_ne!(delta, T::Unsigned::ZERO); + + // Compute an arbitrary integer offset from the start of the range. We + // do this by consuming `size_of(T)` bytes from the input to create an + // arbitrary integer and then clamping that int into our range bounds + // with a modulo operation. + let mut arbitrary_int = T::Unsigned::ZERO; + let mut bytes_consumed: usize = 0; + + while (bytes_consumed < mem::size_of::<T>()) + && (delta >> T::Unsigned::from_usize(bytes_consumed * 8)) > T::Unsigned::ZERO + { + let byte = match bytes.next() { + None => break, + Some(b) => b, + }; + bytes_consumed += 1; + + // Combine this byte into our arbitrary integer, but avoid + // overflowing the shift for `u8` and `i8`. + arbitrary_int = if mem::size_of::<T>() == 1 { + T::Unsigned::from_u8(byte) + } else { + (arbitrary_int << 8) | T::Unsigned::from_u8(byte) + }; + } + + let offset = if delta == T::Unsigned::MAX { + arbitrary_int + } else { + arbitrary_int % (delta.checked_add(T::Unsigned::ONE).unwrap()) + }; + + // Finally, we add `start` to our offset from `start` to get the result + // actual value within the range. + let result = start.wrapping_add(offset); + + // And convert back to our maybe-signed representation. + let result = T::from_unsigned(result); + debug_assert!(*range.start() <= result); + debug_assert!(result <= *range.end()); + + Ok((result, bytes_consumed)) + } + + /// Choose one of the given choices. + /// + /// This should only be used inside of `Arbitrary` implementations. + /// + /// Returns an error if there is not enough underlying data to make a + /// choice or if no choices are provided. + /// + /// # Examples + /// + /// Selecting from an array of choices: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let choices = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + /// + /// let choice = u.choose(&choices).unwrap(); + /// + /// println!("chose {}", choice); + /// ``` + /// + /// An error is returned if no choices are provided: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let choices: [char; 0] = []; + /// + /// let result = u.choose(&choices); + /// + /// assert!(result.is_err()); + /// ``` + pub fn choose<'b, T>(&mut self, choices: &'b [T]) -> Result<&'b T> { + let idx = self.choose_index(choices.len())?; + Ok(&choices[idx]) + } + + /// Choose a value in `0..len`. + /// + /// Returns an error if the `len` is zero. + /// + /// # Examples + /// + /// Using Fisher–Yates shuffle shuffle to gerate an arbitrary permutation. + /// + /// [Fisher–Yates shuffle]: https://en.wikipedia.org/wiki/Fisher–Yates_shuffle + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let mut permutation = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; + /// let mut to_permute = &mut permutation[..]; + /// while to_permute.len() > 1 { + /// let idx = u.choose_index(to_permute.len()).unwrap(); + /// to_permute.swap(0, idx); + /// to_permute = &mut to_permute[1..]; + /// } + /// + /// println!("permutation: {:?}", permutation); + /// ``` + /// + /// An error is returned if the length is zero: + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + /// let array: [i32; 0] = []; + /// + /// let result = u.choose_index(array.len()); + /// + /// assert!(result.is_err()); + /// ``` + pub fn choose_index(&mut self, len: usize) -> Result<usize> { + if len == 0 { + return Err(Error::EmptyChoose); + } + let idx = self.int_in_range(0..=len - 1)?; + Ok(idx) + } + + /// Generate a boolean according to the given ratio. + /// + /// # Panics + /// + /// Panics when the numerator and denominator do not meet these constraints: + /// + /// * `0 < numerator <= denominator` + /// + /// # Example + /// + /// Generate a boolean that is `true` five sevenths of the time: + /// + /// ``` + /// # fn foo() -> arbitrary::Result<()> { + /// use arbitrary::Unstructured; + /// + /// # let my_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; + /// let mut u = Unstructured::new(&my_data); + /// + /// if u.ratio(5, 7)? { + /// // Take this branch 5/7 of the time. + /// } + /// # Ok(()) + /// # } + /// ``` + pub fn ratio<T>(&mut self, numerator: T, denominator: T) -> Result<bool> + where + T: Int, + { + assert!(T::ZERO < numerator); + assert!(numerator <= denominator); + let x = self.int_in_range(T::ONE..=denominator)?; + Ok(x <= numerator) + } + + /// Fill a `buffer` with bytes from the underlying raw data. + /// + /// This should only be called within an `Arbitrary` implementation. This is + /// a very low-level operation. You should generally prefer calling nested + /// `Arbitrary` implementations like `<Vec<u8>>::arbitrary` and + /// `String::arbitrary` over using this method directly. + /// + /// If this `Unstructured` does not have enough underlying data to fill the + /// whole `buffer`, it pads the buffer out with zeros. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// let mut buf = [0; 2]; + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [1, 2]); + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [3, 4]); + /// + /// assert!(u.fill_buffer(&mut buf).is_ok()); + /// assert_eq!(buf, [0, 0]); + /// ``` + pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> { + let n = std::cmp::min(buffer.len(), self.data.len()); + buffer[..n].copy_from_slice(&self.data[..n]); + for byte in buffer[n..].iter_mut() { + *byte = 0; + } + self.data = &self.data[n..]; + Ok(()) + } + + /// Provide `size` bytes from the underlying raw data. + /// + /// This should only be called within an `Arbitrary` implementation. This is + /// a very low-level operation. You should generally prefer calling nested + /// `Arbitrary` implementations like `<Vec<u8>>::arbitrary` and + /// `String::arbitrary` over using this method directly. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3, 4]); + /// + /// assert!(u.bytes(2).unwrap() == &[1, 2]); + /// assert!(u.bytes(2).unwrap() == &[3, 4]); + /// ``` + pub fn bytes(&mut self, size: usize) -> Result<&'a [u8]> { + if self.data.len() < size { + return Err(Error::NotEnoughData); + } + + let (for_buf, rest) = self.data.split_at(size); + self.data = rest; + Ok(for_buf) + } + + /// Peek at `size` number of bytes of the underlying raw input. + /// + /// Does not consume the bytes, only peeks at them. + /// + /// Returns `None` if there are not `size` bytes left in the underlying raw + /// input. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let u = Unstructured::new(&[1, 2, 3]); + /// + /// assert_eq!(u.peek_bytes(0).unwrap(), []); + /// assert_eq!(u.peek_bytes(1).unwrap(), [1]); + /// assert_eq!(u.peek_bytes(2).unwrap(), [1, 2]); + /// assert_eq!(u.peek_bytes(3).unwrap(), [1, 2, 3]); + /// + /// assert!(u.peek_bytes(4).is_none()); + /// ``` + pub fn peek_bytes(&self, size: usize) -> Option<&'a [u8]> { + self.data.get(..size) + } + + /// Consume all of the rest of the remaining underlying bytes. + /// + /// Returns a slice of all the remaining, unconsumed bytes. + /// + /// # Example + /// + /// ``` + /// use arbitrary::Unstructured; + /// + /// let mut u = Unstructured::new(&[1, 2, 3]); + /// + /// let mut remaining = u.take_rest(); + /// + /// assert_eq!(remaining, [1, 2, 3]); + /// ``` + pub fn take_rest(mut self) -> &'a [u8] { + mem::take(&mut self.data) + } + + /// Provide an iterator over elements for constructing a collection + /// + /// This is useful for implementing [`Arbitrary::arbitrary`] on collections + /// since the implementation is simply `u.arbitrary_iter()?.collect()` + pub fn arbitrary_iter<'b, ElementType: Arbitrary<'a>>( + &'b mut self, + ) -> Result<ArbitraryIter<'a, 'b, ElementType>> { + Ok(ArbitraryIter { + u: &mut *self, + _marker: PhantomData, + }) + } + + /// Provide an iterator over elements for constructing a collection from + /// all the remaining bytes. + /// + /// This is useful for implementing [`Arbitrary::arbitrary_take_rest`] on collections + /// since the implementation is simply `u.arbitrary_take_rest_iter()?.collect()` + pub fn arbitrary_take_rest_iter<ElementType: Arbitrary<'a>>( + self, + ) -> Result<ArbitraryTakeRestIter<'a, ElementType>> { + let (lower, upper) = ElementType::size_hint(0); + + let elem_size = upper.unwrap_or(lower * 2); + let elem_size = std::cmp::max(1, elem_size); + let size = self.len() / elem_size; + Ok(ArbitraryTakeRestIter { + size, + u: Some(self), + _marker: PhantomData, + }) + } + + /// Call the given function an arbitrary number of times. + /// + /// The function is given this `Unstructured` so that it can continue to + /// generate arbitrary data and structures. + /// + /// You may optionaly specify minimum and maximum bounds on the number of + /// times the function is called. + /// + /// You may break out of the loop early by returning + /// `Ok(std::ops::ControlFlow::Break)`. To continue the loop, return + /// `Ok(std::ops::ControlFlow::Continue)`. + /// + /// # Panics + /// + /// Panics if `min > max`. + /// + /// # Example + /// + /// Call a closure that generates an arbitrary type inside a context an + /// arbitrary number of times: + /// + /// ``` + /// use arbitrary::{Result, Unstructured}; + /// use std::ops::ControlFlow; + /// + /// enum Type { + /// /// A boolean type. + /// Bool, + /// + /// /// An integer type. + /// Int, + /// + /// /// A list of the `i`th type in this type's context. + /// List(usize), + /// } + /// + /// fn arbitrary_types_context(u: &mut Unstructured) -> Result<Vec<Type>> { + /// let mut context = vec![]; + /// + /// u.arbitrary_loop(Some(10), Some(20), |u| { + /// let num_choices = if context.is_empty() { + /// 2 + /// } else { + /// 3 + /// }; + /// let ty = match u.int_in_range::<u8>(1..=num_choices)? { + /// 1 => Type::Bool, + /// 2 => Type::Int, + /// 3 => Type::List(u.int_in_range(0..=context.len() - 1)?), + /// _ => unreachable!(), + /// }; + /// context.push(ty); + /// Ok(ControlFlow::Continue(())) + /// })?; + /// + /// // The number of loop iterations are constrained by the min/max + /// // bounds that we provided. + /// assert!(context.len() >= 10); + /// assert!(context.len() <= 20); + /// + /// Ok(context) + /// } + /// ``` + pub fn arbitrary_loop( + &mut self, + min: Option<u32>, + max: Option<u32>, + mut f: impl FnMut(&mut Self) -> Result<ControlFlow<(), ()>>, + ) -> Result<()> { + let min = min.unwrap_or(0); + let max = max.unwrap_or(u32::MAX); + + for _ in 0..self.int_in_range(min..=max)? { + match f(self)? { + ControlFlow::Continue(_) => continue, + ControlFlow::Break(_) => break, + } + } + + Ok(()) + } +} + +/// Utility iterator produced by [`Unstructured::arbitrary_iter`] +pub struct ArbitraryIter<'a, 'b, ElementType> { + u: &'b mut Unstructured<'a>, + _marker: PhantomData<ElementType>, +} + +impl<'a, 'b, ElementType: Arbitrary<'a>> Iterator for ArbitraryIter<'a, 'b, ElementType> { + type Item = Result<ElementType>; + fn next(&mut self) -> Option<Result<ElementType>> { + let keep_going = self.u.arbitrary().unwrap_or(false); + if keep_going { + Some(Arbitrary::arbitrary(self.u)) + } else { + None + } + } +} + +/// Utility iterator produced by [`Unstructured::arbitrary_take_rest_iter`] +pub struct ArbitraryTakeRestIter<'a, ElementType> { + u: Option<Unstructured<'a>>, + size: usize, + _marker: PhantomData<ElementType>, +} + +impl<'a, ElementType: Arbitrary<'a>> Iterator for ArbitraryTakeRestIter<'a, ElementType> { + type Item = Result<ElementType>; + fn next(&mut self) -> Option<Result<ElementType>> { + if let Some(mut u) = self.u.take() { + if self.size == 1 { + Some(Arbitrary::arbitrary_take_rest(u)) + } else if self.size == 0 { + None + } else { + self.size -= 1; + let ret = Arbitrary::arbitrary(&mut u); + self.u = Some(u); + Some(ret) + } + } else { + None + } + } +} + +/// A trait that is implemented for all of the primitive integers: +/// +/// * `u8` +/// * `u16` +/// * `u32` +/// * `u64` +/// * `u128` +/// * `usize` +/// * `i8` +/// * `i16` +/// * `i32` +/// * `i64` +/// * `i128` +/// * `isize` +/// +/// Don't implement this trait yourself. +pub trait Int: + Copy + + std::fmt::Debug + + PartialOrd + + Ord + + ops::Sub<Self, Output = Self> + + ops::Rem<Self, Output = Self> + + ops::Shr<Self, Output = Self> + + ops::Shl<usize, Output = Self> + + ops::BitOr<Self, Output = Self> +{ + #[doc(hidden)] + type Unsigned: Int; + + #[doc(hidden)] + const ZERO: Self; + + #[doc(hidden)] + const ONE: Self; + + #[doc(hidden)] + const MAX: Self; + + #[doc(hidden)] + fn from_u8(b: u8) -> Self; + + #[doc(hidden)] + fn from_usize(u: usize) -> Self; + + #[doc(hidden)] + fn checked_add(self, rhs: Self) -> Option<Self>; + + #[doc(hidden)] + fn wrapping_add(self, rhs: Self) -> Self; + + #[doc(hidden)] + fn wrapping_sub(self, rhs: Self) -> Self; + + #[doc(hidden)] + fn to_unsigned(self) -> Self::Unsigned; + + #[doc(hidden)] + fn from_unsigned(unsigned: Self::Unsigned) -> Self; +} + +macro_rules! impl_int { + ( $( $ty:ty : $unsigned_ty: ty ; )* ) => { + $( + impl Int for $ty { + type Unsigned = $unsigned_ty; + + const ZERO: Self = 0; + + const ONE: Self = 1; + + const MAX: Self = Self::MAX; + + fn from_u8(b: u8) -> Self { + b as Self + } + + fn from_usize(u: usize) -> Self { + u as Self + } + + fn checked_add(self, rhs: Self) -> Option<Self> { + <$ty>::checked_add(self, rhs) + } + + fn wrapping_add(self, rhs: Self) -> Self { + <$ty>::wrapping_add(self, rhs) + } + + fn wrapping_sub(self, rhs: Self) -> Self { + <$ty>::wrapping_sub(self, rhs) + } + + fn to_unsigned(self) -> Self::Unsigned { + self as $unsigned_ty + } + + fn from_unsigned(unsigned: $unsigned_ty) -> Self { + unsigned as Self + } + } + )* + } +} + +impl_int! { + u8: u8; + u16: u16; + u32: u32; + u64: u64; + u128: u128; + usize: usize; + i8: u8; + i16: u16; + i32: u32; + i64: u64; + i128: u128; + isize: usize; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_byte_size() { + let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); + // Should take one byte off the end + assert_eq!(u.arbitrary_byte_size().unwrap(), 6); + assert_eq!(u.len(), 9); + let mut v = vec![]; + v.resize(260, 0); + v.push(1); + v.push(4); + let mut u = Unstructured::new(&v); + // Should read two bytes off the end + assert_eq!(u.arbitrary_byte_size().unwrap(), 0x104); + assert_eq!(u.len(), 260); + } + + #[test] + fn int_in_range_of_one() { + let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 6]); + let x = u.int_in_range(0..=0).unwrap(); + assert_eq!(x, 0); + let choice = *u.choose(&[42]).unwrap(); + assert_eq!(choice, 42) + } + + #[test] + fn int_in_range_uses_minimal_amount_of_bytes() { + let mut u = Unstructured::new(&[1, 2]); + assert_eq!(1, u.int_in_range::<u8>(0..=u8::MAX).unwrap()); + assert_eq!(u.len(), 1); + + let mut u = Unstructured::new(&[1, 2]); + assert_eq!(1, u.int_in_range::<u32>(0..=u8::MAX as u32).unwrap()); + assert_eq!(u.len(), 1); + + let mut u = Unstructured::new(&[1]); + assert_eq!(1, u.int_in_range::<u32>(0..=u8::MAX as u32 + 1).unwrap()); + assert!(u.is_empty()); + } + + #[test] + fn int_in_range_in_bounds() { + for input in u8::MIN..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(1..=u8::MAX).unwrap(); + assert_ne!(x, 0); + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); + assert_ne!(x, u8::MAX); + } + } + + #[test] + fn int_in_range_covers_unsigned_range() { + // Test that we generate all values within the range given to + // `int_in_range`. + + let mut full = [false; u8::MAX as usize + 1]; + let mut no_zero = [false; u8::MAX as usize]; + let mut no_max = [false; u8::MAX as usize]; + let mut narrow = [false; 10]; + + for input in u8::MIN..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX).unwrap(); + full[x as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(1..=u8::MAX).unwrap(); + no_zero[x as usize - 1] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(0..=u8::MAX - 1).unwrap(); + no_max[x as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(100..=109).unwrap(); + narrow[x as usize - 100] = true; + } + + for (i, covered) in full.iter().enumerate() { + assert!(covered, "full[{}] should have been generated", i); + } + for (i, covered) in no_zero.iter().enumerate() { + assert!(covered, "no_zero[{}] should have been generated", i); + } + for (i, covered) in no_max.iter().enumerate() { + assert!(covered, "no_max[{}] should have been generated", i); + } + for (i, covered) in narrow.iter().enumerate() { + assert!(covered, "narrow[{}] should have been generated", i); + } + } + + #[test] + fn int_in_range_covers_signed_range() { + // Test that we generate all values within the range given to + // `int_in_range`. + + let mut full = [false; u8::MAX as usize + 1]; + let mut no_min = [false; u8::MAX as usize]; + let mut no_max = [false; u8::MAX as usize]; + let mut narrow = [false; 21]; + + let abs_i8_min: isize = 128; + + for input in 0..=u8::MAX { + let input = [input]; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN..=i8::MAX).unwrap(); + full[(x as isize + abs_i8_min) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN + 1..=i8::MAX).unwrap(); + no_min[(x as isize + abs_i8_min - 1) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(i8::MIN..=i8::MAX - 1).unwrap(); + no_max[(x as isize + abs_i8_min) as usize] = true; + + let mut u = Unstructured::new(&input); + let x = u.int_in_range(-10..=10).unwrap(); + narrow[(x as isize + 10) as usize] = true; + } + + for (i, covered) in full.iter().enumerate() { + assert!(covered, "full[{}] should have been generated", i); + } + for (i, covered) in no_min.iter().enumerate() { + assert!(covered, "no_min[{}] should have been generated", i); + } + for (i, covered) in no_max.iter().enumerate() { + assert!(covered, "no_max[{}] should have been generated", i); + } + for (i, covered) in narrow.iter().enumerate() { + assert!(covered, "narrow[{}] should have been generated", i); + } + } +} |