diff --git a/fuzz/fuzz_targets/bench/lib.rs b/fuzz/fuzz_targets/bench/lib.rs index 9176cf30..4d9218e0 100644 --- a/fuzz/fuzz_targets/bench/lib.rs +++ b/fuzz/fuzz_targets/bench/lib.rs @@ -30,6 +30,7 @@ pub fn roundtrip_arbitrary_typed_ron_or_panic(data: &[u8]) -> Option panic!("{:?} -! {:?}", typed_value, err), }; + if let Err(err) = ron::Options::default().from_str::(&ron) { match err.code { // Erroring on deep recursion is better than crashing on a stack overflow @@ -38,6 +39,7 @@ pub fn roundtrip_arbitrary_typed_ron_or_panic(data: &[u8]) -> Option panic!("{:?} -> {} -! {:?}", typed_value, ron, err), } }; + if let Err(err) = ron::Options::default().from_str_seed(&ron, &typed_value) { match err.code { // Erroring on deep recursion is better than crashing on a stack overflow @@ -46,7 +48,7 @@ pub fn roundtrip_arbitrary_typed_ron_or_panic(data: &[u8]) -> Option panic!("{:?} -> {} -! {:?}", typed_value, ron, err), } }; - // TODO: also do typed deserialise + Some(typed_value) } else { None @@ -189,7 +191,12 @@ impl<'a> Serialize for BorrowedTypedSerdeData<'a> { serializer.serialize_none() } } - (SerdeDataType::Array { kind, len }, SerdeDataValue::Seq { elems }) => { + ( + SerdeDataType::Array { + kind_len: (kind, len), + }, + SerdeDataValue::Seq { elems }, + ) => { if elems.len() != *len { return Err(serde::ser::Error::custom("mismatch array len")); } @@ -530,7 +537,12 @@ impl<'a, 'de> DeserializeSeed<'de> for BorrowedTypedSerdeData<'a> { value: value.as_deref(), }) } - (SerdeDataType::Array { kind, len }, SerdeDataValue::Seq { elems }) => { + ( + SerdeDataType::Array { + kind_len: (kind, len), + }, + SerdeDataValue::Seq { elems }, + ) => { struct ArrayVisitor<'a> { kind: &'a SerdeDataType<'a>, elems: &'a [SerdeDataValue<'a>], @@ -1327,10 +1339,8 @@ pub enum SerdeDataType<'a> { inner: Box, }, Array { - #[arbitrary(with = arbitrary_recursion_guard)] - kind: Box, - #[arbitrary(with = arbitrary_recursion_guard)] - len: usize, + #[arbitrary(with = arbitrary_array_len_recursion_guard)] + kind_len: (Box, usize), }, Tuple { #[arbitrary(with = arbitrary_recursion_guard)] @@ -1403,11 +1413,9 @@ impl<'a> SerdeDataType<'a> { }; Ok(SerdeDataValue::Option { inner: value }) } - SerdeDataType::Array { kind, len } => { - if *len > 32 { - // Restrict array lengths to be reasonable, as arbitrary cannot - return Err(arbitrary::Error::IncorrectFormat); - } + SerdeDataType::Array { + kind_len: (kind, len), + } => { let mut array = Vec::with_capacity(*len); for _ in 0..*len { array.push(kind.arbitrary_value(u)?); @@ -1422,17 +1430,15 @@ impl<'a> SerdeDataType<'a> { Ok(SerdeDataValue::Seq { elems: tuple }) } SerdeDataType::Vec { item } => { - let len = u.arbitrary_len::()?.min(4); - let mut vec = Vec::with_capacity(len); - for _ in 0..len { + let mut vec = Vec::new(); + while u.arbitrary()? { vec.push(item.arbitrary_value(u)?); } Ok(SerdeDataValue::Seq { elems: vec }) } SerdeDataType::Map { key, value } => { - let len = u.arbitrary_len::()?.min(4); - let mut map = Vec::with_capacity(len); - for _ in 0..len { + let mut map = Vec::new(); + while u.arbitrary()? { map.push((key.arbitrary_value(u)?, value.arbitrary_value(u)?)); } Ok(SerdeDataValue::Map { elems: map }) @@ -1559,6 +1565,46 @@ fn arbitrary_recursion_guard<'a, T: Arbitrary<'a> + Default>( result } +fn arbitrary_array_len_recursion_guard<'a>( + u: &mut Unstructured<'a>, +) -> arbitrary::Result<(Box>, usize)> { + const MAX_ARRAY_SPREAD: usize = 32; + static ARRAY_SPREAD: AtomicUsize = AtomicUsize::new(1); + + let max_depth = ron::Options::default() + .recursion_limit + .map_or(256, |limit| limit * 2); + + // Fall back to zero-sized arrays if the input is exhausted + if u.is_empty() { + return Ok((Box::new(SerdeDataType::Unit), 0)); + } + + let result = if RECURSION_DEPTH.fetch_add(1, Ordering::Relaxed) < max_depth { + // Limit the maximum array spread, since arbitrary cannot + let spread = ARRAY_SPREAD.load(Ordering::Relaxed); + let len = u.int_in_range::(0..=(MAX_ARRAY_SPREAD / spread).clamp(1, 16))?; + + // Only generate intricate inner array types if the length is non-zero + let kind = if len > 0 { + ARRAY_SPREAD.swap(spread * len, Ordering::Relaxed); + let kind = SerdeDataType::arbitrary(u)?; + ARRAY_SPREAD.swap(spread, Ordering::Relaxed); + kind + } else { + SerdeDataType::Unit + }; + + Ok((Box::new(kind), len)) + } else { + Ok((Box::new(SerdeDataType::Unit), 0)) + }; + + RECURSION_DEPTH.fetch_sub(1, Ordering::Relaxed); + + result +} + fn arbitrary_str_tuple_vec_recursion_guard<'a, T: Arbitrary<'a>>( u: &mut Unstructured<'a>, ) -> arbitrary::Result<(Vec<&'a str>, Vec)> { @@ -1567,11 +1613,10 @@ fn arbitrary_str_tuple_vec_recursion_guard<'a, T: Arbitrary<'a>>( .map_or(256, |limit| limit * 2); let result = if RECURSION_DEPTH.fetch_add(1, Ordering::Relaxed) < max_depth { - let len = u.arbitrary_len::<(&str, T)>()?; - let mut s = Vec::with_capacity(len); - let mut v = Vec::with_capacity(len); + let mut s = Vec::new(); + let mut v = Vec::new(); - for _ in 0..len { + while u.arbitrary()? { s.push(<&str>::arbitrary(u)?); v.push(T::arbitrary(u)?); }