diff options
author | Joel Galenson <jgalenson@google.com> | 2021-06-21 12:05:54 -0700 |
---|---|---|
committer | Joel Galenson <jgalenson@google.com> | 2021-06-21 12:05:54 -0700 |
commit | e0b2b28ae4a9ecfd299dd80de58fc7ec17e8f0c5 (patch) | |
tree | f2191863eba0b1e38e27936acf7bd3ff56edac4f | |
parent | e28af0befb7c8de39febbd271d3812bbc51aaf90 (diff) | |
download | arbitrary-e0b2b28ae4a9ecfd299dd80de58fc7ec17e8f0c5.tar.gz |
Upgrade rust/crates/arbitrary to 1.0.1android-s-beta-5android-s-beta-4android-s-beta-3android-s-beta-5android-s-beta-4
Test: make
Change-Id: I4d3c5bf08f887ced41873b35a0aeaee174db5711
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 2 | ||||
-rw-r--r-- | CHANGELOG.md | 15 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | Cargo.toml.orig | 2 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/lib.rs | 181 | ||||
-rw-r--r-- | src/unstructured.rs | 24 |
9 files changed, 175 insertions, 63 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index cfe44cd..262c88c 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "83b852c9bba47359ad33fc5b1f81f29425bc97e8" + "sha1": "5ec3b33f05e8e993688ab872ca5e1a24f4802ebe" } } @@ -54,5 +54,5 @@ rust_library_rlib { // derive_arbitrary-1.0.1 // proc-macro2-1.0.27 "default,proc-macro" // quote-1.0.9 "default,proc-macro" -// syn-1.0.72 "clone-impls,default,derive,parsing,printing,proc-macro,quote" +// syn-1.0.73 "clone-impls,default,derive,parsing,printing,proc-macro,quote" // unicode-xid-0.2.2 "default" diff --git a/CHANGELOG.md b/CHANGELOG.md index 6542d53..54dc917 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,21 @@ Released YYYY-MM-DD. * TODO (or remove section if none) +## 1.0.1 + +Released 2021-05-20. + +### Added + +* `Arbitrary` impls for `NonZeroX` types [#79](https://github.com/rust-fuzz/arbitrary/pull/79) +* `Arbitrary` impls for all arrays using const generics [#55](https://github.com/rust-fuzz/arbitrary/pull/55) +* `Arbitrary` impls for `Ipv4Addr` and `Ipv6Addr` [#84](https://github.com/rust-fuzz/arbitrary/pull/84) + +### Fixed + +* Use fewer bytes for `Unstructured::int_in_range()` [#80](https://github.com/rust-fuzz/arbitrary/pull/80) +* Use correct range for `char` generation [#83](https://github.com/rust-fuzz/arbitrary/pull/83) + -------------------------------------------------------------------------------- ## 1.0.0 @@ -13,7 +13,7 @@ [package] edition = "2018" name = "arbitrary" -version = "1.0.0" +version = "1.0.1" authors = ["The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>", "Simonas Kazlauskas <arbitrary@kazlauskas.me>", "Brian L. Troutwine <brian@troutwine.us>", "Corey Farwell <coreyf@rwell.org>"] description = "The trait for generating structured data from unstructured data" documentation = "https://docs.rs/arbitrary/" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index f177ed4..e7f7951 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "arbitrary" -version = "1.0.0" # Make sure this matches the derive crate version +version = "1.0.1" # Make sure this matches the derive crate version authors = [ "The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/arbitrary/arbitrary-1.0.0.crate" + value: "https://static.crates.io/crates/arbitrary/arbitrary-1.0.1.crate" } - version: "1.0.0" + version: "1.0.1" license_type: NOTICE last_upgrade_date { year: 2021 - month: 4 - day: 1 + month: 6 + day: 21 } } @@ -10,7 +10,7 @@ ## About -The `Arbitrary` crate lets you construct arbitrary instance of a type. +The `Arbitrary` crate lets you construct arbitrary instances of a type. This crate is primarily intended to be combined with a fuzzer like [libFuzzer and `cargo-fuzz`](https://github.com/rust-fuzz/cargo-fuzz) or @@ -37,12 +37,15 @@ pub mod size_hint; 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::net::{Ipv4Addr, Ipv6Addr}; use std::path::PathBuf; use std::rc::Rc; use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize}; @@ -204,7 +207,7 @@ pub trait Arbitrary<'a>: Sized { /// 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 recrusion! + /// cannot guarantee the lack of type recursion! /// /// Otherwise, you need to use /// [`arbitrary::size_hint::recursion_guard(depth)`][crate::size_hint::recursion_guard] @@ -345,12 +348,13 @@ impl_arbitrary_for_floats! { impl<'a> Arbitrary<'a> for char { fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { use std::char; - const CHAR_END: u32 = 0x0011_000; + // 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) { - return Ok(c); + Ok(c) } else { // We found a surrogate, wrap and try again c -= SURROGATES_START; @@ -571,61 +575,91 @@ macro_rules! arbitrary_tuple { } 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); -macro_rules! arbitrary_array { - {$n:expr, ($t:ident, $a:ident) $(($ts:ident, $as:ident))*} => { - arbitrary_array!{($n - 1), $(($ts, $as))*} - - impl<'a, T: Arbitrary<'a>> Arbitrary<'a> for [T; $n] { - fn arbitrary(u: &mut Unstructured<'a>) -> Result<[T; $n]> { - Ok([ - Arbitrary::arbitrary(u)?, - $(<$ts as Arbitrary>::arbitrary(u)?),* - ]) - } - - #[allow(unused_mut)] - fn arbitrary_take_rest(mut u: Unstructured<'a>) -> Result<[T; $n]> { - $(let $as = $ts::arbitrary(&mut u)?;)* - let last = Arbitrary::arbitrary_take_rest(u)?; +// 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, +} - Ok([ - $($as,)* last - ]) - } +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); + } + } +} - #[inline] - fn size_hint(depth: usize) -> (usize, Option<usize>) { - crate::size_hint::and_all(&[ - <$t as Arbitrary>::size_hint(depth), - $( <$ts as Arbitrary>::size_hint(depth) ),* - ]) - } +fn create_array<F, T, const N: usize>(mut cb: F) -> [T; N] +where + F: FnMut(usize) -> 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 (&mut *array.as_mut_ptr()).iter_mut().enumerate() { + core::ptr::write(value_ptr, cb(idx)); + guard.initialized += 1; } + mem::forget(guard); + array.assume_init() + } +} + +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, }; - ($n: expr,) => {}; + unsafe { + for (idx, value_ptr) in (&mut *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: Arbitrary<'a>> Arbitrary<'a> for [T; 0] { - fn arbitrary(_: &mut Unstructured<'a>) -> Result<[T; 0]> { - Ok([]) +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)) } - fn arbitrary_take_rest(_: Unstructured<'a>) -> Result<[T; 0]> { - Ok([]) + #[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(_: usize) -> (usize, Option<usize>) { - crate::size_hint::and_all(&[]) + fn size_hint(d: usize) -> (usize, Option<usize>) { + crate::size_hint::and_all(&create_array::<_, (usize, Option<usize>), N>(|_| { + <T as Arbitrary>::size_hint(d) + })) } } -arbitrary_array! { 32, (T, a) (T, b) (T, c) (T, d) (T, e) (T, f) (T, g) (T, h) -(T, i) (T, j) (T, k) (T, l) (T, m) (T, n) (T, o) (T, p) -(T, q) (T, r) (T, s) (T, u) (T, v) (T, w) (T, x) (T, y) -(T, z) (T, aa) (T, ab) (T, ac) (T, ad) (T, ae) (T, af) -(T, ag) } - impl<'a> Arbitrary<'a> for &'a [u8] { fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { let len = u.arbitrary_len::<u8>()?; @@ -872,7 +906,7 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Box<A> { #[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { - crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) } } @@ -918,7 +952,7 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Arc<A> { #[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { - crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) } } @@ -929,7 +963,7 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for Rc<A> { #[inline] fn size_hint(depth: usize) -> (usize, Option<usize>) { - crate::size_hint::recursion_guard(depth, |depth| <A as Arbitrary>::size_hint(depth)) + crate::size_hint::recursion_guard(depth, <A as Arbitrary>::size_hint) } } @@ -1010,6 +1044,59 @@ impl<'a, A: Arbitrary<'a>> Arbitrary<'a> for ::std::num::Wrapping<A> { } } +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::*; diff --git a/src/unstructured.rs b/src/unstructured.rs index 9e2f497..968d41a 100644 --- a/src/unstructured.rs +++ b/src/unstructured.rs @@ -221,7 +221,7 @@ impl<'a> Unstructured<'a> { } fn arbitrary_byte_size(&mut self) -> Result<usize> { - if self.data.len() == 0 { + if self.data.is_empty() { Ok(0) } else if self.data.len() == 1 { self.data = &[]; @@ -322,7 +322,7 @@ impl<'a> Unstructured<'a> { let mut offset: usize = 0; while offset < mem::size_of::<T>() - && (range >> T::Widest::from_usize(offset)) > T::Widest::ZERO + && (range >> T::Widest::from_usize(offset * 8)) > T::Widest::ZERO { let byte = bytes.next().ok_or(Error::NotEnoughData)?; result = (result << 8) | T::Widest::from_u8(byte); @@ -405,11 +405,9 @@ impl<'a> Unstructured<'a> { /// ``` pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> { let n = std::cmp::min(buffer.len(), self.data.len()); - for i in 0..n { - buffer[i] = self.data[i]; - } - for i in self.data.len()..buffer.len() { - buffer[i] = 0; + buffer[..n].copy_from_slice(&self.data[..n]); + for byte in buffer[n..].iter_mut() { + *byte = 0; } self.data = &self.data[n..]; Ok(()) @@ -701,4 +699,16 @@ mod tests { 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]); + u.int_in_range::<u8>(0..=u8::MAX).unwrap(); + + let mut u = Unstructured::new(&[1]); + u.int_in_range::<u32>(0..=u8::MAX as u32).unwrap(); + + let mut u = Unstructured::new(&[1]); + u.int_in_range::<u32>(0..=u8::MAX as u32 + 1).unwrap_err(); + } } |