| // Copyright 2026 Google LLC | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| pub mod arbitrary; | |
| pub mod containers; | |
| pub mod range; | |
| pub mod tuple_of; | |
| pub mod utility; | |
| use ::serde::de::DeserializeOwned; | |
| use ::serde::Serialize; | |
| use anyhow; | |
| use anyhow::Context; | |
| use std::any::Any; | |
| pub trait CloneAny: Any { | |
| fn clone_box(&self) -> Box<dyn CloneAny>; | |
| fn as_any(&self) -> &dyn Any; | |
| fn as_mut_any(&mut self) -> &mut dyn Any; | |
| } | |
| impl dyn CloneAny { | |
| /// Returns `true` if the underlying type is of type `T` | |
| pub fn is<T: Any>(&self) -> bool { | |
| self.as_any().is::<T>() | |
| } | |
| /// Returns a reference to the concrete value if it is of type `T`, or `None` otherwise. | |
| pub fn downcast_ref<T: Any>(&self) -> Option<&T> { | |
| self.as_any().downcast_ref::<T>() | |
| } | |
| /// Returns a mutable reference to the concrete value if it is of type `T`, or `None` otherwise. | |
| pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> { | |
| self.as_mut_any().downcast_mut::<T>() | |
| } | |
| } | |
| impl<T: Any + Clone> CloneAny for T { | |
| fn clone_box(&self) -> Box<dyn CloneAny> { | |
| // Prevent infinite recursion if T is a nested Box type. | |
| if let Some(boxed) = self.as_any().downcast_ref::<Box<dyn CloneAny>>() { | |
| return (**boxed).clone_box(); | |
| } | |
| Box::new(self.clone()) | |
| } | |
| fn as_any(&self) -> &dyn Any { | |
| self | |
| } | |
| fn as_mut_any(&mut self) -> &mut dyn Any { | |
| self | |
| } | |
| } | |
| impl Clone for Box<dyn CloneAny> { | |
| fn clone(&self) -> Self { | |
| self.clone_box() | |
| } | |
| } | |
| /// Type alias for a type-erased corpus value. | |
| pub type GenericCorpusValue = Box<dyn CloneAny>; | |
| /// Type alias for a type-erased user value. | |
| pub type GenericUserValue = Box<dyn CloneAny>; | |
| /// A trait for types that represent a set of values that an input can take. | |
| /// | |
| /// Domain types are used to represent the domain of values that a fuzz test input can take | |
| /// throughout the fuzzing process. | |
| /// Domain types are used by the fuzzing engine through the APIs defined in this trait. | |
| /// | |
| /// ## Serialization/Deserialization of CorpusValue and UserValue relationship. | |
| /// | |
| /// The values drawn from a domain are always of type `CorpusValue`. These values are the | |
| /// internal representation of the value and they are not directly usable by the fuzz property | |
| /// function. | |
| /// | |
| /// The `corpus_to_user_value` method is used to retrieve the user value from the corpus value. For | |
| /// example, if the domain outputs an `&str` then the CorpusValue could be a `String` and the | |
| /// `corpus_to_user_value` method would be used to retrieve the `&str` from the `String`. | |
| /// | |
| /// The `parse_corpus` (resp. `serialize_corpus`) method is used deserialize (resp. serialize) | |
| /// the corpus value from (to) a slice of bytes (resp. a vector of bytes). | |
| /// | |
| /// ### Relationship diagram | |
| /// | |
| /// The methods below are responsible for transforming between `UserValue`, `CorpusValue`, and the | |
| /// serialized representation of `CorpusValue`. Here's a quick overview: | |
| /// | |
| /// ```text | |
| /// +-- corpus_to_user_value() <---+ +-- parse_corpus() <---+ | |
| /// | | | | | |
| /// v | v | | |
| /// UserValue<'a> CorpusValue &[u8] | |
| /// | ^ | |
| /// | | | |
| /// +-> serialize_corpus() + | |
| /// ``` | |
| pub trait Domain { | |
| /// The type of the values that the domain outputs. This should of the same type as the | |
| /// parameter of the fuzz property function. | |
| type UserValue<'user>; | |
| /// The type of the corpus from which the values of type UserValue are drawn. | |
| /// For example, if the domain should output an `&str` then the UserValue should be `&str` and | |
| /// the CorpusValue could the owned data structured that the `&str` points to (eg: String). | |
| /// The CorpusValue type should implement `serde::Serialize`, `serde::de::DeserializeOwned` and | |
| /// `Clone`. | |
| type CorpusValue: Serialize + DeserializeOwned + Clone; | |
| /// Initializes a new value drawn from the domain. | |
| 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( | |
| &self, | |
| val: &mut Self::CorpusValue, | |
| rng: &mut dyn rand::Rng, | |
| only_shrink: bool, | |
| ) -> anyhow::Result<()>; | |
| /// Deprecated alias of `corpus_to_user_value`. | |
| /// | |
| /// `get_user_value` and `corpus_to_user_value` have default implementations that delegate to | |
| /// each other, so implementors can provide either one during the migration. Implementors | |
| /// MUST override at least one of them; otherwise calling either will recurse infinitely. | |
| #[deprecated(note = "Use `corpus_to_user_value` instead")] | |
| fn get_user_value<'a>( | |
| &self, | |
| val: &'a Self::CorpusValue, | |
| ) -> anyhow::Result<Self::UserValue<'a>> { | |
| self.corpus_to_user_value(val) | |
| } | |
| /// Retrieves a UserValue from a given CorpusValue. | |
| /// | |
| /// This is used to convert the corpus value into the user value that can then be passed to the | |
| /// fuzz property function. | |
| /// | |
| /// The default implementation delegates to the deprecated `get_user_value` for backwards | |
| /// compatibility. New implementors should override this method instead. | |
| fn corpus_to_user_value<'a>( | |
| &self, | |
| corpus_value: &'a Self::CorpusValue, | |
| ) -> anyhow::Result<Self::UserValue<'a>> { | |
| #[allow(deprecated)] | |
| self.get_user_value(corpus_value) | |
| } | |
| /// Turns a slice of bytes into `CorpusValue`. | |
| /// | |
| /// By default, it uses Postcard to deserialize the data. | |
| fn parse_corpus(&self, data: &[u8]) -> anyhow::Result<Self::CorpusValue> { | |
| postcard::from_bytes(data).context("Failed to deserialize corpus value from bytes") | |
| } | |
| /// Serializes `corpus_value` to a Vec of bytes (ie, Vec<u8>). | |
| /// | |
| /// By default, it uses Postcard to serialize the data. | |
| 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") | |
| } | |
| } | |
| /// A type-erased interface for Domain types. | |
| /// | |
| /// This trait is used to expose a common interface for Domain types to the fuzzing engine through | |
| /// the `FuzzTest` trait. | |
| /// The methods of this trait are similar to that of the `Domain` trait, but they operate on | |
| /// a type-erased `GenericCorpusValue` instead of an explicit type. | |
| pub trait GenericDomain { | |
| /// Initializes a new value drawn from the domain. | |
| /// | |
| /// See `Domain::init` for more details. | |
| 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( | |
| &self, | |
| val: &mut GenericCorpusValue, | |
| rng: &mut dyn rand::Rng, | |
| only_shrink: bool, | |
| ) -> anyhow::Result<()>; | |
| /// Parses a slice of bytes into a `GenericCorpusValue`. | |
| /// | |
| /// See `Domain::parse_corpus` for more details. | |
| fn parse_corpus(&self, data: &[u8]) -> anyhow::Result<GenericCorpusValue>; | |
| /// Serializes a `GenericCorpusValue` to a Vec of bytes (ie, Vec<u8>). | |
| /// | |
| /// See `Domain::serialize_corpus` for more details. | |
| fn serialize_corpus(&self, val: &GenericCorpusValue) -> anyhow::Result<Vec<u8>>; | |
| } | |
| /// Blanket implementation of the `GenericDomain` trait for types implementing the `Domain` trait. | |
| /// | |
| /// This implementation is a simple pass-through implementation that uses the methods of the | |
| /// `Domain` trait to implement the `GenericDomain` trait. | |
| impl<D> GenericDomain for D | |
| where | |
| D: Domain, | |
| D::CorpusValue: 'static, | |
| { | |
| fn init(&self, rng: &mut dyn rand::Rng) -> anyhow::Result<GenericCorpusValue> { | |
| Ok(Box::new(self.init(rng)?)) | |
| } | |
| /// Retrieves the underlying `Domain`'s `CorpusValue` from the `GenericCorpusValue` and calls | |
| /// the underlying `Domain::mutate` method. | |
| /// | |
| /// If the `GenericCorpusValue` cannot be downcasted to the underlying `Domain`'s `CorpusValue` | |
| /// then an Error is returned. | |
| /// | |
| /// See `GenericDomain::mutate` for more details. | |
| fn mutate( | |
| &self, | |
| val: &mut GenericCorpusValue, | |
| rng: &mut dyn rand::Rng, | |
| only_shrink: bool, | |
| ) -> anyhow::Result<()> { | |
| self.mutate( | |
| val.downcast_mut().context("Failed to retrieve the Corpus Value")?, | |
| rng, | |
| only_shrink, | |
| ) | |
| } | |
| /// Calls the underlying `Domain::parse_corpus` method with the `data` and wraps the resulting | |
| /// `CorpusValue` in a `GenericCorpusValue`. | |
| /// | |
| /// See `GenericDomain::parse_corpus` for more details. | |
| fn parse_corpus(&self, data: &[u8]) -> anyhow::Result<GenericCorpusValue> { | |
| Ok(Box::new(self.parse_corpus(data)?)) | |
| } | |
| /// Retrieves the underlying `Domain`'s `CorpusValue` from the `GenericCorpusValue` and calls | |
| /// the underlying `Domain::serialize_corpus` method. | |
| /// | |
| /// If the `GenericCorpusValue` cannot be downcasted to the underlying `Domain`'s `CorpusValue` | |
| /// then an Error is returned. | |
| /// | |
| /// See `GenericDomain::serialize_corpus` for more details. | |
| fn serialize_corpus(&self, val: &GenericCorpusValue) -> anyhow::Result<Vec<u8>> { | |
| self.serialize_corpus(val.downcast_ref().context("Failed to retrieve the Corpus Value")?) | |
| } | |
| } |