No public description PiperOrigin-RevId: 990457042
diff --git a/rust/e2e_tests/testdata/fuzz_tests.rs b/rust/e2e_tests/testdata/fuzz_tests.rs index e725ff9..e2f9afd 100644 --- a/rust/e2e_tests/testdata/fuzz_tests.rs +++ b/rust/e2e_tests/testdata/fuzz_tests.rs
@@ -32,14 +32,14 @@ type UserValue<'user> = Vec<u8>; type CorpusValue = Vec<u8>; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { let mut val = vec![0u8; rng.random_range(0..100)]; rng.fill(&mut val[..]); Ok(val) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -160,12 +160,12 @@ type UserValue<'user> = u32; type CorpusValue = u32; - fn init(&mut self, _rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, _rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(0) } fn mutate( - &mut self, + &self, _val: &mut Self::CorpusValue, _rng: &mut dyn rand::Rng, _only_shrink: bool,
diff --git a/rust/fuzztest_macro/src/helpers/fuzztest_domain.rs b/rust/fuzztest_macro/src/helpers/fuzztest_domain.rs index f74a152..5ee045d 100644 --- a/rust/fuzztest_macro/src/helpers/fuzztest_domain.rs +++ b/rust/fuzztest_macro/src/helpers/fuzztest_domain.rs
@@ -77,14 +77,14 @@ type UserValue<#user_value_lifetime_generic> = #domain_struct_name <#(#user_value_domain_generics),*>; type CorpusValue = #domain_struct_name <#(#corpus_domain_generics),*>; - fn init(&mut self, rng: &mut dyn ::fuzztest::reexports::rand::Rng) -> ::fuzztest::reexports::anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn ::fuzztest::reexports::rand::Rng) -> ::fuzztest::reexports::anyhow::Result<Self::CorpusValue> { Ok(#domain_struct_name { #(#field_names: self.#field_names.init(rng)?),* }) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn ::fuzztest::reexports::rand::Rng, only_shrink: bool, @@ -98,11 +98,6 @@ #(#field_names: self.#field_names.corpus_to_user_value(&corpus_value.#field_names)?),* }) } - - fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> ::fuzztest::reexports::anyhow::Result<()> { - #( self.#field_names.validate_corpus_value(&corpus_value.#field_names)?; )* - Ok(()) - } } }; (domain_definition_tokens, field_names) @@ -149,7 +144,7 @@ type UserValue<'user> = __FuzzTestTestFuzzStateWrapper<T0::UserValue<'user>, T1::UserValue<'user> >; type CorpusValue = __FuzzTestTestFuzzStateWrapper<T0::CorpusValue, T1::CorpusValue>; - fn init(&mut self, rng: &mut dyn ::fuzztest::reexports::rand::Rng) -> ::fuzztest::reexports::anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn ::fuzztest::reexports::rand::Rng) -> ::fuzztest::reexports::anyhow::Result<Self::CorpusValue> { Ok(__FuzzTestTestFuzzStateWrapper { a: self.a.init(rng)?, b: self.b.init(rng)? @@ -157,7 +152,7 @@ } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn ::fuzztest::reexports::rand::Rng, only_shrink: bool, @@ -173,12 +168,6 @@ b: self.b.corpus_to_user_value(&corpus_value.b)? }) } - - fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> ::fuzztest::reexports::anyhow::Result<()> { - self.a.validate_corpus_value(&corpus_value.a)?; - self.b.validate_corpus_value(&corpus_value.b)?; - Ok(()) - } } } .to_string())
diff --git a/rust/fuzztest_macro/src/helpers/test_registration.rs b/rust/fuzztest_macro/src/helpers/test_registration.rs index b38ceec..60e73f5 100644 --- a/rust/fuzztest_macro/src/helpers/test_registration.rs +++ b/rust/fuzztest_macro/src/helpers/test_registration.rs
@@ -111,11 +111,9 @@ let fuzz_test_struct_instance_tokens = quote!( #fuzz_test_struct_name { - domain: std::sync::Arc::new(std::sync::Mutex::new( - #domain_struct_name { + domain: #domain_struct_name { #(#fuzz_test_domain_field_names: #domain_ctors),* - } - )), + }, test_fn: #prop_fn_ident } ); @@ -216,7 +214,7 @@ { where_clauses.predicates.push( parse_quote! { - for <#user_value_lifetime_generic> #domain_gen: #crate_name::domains::Domain<UserValue<#user_value_lifetime_generic> = #ty > + 'static + for <#user_value_lifetime_generic> #domain_gen: #crate_name::domains::Domain<UserValue<#user_value_lifetime_generic> = #ty > }); where_clauses.predicates.push(parse_quote! { #corpus_gen: 'static }); } @@ -231,7 +229,7 @@ #fuzz_test_domain_definition struct #fuzz_test_struct_name #generics { - domain: std::sync::Arc<std::sync::Mutex<#domain_struct_name #generics>>, + domain: #domain_struct_name #generics, test_fn: #test_fn_type } @@ -252,10 +250,7 @@ .downcast_ref::<#domain_struct_name<#(#corpus_generics),*>>() .expect("Attempt to recover user value before testing failed."); - let user_value = self.domain.lock() - .expect("Failed to acquire domain lock") - .corpus_to_user_value(wrapper) - .expect("Failed to get user value from corpus value"); + let user_value = self.domain.corpus_to_user_value(wrapper).expect("Failed to get user value from corpus value"); let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| (self.test_fn)(#(user_value.#fuzz_test_domain_field_names),* ) )); @@ -264,8 +259,8 @@ fn print_finding_report(&self) { todo!("Not implemented!") } - fn domains(&self) -> std::sync::Arc<std::sync::Mutex<dyn #crate_name::domains::GenericDomain>> { - std::sync::Arc::clone(&self.domain) as std::sync::Arc<std::sync::Mutex<dyn #crate_name::domains::GenericDomain>> + fn domains(&self) -> &dyn #crate_name::domains::GenericDomain { + &self.domain } } @@ -306,14 +301,14 @@ expect_that!( fuzztest_object_tokenstream.to_string(), ends_with( quote! { struct __FuzzTestTestFuzz<T0, T1> { - domain: std::sync::Arc<std::sync::Mutex<__FuzzTestTestFuzzStateWrapper<T0, T1> >>, + domain: __FuzzTestTestFuzzStateWrapper<T0, T1>, test_fn: fn(i32, std::string::String) } impl<T0, T1> ::fuzztest::internal::FuzzTest for __FuzzTestTestFuzz<T0, T1> - where for <'user> T0: ::fuzztest::domains::Domain<UserValue<'user> = i32> + 'static, + where for <'user> T0: ::fuzztest::domains::Domain<UserValue<'user> = i32>, T0::CorpusValue: 'static, - for <'user> T1: ::fuzztest::domains::Domain<UserValue<'user> = std::string::String> + 'static, + for <'user> T1: ::fuzztest::domains::Domain<UserValue<'user> = std::string::String>, T1::CorpusValue: 'static { fn name(&self) -> &'static str { "test_fuzz" @@ -331,10 +326,7 @@ .downcast_ref::<__FuzzTestTestFuzzStateWrapper<T0::CorpusValue, T1::CorpusValue>>() .expect("Attempt to recover user value before testing failed."); - let user_value = self.domain.lock() - .expect("Failed to acquire domain lock") - .corpus_to_user_value(wrapper) - .expect("Failed to get user value from corpus value"); + let user_value = self.domain.corpus_to_user_value(wrapper).expect("Failed to get user value from corpus value"); // Safety: Data is not reused after the test. let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| (self.test_fn)(user_value.a, user_value.b) )); @@ -343,19 +335,17 @@ fn print_finding_report(&self) { todo!("Not implemented!") } - fn domains(&self) -> std::sync::Arc<std::sync::Mutex<dyn ::fuzztest::domains::GenericDomain>> { - std::sync::Arc::clone(&self.domain) as std::sync::Arc<std::sync::Mutex<dyn ::fuzztest::domains::GenericDomain>> + fn domains(&self) -> &dyn ::fuzztest::domains::GenericDomain { + &self.domain } } fn __FuzzTestTestFuzz_factory() -> ::fuzztest::internal::BoxedFuzzTest { ::std::boxed::Box::new(__FuzzTestTestFuzz { - domain: std::sync::Arc::new(std::sync::Mutex::new( - __FuzzTestTestFuzzStateWrapper { - a: ::fuzztest::domains::arbitrary::Arbitrary::<i32>::default(), - b: ::fuzztest::domains::arbitrary::Arbitrary::<String>::default() - } - )), + domain: __FuzzTestTestFuzzStateWrapper { + a: ::fuzztest::domains::arbitrary::Arbitrary::<i32>::default(), + b: ::fuzztest::domains::arbitrary::Arbitrary::<String>::default() + }, test_fn: __property_fn__test_fuzz }) }
diff --git a/rust/src/domains.rs b/rust/src/domains.rs index 3857424..550fa2f 100644 --- a/rust/src/domains.rs +++ b/rust/src/domains.rs
@@ -123,15 +123,15 @@ type CorpusValue: Serialize + DeserializeOwned + Clone; /// Initializes a new value drawn from the domain. - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue>; + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue>; /// Mutates the value in `val` to a new value drawn from the domain. /// /// If `only_shrink` is `true`, then the mutation must not increase the size of the corpus /// value. Otherwise, the mutation can both shrink and grow the corpus value. fn mutate( - &mut self, - corpus_value: &mut Self::CorpusValue, + &self, + val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, ) -> anyhow::Result<()>; @@ -177,16 +177,6 @@ fn serialize_corpus(&self, corpus_value: &Self::CorpusValue) -> anyhow::Result<Vec<u8>> { postcard::to_stdvec(corpus_value).context("Failed to serialize corpus value to bytes") } - - /// Validates that a corpus value satisfies the domain's constraints. - /// - /// This method is called, among other things, after the `CorpusValue` was constructed from a - /// user provided value. - /// For example, when the domain is seeded, this method is used to check that seeds specified by - /// the users are valid given the domain's constraints. - fn validate_corpus_value(&self, _corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - Ok(()) - } } /// A type-erased interface for Domain types. @@ -199,14 +189,14 @@ /// Initializes a new value drawn from the domain. /// /// See `Domain::init` for more details. - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<GenericCorpusValue>; + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<GenericCorpusValue>; /// Mutates the value in `val` to a new value drawn from the domain. /// /// See `Domain::mutate` for more details. fn mutate( - &mut self, - corpus_value: &mut GenericCorpusValue, + &self, + val: &mut GenericCorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, ) -> anyhow::Result<()>; @@ -231,7 +221,7 @@ D: Domain, D::CorpusValue: 'static, { - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<GenericCorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<GenericCorpusValue> { Ok(Box::new(self.init(rng)?)) } @@ -243,13 +233,13 @@ /// /// See `GenericDomain::mutate` for more details. fn mutate( - &mut self, - corpus_value: &mut GenericCorpusValue, + &self, + val: &mut GenericCorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, ) -> anyhow::Result<()> { self.mutate( - corpus_value.downcast_mut().context("Failed to retrieve the Corpus Value")?, + val.downcast_mut().context("Failed to retrieve the Corpus Value")?, rng, only_shrink, )
diff --git a/rust/src/domains/arbitrary.rs b/rust/src/domains/arbitrary.rs index 326e16a..303d751 100644 --- a/rust/src/domains/arbitrary.rs +++ b/rust/src/domains/arbitrary.rs
@@ -36,7 +36,7 @@ /// # use rand::rngs::SmallRng; /// # use rand::SeedableRng; /// -/// let mut arbitrary_i32 = Arbitrary::<i32>::default(); +/// let arbitrary_i32 = Arbitrary::<i32>::default(); /// let mut rng = SmallRng::seed_from_u64(73); /// /// let sample = arbitrary_i32.init(&mut rng); @@ -46,13 +46,13 @@ _phantom: PhantomData<T>, } -impl<T: Clone> Clone for Arbitrary<T> { +impl<T> Clone for Arbitrary<T> { fn clone(&self) -> Self { Self { _phantom: PhantomData } } } -impl<T: fmt::Debug> fmt::Debug for Arbitrary<T> { +impl<T> fmt::Debug for Arbitrary<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Arbitrary").field("_phantom", &self._phantom).finish() } @@ -68,7 +68,7 @@ impl<T> Arbitrary<T> { /// Creates a new `Arbitrary` domain for the given type `T`. pub fn new() -> Self { - Self::default() + Self { _phantom: PhantomData } } } @@ -76,12 +76,12 @@ type UserValue<'user> = bool; type CorpusValue = bool; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(rng.random()) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -101,10 +101,6 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(*corpus_value) } - - fn validate_corpus_value(&self, _corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - Ok(()) - } } macro_rules! impl_domain_for_integer { @@ -116,14 +112,14 @@ type UserValue<'user> = $ty; type CorpusValue = $ty; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { - // We generate the equivalent integer type so this works for size types. + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + // We generate a the equivalent integer type so this works for size types. let val: $int_ty = choose_value(rng); Ok(val as $ty) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -148,13 +144,6 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(*corpus_value) } - - fn validate_corpus_value( - &self, - _corpus_value: &Self::CorpusValue, - ) -> anyhow::Result<()> { - Ok(()) - } } }; } @@ -178,12 +167,12 @@ type UserValue<'user> = $ty; type CorpusValue = $ty; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(choose_value(rng)) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -226,13 +215,6 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(*corpus_value) } - - fn validate_corpus_value( - &self, - _corpus_value: &Self::CorpusValue, - ) -> anyhow::Result<()> { - Ok(()) - } } }; } @@ -281,12 +263,12 @@ type UserValue<'user> = char; type CorpusValue = char; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(choose_value(rng)) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -318,22 +300,18 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(*corpus_value) } - - fn validate_corpus_value(&self, _corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - Ok(()) - } } impl Domain for Arbitrary<()> { type UserValue<'user> = (); type CorpusValue = (); - fn init(&mut self, _rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, _rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(()) } fn mutate( - &mut self, + &self, _val: &mut Self::CorpusValue, _rng: &mut dyn rand::Rng, _only_shrink: bool, @@ -348,10 +326,6 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(()) } - - fn validate_corpus_value(&self, _corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - Ok(()) - } } #[cfg(test)] @@ -438,7 +412,7 @@ CorpusValueForArbitrary<T>: std::fmt::Debug + Default + Clone + Copy + PartialOrd + PartialEq + 'static, { - let mut domain = Arbitrary::<T>::default(); + let domain = Arbitrary::<T>::default(); let mut rng = get_rng(); let mut value = domain.init(&mut rng).unwrap(); @@ -468,7 +442,7 @@ + std::hash::Hash + 'static, { - let mut domain = Arbitrary::<T>::default(); + let domain = Arbitrary::<T>::default(); let mut rng = get_rng(); for _ in 0..100 { let mut value = domain.init(&mut rng).unwrap(); @@ -500,7 +474,7 @@ + NumTraitsExtended + 'static, { - let mut domain = Arbitrary::<T>::default(); + let domain = Arbitrary::<T>::default(); let mut rng = get_rng(); // Get a value that is not the shrink target @@ -646,7 +620,7 @@ } fn test_bool_shrink() { - let mut domain = Arbitrary::<bool>::default(); + let domain = Arbitrary::<bool>::default(); let mut rng = get_rng(); let mut value = true; domain.mutate(&mut value, &mut rng, true).unwrap(); @@ -663,7 +637,7 @@ #[test] fn test_unit() { let mut rng = get_rng(); - let mut domain = Arbitrary::<()>::default(); + let domain = Arbitrary::<()>::default(); // init() always returns () assert_eq!(domain.init(&mut rng).unwrap(), ()); @@ -686,7 +660,7 @@ Float + SampleUniform + std::fmt::Display + std::fmt::Debug + SpecialValues + 'static, StandardUniform: Distribution<T>, { - let mut domain = Arbitrary::<T>::default(); + let domain = Arbitrary::<T>::default(); let mut rng = get_rng(); // Positive. @@ -750,7 +724,7 @@ #[test] fn test_char_mutate_boundaries() { - let mut domain = Arbitrary::<char>::default(); + let domain = Arbitrary::<char>::default(); let mut rng = get_rng(); let mut val = '\u{0000}'; domain.mutate(&mut val, &mut rng, false).unwrap(); @@ -789,7 +763,7 @@ #[test] fn test_char_shrink_to_null() { for _ in 0..10 { - let mut domain = Arbitrary::<char>::default(); + let domain = Arbitrary::<char>::default(); let mut rng = get_rng(); let mut value = domain.init(&mut rng).unwrap();
diff --git a/rust/src/domains/containers.rs b/rust/src/domains/containers.rs index 4c816a1..30bc1e9 100644 --- a/rust/src/domains/containers.rs +++ b/rust/src/domains/containers.rs
@@ -1,7 +1,8 @@ -use super::Domain; use rand::RngExt; use std::fmt; +use super::Domain; + const DEFAULT_MAX_LEN: usize = 5000; macro_rules! choose_one { @@ -127,7 +128,7 @@ type CorpusValue = Vec<T::CorpusValue>; type UserValue<'user> = Vec<T::UserValue<'user>>; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { if self.max_len() == 0 { return Ok(Vec::new()); } @@ -142,7 +143,7 @@ } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -192,32 +193,9 @@ } Ok(user_values) } - - fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - if self.max_len_is_soft { - anyhow::ensure!( - self.min_len <= corpus_value.len(), - "Length {} is less than the minimum length {}", - corpus_value.len(), - self.min_len - ); - } else { - anyhow::ensure!( - self.min_len <= corpus_value.len() && corpus_value.len() <= self.max_len(), - "Length {} is not between the minimum length {} and maximum length {}", - corpus_value.len(), - self.min_len, - self.max_len() - ); - } - for item in corpus_value { - self.inner.validate_corpus_value(item)?; - } - Ok(()) - } } -impl<T: Domain> ContainerDomain for VecOf<T> { +impl<T> ContainerDomain for VecOf<T> { fn with_len(self, len: usize) -> Self { Self { min_len: len, max_len: Some(len), ..self } } @@ -267,7 +245,7 @@ #[gtest] fn test_vec_of_mutate_shrink() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(10); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(10); let mut rng = get_rng(); @@ -286,7 +264,7 @@ #[gtest] fn test_vec_of_mutate_grow_and_change() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(10); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(10); let mut rng = get_rng(); @@ -306,7 +284,7 @@ #[gtest] fn test_vec_of_init_respects_min_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(5); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(5); let mut rng = get_rng(); for _ in 0..100 { @@ -317,7 +295,7 @@ #[gtest] fn test_vec_of_init_fixed_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_len(7); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_len(7); let mut rng = get_rng(); for _ in 0..100 { @@ -328,7 +306,7 @@ #[gtest] fn test_vec_of_init_default_max_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()); + let domain = VecOf::new(Arbitrary::<u32>::default()); let mut rng = get_rng(); for _ in 0..100 { @@ -339,7 +317,7 @@ #[gtest] fn test_vec_of_mutate_respects_min_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(3); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(3); let mut rng = get_rng(); let mut val = vec![1, 2, 3]; @@ -351,7 +329,7 @@ #[gtest] fn test_vec_of_mutate_respects_max_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(3); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_max_len(3); let mut rng = get_rng(); let mut val = vec![1, 2, 3]; @@ -363,7 +341,7 @@ #[gtest] fn test_vec_of_mutate_min_len_validation() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(5); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_min_len(5); let mut rng = get_rng(); let mut val = vec![1, 2, 3]; // Length 3, which is < 5 @@ -380,7 +358,7 @@ #[gtest] fn test_vec_of_mutate_soft_max_len_behavior() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_soft_max_len(5); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_soft_max_len(5); let mut rng = get_rng(); // Valid mutation within bounds @@ -416,7 +394,7 @@ #[gtest] fn test_vec_of_mutate_no_action_at_bounds() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_len(1); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_len(1); let mut rng = get_rng(); let mut val = vec![100u32]; @@ -437,7 +415,7 @@ #[gtest] fn test_vec_of_zero_len() { - let mut domain = VecOf::new(Arbitrary::<u32>::default()).with_len(0); + let domain = VecOf::new(Arbitrary::<u32>::default()).with_len(0); let mut rng = get_rng(); let val = domain.init(&mut rng).unwrap();
diff --git a/rust/src/domains/range.rs b/rust/src/domains/range.rs index 24208de..1794146 100644 --- a/rust/src/domains/range.rs +++ b/rust/src/domains/range.rs
@@ -29,7 +29,7 @@ /// # use fuzztest::domains::range::InRange; /// # use rand::prelude::*; /// -/// let mut range_i32 = InRange::new(21i32, 73); +/// let range_i32 = InRange::new(21i32, 73); /// let sample = range_i32.init(&mut rand::rng()); /// /// assert!(sample.is_ok()); @@ -57,12 +57,12 @@ type UserValue<'user> = i32; type CorpusValue = i32; - fn init(&mut self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { + fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<Self::CorpusValue> { Ok(self.get_in_range(rng)) } fn mutate( - &mut self, + &self, val: &mut Self::CorpusValue, rng: &mut dyn rand::Rng, only_shrink: bool, @@ -81,18 +81,6 @@ ) -> anyhow::Result<Self::UserValue<'a>> { Ok(*corpus_value) } - - fn validate_corpus_value(&self, corpus_value: &Self::CorpusValue) -> anyhow::Result<()> { - if *corpus_value < self.lower || *corpus_value > self.upper { - anyhow::bail!( - "Value {} is out of range [{}, {}]", - corpus_value, - self.lower, - self.upper - ); - } - Ok(()) - } } #[cfg(test)]
diff --git a/rust/src/internal.rs b/rust/src/internal.rs index 5f7e95b..213e66a 100644 --- a/rust/src/internal.rs +++ b/rust/src/internal.rs
@@ -14,11 +14,8 @@ use super::domains::GenericCorpusValue; use super::domains::GenericDomain; - use std::collections::HashMap; -use std::sync::Arc; use std::sync::LazyLock; -use std::sync::Mutex; /// A trait implemented by types used to Fuzz a given property function. /// @@ -38,7 +35,7 @@ /// Returns `true` if the property function holds, `false` if it crashes. fn execute(&self, args: &GenericCorpusValue) -> bool; fn print_finding_report(&self); - fn domains(&self) -> Arc<Mutex<dyn GenericDomain>>; + fn domains(&self) -> &dyn GenericDomain; } /// Identifies the property function of a fuzz test.
diff --git a/rust/src/worker.rs b/rust/src/worker.rs index cd9ed80..e19f21f 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs
@@ -158,9 +158,7 @@ } pub fn get_random_seed_input(&self, sink: &mut InputSink) { - let domains = self.fuzz_test.domains(); - let mut domains_guard = domains.lock().expect("Failed to lock domains"); - match domains_guard.init(&mut rand::rng()) { + match self.fuzz_test.domains().init(&mut rand::rng()) { Ok(val) => { sink.emit(pack_input(val)); } @@ -172,10 +170,8 @@ pub fn mutate(&self, origin: &GenericCorpusValue, shrink: bool, sink: &mut InputSink) { let mut mutant = origin.clone(); - let domains = self.fuzz_test.domains(); - let mut domains_guard = domains.lock().expect("Failed to lock domains"); - if let Err(e) = domains_guard.mutate(&mut mutant, &mut rand::rng(), shrink) { + if let Err(e) = self.fuzz_test.domains().mutate(&mut mutant, &mut rand::rng(), shrink) { emit_error(&format!("Failed to mutate: {:?}", e)); return; } @@ -215,9 +211,7 @@ } pub fn serialize_input_content(&self, input: &GenericCorpusValue, sink: &mut BytesSink) { - let domains = self.fuzz_test.domains(); - let domains_guard = domains.lock().expect("Failed to lock domains"); - match domains_guard.serialize_corpus(input) { + match self.fuzz_test.domains().serialize_corpus(input) { Ok(serialized) => { sink.emit(&serialized); } @@ -228,9 +222,7 @@ } pub fn deserialize_input_content(&self, content: &[u8], sink: &mut InputSink) { - let domains = self.fuzz_test.domains(); - let domains_guard = domains.lock().expect("Failed to lock domains"); - match domains_guard.parse_corpus(content) { + match self.fuzz_test.domains().parse_corpus(content) { Ok(val) => { sink.emit(pack_input(val)); } @@ -250,9 +242,8 @@ pub fn free_input(&self, input: engine_ffi::FuzzTestInputHandle) { if input.0 != 0 { - // SAFETY: The engine guarantees `input` was created by - // `deserialize_input_content_callback` (or `emit` in `InputSink`) and has - // not been freed yet. + // SAFETY: The engine guarantees `input` was created by `deserialize_input_content_callback` + // (or `emit` in `InputSink`) and has not been freed yet. unsafe { let _ = Box::from_raw(input.0 as *mut GenericCorpusValue); } @@ -301,8 +292,8 @@ /// /// The caller must ensure that: /// * `ctx` is a valid pointer to the `RustFuzzTestAdapterManager` passed during initialization. -/// * `sink` is a valid pointer to a `FuzzTestBytesSink` whose lifetime extends for the duration of -/// this call. +/// * `sink` is a valid pointer to a `FuzzTestBytesSink` whose lifetime extends for the duration +/// of this call. pub unsafe extern "C" fn get_binary_id_callback( ctx: *mut engine_ffi::FuzzTestAdapterManagerCtx, sink: *const engine_ffi::FuzzTestBytesSink, @@ -320,8 +311,8 @@ /// /// The caller must ensure that: /// * `ctx` is a valid pointer to the `RustFuzzTestAdapterManager` passed during initialization. -/// * `sink` is a valid pointer to a `FuzzTestBytesSink` whose lifetime extends for the duration of -/// this call. +/// * `sink` is a valid pointer to a `FuzzTestBytesSink` whose lifetime extends for the duration +/// of this call. pub unsafe extern "C" fn get_test_name_callback( ctx: *mut engine_ffi::FuzzTestAdapterManagerCtx, sink: *const engine_ffi::FuzzTestBytesSink, @@ -351,8 +342,8 @@ // passed during initialization. let manager = unsafe { &*(ctx as *const RustFuzzTestAdapterManager) }; - // SAFETY: The engine guarantees `diagnostic_sink` is a valid pointer to a - // `FuzzTestDiagnosticSink` whose lifetime extends until `FreeCtx` is called on the adapter. + // SAFETY: The engine guarantees `diagnostic_sink` is a valid pointer to a `FuzzTestDiagnosticSink` + // whose lifetime extends until `FreeCtx` is called on the adapter. let safe_sink = unsafe { DiagnosticSink::from_raw(diagnostic_sink) }; set_diagnostic_sink(safe_sink); @@ -396,8 +387,7 @@ // SAFETY: The engine guarantees `ctx` is a valid pointer to the `RustFuzzTestAdapter` // created by `construct_adapter_callback`. let adapter = unsafe { &*(ctx as *const RustFuzzTestAdapter) }; - // SAFETY: The engine guarantees `registry` is a valid pointer to - // `FuzzTestCoverageDomainRegistry`. + // SAFETY: The engine guarantees `registry` is a valid pointer to `FuzzTestCoverageDomainRegistry`. let mut registry = unsafe { CoverageDomainRegistry::from_raw(registry) }; adapter.set_up_coverage_domains(&mut registry); } @@ -587,8 +577,7 @@ /// * `ctx` is a valid pointer to the `RustFuzzTestAdapter` created by `construct_adapter_callback`. /// * `metadata` is a valid pointer to `FuzzTestBytesView` containing serialized input metadata. /// * `input` is a valid `FuzzTestInputHandle` pointing to a heap-allocated `GenericCorpusValue` -/// managed by the framework, and the engine guarantees exclusive access to it for the call -/// duration. +/// managed by the framework, and the engine guarantees exclusive access to it for the call duration. pub unsafe extern "C" fn update_input_metadata_callback( ctx: *mut engine_ffi::FuzzTestAdapterCtx, metadata: *const engine_ffi::FuzzTestBytesView, @@ -650,8 +639,6 @@ let mut generic_corpus_value = fuzztest .domains() - .lock() - .expect("Failed to lock domains") .init(&mut rng) .expect("domain initialization should succeed to provide an initial corpus value"); @@ -662,8 +649,6 @@ while start_time.elapsed() < smoke_test_duration { fuzztest .domains() - .lock() - .expect("Failed to lock domains") .mutate(&mut generic_corpus_value, &mut rng, only_shrink) .expect("domain mutation should succeed"); let result = fuzztest.execute(&generic_corpus_value); @@ -688,9 +673,9 @@ /// engine loop until complete. /// - Returns cleanly on [`WorkerStatus::Success`], or panics on [`WorkerStatus::Failure`] to /// signal test failure to the harness. -/// 2. Smoke Test Mode: If worker mode is not active (e.g., during standard `blaze test` or `cargo -/// test` unit test runs), falls back to executing a short local smoke test using sample inputs -/// and mutation iterations to verify property function sanity. +/// 2. Smoke Test Mode: If worker mode is not active (e.g., during standard `blaze test` or +/// `cargo test` unit test runs), falls back to executing a short local smoke test using sample +/// inputs and mutation iterations to verify property function sanity. pub fn process(manager: RustFuzzTestAdapterManager) { super::crash_handler::register_crash_handler();