libafl 0.9.0

Slot your own fuzzers together and extend their features using Rust
Documentation
//! Poor-rust-man's downcasts for stuff we send over the wire (or shared maps)

use alloc::boxed::Box;
use core::{any::Any, fmt::Debug};

use serde::{de::DeserializeSeed, Deserialize, Deserializer, Serialize, Serializer};

/// A (de)serializable Any trait
pub trait SerdeAny: Any + erased_serde::Serialize + Debug {
    /// returns this as Any trait
    fn as_any(&self) -> &dyn Any;
    /// returns this as mutable Any trait
    fn as_any_mut(&mut self) -> &mut dyn Any;
    /// returns this as boxed Any trait
    fn as_any_boxed(self: Box<Self>) -> Box<dyn Any>;
}

/// Wrap a type for serialization
#[derive(Debug)]
pub struct Wrap<'a, T: ?Sized + Debug>(pub &'a T);
impl<'a, T> Serialize for Wrap<'a, T>
where
    T: ?Sized + erased_serde::Serialize + 'a + Debug,
{
    /// Serialize the type
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        erased_serde::serialize(self.0, serializer)
    }
}

/// Callback for [`SerdeAny`] deserialization.
pub type DeserializeCallback<B> =
    fn(&mut dyn erased_serde::Deserializer) -> Result<Box<B>, erased_serde::Error>;

/// Callback struct for deserialization of a [`SerdeAny`] type.
#[allow(missing_debug_implementations)]
pub struct DeserializeCallbackSeed<B>
where
    B: ?Sized,
{
    /// Callback for deserialization of a [`SerdeAny`] type.
    pub cb: DeserializeCallback<B>,
}

impl<'de, B> DeserializeSeed<'de> for DeserializeCallbackSeed<B>
where
    B: ?Sized,
{
    type Value = Box<B>;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        let mut erased = <dyn erased_serde::Deserializer>::erase(deserializer);
        (self.cb)(&mut erased).map_err(serde::de::Error::custom)
    }
}

/// Creates the [`serde`] registry for serialization and deserialization of [`SerdeAny`].
/// Each element needs to be registered so that it can be deserialized.
#[macro_export]
macro_rules! create_serde_registry_for_trait {
    ($mod_name:ident, $trait_name:path) => {
        /// A [`crate::bolts::serdeany`] module.
        pub mod $mod_name {

            use alloc::boxed::Box;
            use core::{any::TypeId, fmt};

            use hashbrown::{
                hash_map::{Keys, Values, ValuesMut},
                HashMap,
            };
            use postcard;
            use serde::{Deserialize, Serialize};
            use $crate::{
                bolts::{
                    anymap::{pack_type_id, unpack_type_id},
                    serdeany::{DeserializeCallback, DeserializeCallbackSeed},
                },
                Error,
            };

            /// Visitor object used internally for the [`SerdeAny`] registry.
            #[derive(Debug)]
            pub struct BoxDynVisitor {}
            #[allow(unused_qualifications)]
            impl<'de> serde::de::Visitor<'de> for BoxDynVisitor {
                type Value = Box<dyn $trait_name>;

                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                    formatter.write_str("Expecting a serialized trait object")
                }

                fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
                where
                    V: serde::de::SeqAccess<'de>,
                {
                    let id: u64 = visitor.next_element()?.unwrap();
                    let cb = unsafe {
                        *REGISTRY
                            .deserializers
                            .as_ref()
                            .expect("Empty types registry")
                            .get(&id)
                            .expect("Cannot deserialize an unregistered type")
                    };
                    let seed = DeserializeCallbackSeed::<dyn $trait_name> { cb };
                    let obj: Self::Value = visitor.next_element_seed(seed)?.unwrap();
                    Ok(obj)
                }
            }

            #[allow(unused_qualifications)]
            struct Registry {
                deserializers: Option<HashMap<u64, DeserializeCallback<dyn $trait_name>>>,
                finalized: bool,
            }

            #[allow(unused_qualifications)]
            impl Registry {
                pub fn register<T>(&mut self)
                where
                    T: $trait_name + Serialize + serde::de::DeserializeOwned,
                {
                    assert!(!self.finalized, "Registry is already finalized!");

                    let deserializers = self.deserializers.get_or_insert_with(HashMap::default);
                    deserializers.insert(unpack_type_id(TypeId::of::<T>()), |de| {
                        Ok(Box::new(erased_serde::deserialize::<T>(de)?))
                    });
                }

                pub fn finalize(&mut self) {
                    self.finalized = true;
                }
            }

            static mut REGISTRY: Registry = Registry {
                deserializers: None,
                finalized: false,
            };

            /// This shugar must be used to register all the structs which
            /// have trait objects that can be serialized and deserialized in the program
            #[derive(Debug)]
            pub struct RegistryBuilder {}

            #[allow(unused_qualifications)]
            impl RegistryBuilder {
                /// Register a given struct type for trait object (de)serialization
                pub fn register<T>()
                where
                    T: $trait_name + Serialize + serde::de::DeserializeOwned,
                {
                    unsafe {
                        REGISTRY.register::<T>();
                    }
                }

                /// Finalize the registry, no more registrations are allowed after this call
                pub fn finalize() {
                    unsafe {
                        REGISTRY.finalize();
                    }
                }
            }

            /// A (de)serializable anymap containing (de)serializable trait objects registered
            /// in the registry
            #[derive(Debug, Serialize, Deserialize)]
            pub struct SerdeAnyMap {
                map: HashMap<u64, Box<dyn $trait_name>>,
            }

            // Cloning by serializing and deserializing. It ain't fast, but it's honest work.
            // We unwrap postcard, it should not have a reason to fail.
            impl Clone for SerdeAnyMap {
                fn clone(&self) -> Self {
                    let serialized = postcard::to_allocvec(&self).unwrap();
                    postcard::from_bytes(&serialized).unwrap()
                }
            }

            /*
            #[cfg(feature = "anymap_debug")]
            impl fmt::Debug for SerdeAnyMap {
                fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                    let json = serde_json::to_string(&self);
                    write!(f, "SerdeAnyMap: [{:?}]", json)
                }
            }

            #[cfg(not(feature = "anymap_debug"))]
            impl fmt::Debug for SerdeAnyMap {
                fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                    write!(f, "SerdeAnymap with {} elements", self.len())
                }
            }*/

            #[allow(unused_qualifications)]
            impl SerdeAnyMap {
                /// Get an element from the map.
                #[must_use]
                #[inline]
                pub fn get<T>(&self) -> Option<&T>
                where
                    T: $trait_name,
                {
                    self.map
                        .get(&unpack_type_id(TypeId::of::<T>()))
                        .map(|x| x.as_ref().as_any().downcast_ref::<T>().unwrap())
                }

                /// Get a mutable borrow for an element in the map.
                #[must_use]
                #[inline]
                pub fn get_mut<T>(&mut self) -> Option<&mut T>
                where
                    T: $trait_name,
                {
                    self.map
                        .get_mut(&unpack_type_id(TypeId::of::<T>()))
                        .map(|x| x.as_mut().as_any_mut().downcast_mut::<T>().unwrap())
                }

                /// Remove an element in the map. Returns the removed element.
                #[must_use]
                #[inline]
                pub fn remove<T>(&mut self) -> Option<Box<T>>
                where
                    T: $trait_name,
                {
                    self.map
                        .remove(&unpack_type_id(TypeId::of::<T>()))
                        .map(|x| x.as_any_boxed().downcast::<T>().unwrap())
                }

                /// Insert an element into the map.
                #[inline]
                pub fn insert<T>(&mut self, t: T)
                where
                    T: $trait_name,
                {
                    self.map
                        .insert(unpack_type_id(TypeId::of::<T>()), Box::new(t));
                }

                /// Insert a boxed element into the map.
                #[inline]
                pub fn insert_boxed<T>(&mut self, t: Box<T>)
                where
                    T: $trait_name,
                {
                    self.map.insert(unpack_type_id(TypeId::of::<T>()), t);
                }

                /// Returns the count of elements in this map.
                #[must_use]
                #[inline]
                pub fn len(&self) -> usize {
                    self.map.len()
                }

                /// Returns `true` if this map is empty.
                #[must_use]
                pub fn is_empty(&self) -> bool {
                    self.map.is_empty()
                }

                /// Returns if the map contains the given type.
                #[must_use]
                #[inline]
                pub fn contains<T>(&self) -> bool
                where
                    T: $trait_name,
                {
                    self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
                }

                /// Create a new [`SerdeAnyMap`].
                #[must_use]
                pub fn new() -> Self {
                    SerdeAnyMap {
                        map: HashMap::default(),
                    }
                }
            }

            impl Default for SerdeAnyMap {
                fn default() -> Self {
                    Self::new()
                }
            }

            /// A serializable [`HashMap`] wrapper for [`SerdeAny`] types, addressable by name.
            #[allow(unused_qualifications)]
            #[derive(Debug, Serialize, Deserialize)]
            pub struct NamedSerdeAnyMap {
                map: HashMap<u64, HashMap<u64, Box<dyn $trait_name>>>,
            }

            // Cloning by serializing and deserializing. It ain't fast, but it's honest work.
            // We unwrap postcard, it should not have a reason to fail.
            impl Clone for NamedSerdeAnyMap {
                fn clone(&self) -> Self {
                    let serialized = postcard::to_allocvec(&self).unwrap();
                    postcard::from_bytes(&serialized).unwrap()
                }
            }

            #[allow(unused_qualifications)]
            impl NamedSerdeAnyMap {
                /// Get an element by name
                #[must_use]
                #[inline]
                pub fn get<T>(&self, name: &str) -> Option<&T>
                where
                    T: $trait_name,
                {
                    match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
                        None => None,
                        Some(h) => h
                            .get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
                            .map(|x| x.as_any().downcast_ref::<T>().unwrap()),
                    }
                }

                /// Get an element of a given type contained in this map by [`TypeId`].
                #[must_use]
                #[allow(unused_qualifications)]
                #[inline]
                pub fn by_typeid(&self, name: &str, typeid: &TypeId) -> Option<&dyn $trait_name> {
                    match self.map.get(&unpack_type_id(*typeid)) {
                        None => None,
                        Some(h) => h
                            .get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
                            .map(AsRef::as_ref),
                    }
                }

                /// Get an element of a given type contained in this map by [`TypeId`], as mut.
                #[must_use]
                #[inline]
                pub fn get_mut<T>(&mut self, name: &str) -> Option<&mut T>
                where
                    T: $trait_name,
                {
                    match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
                        None => None,
                        Some(h) => h
                            .get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
                            .map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
                    }
                }

                /// Get an element of a given type contained in this map by [`TypeId`], as mut.
                #[must_use]
                #[inline]
                pub fn by_typeid_mut(
                    &mut self,
                    name: &str,
                    typeid: &TypeId,
                ) -> Option<&mut dyn $trait_name> {
                    match self.map.get_mut(&unpack_type_id(*typeid)) {
                        None => None,
                        Some(h) => h
                            .get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
                            .map(AsMut::as_mut),
                    }
                }

                /// Get all elements of a type contained in this map.
                #[must_use]
                #[allow(unused_qualifications)]
                #[inline]
                pub fn get_all<T>(
                    &self,
                ) -> Option<
                    core::iter::Map<
                        Values<'_, u64, Box<dyn $trait_name>>,
                        fn(&Box<dyn $trait_name>) -> &T,
                    >,
                >
                where
                    T: $trait_name,
                {
                    #[allow(clippy::manual_map)]
                    match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
                        None => None,
                        Some(h) => {
                            Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap()))
                        }
                    }
                }

                /// Get all elements of a given type contained in this map by [`TypeId`].
                #[must_use]
                #[allow(unused_qualifications)]
                #[inline]
                pub fn all_by_typeid(
                    &self,
                    typeid: &TypeId,
                ) -> Option<
                    core::iter::Map<
                        Values<'_, u64, Box<dyn $trait_name>>,
                        fn(&Box<dyn $trait_name>) -> &dyn $trait_name,
                    >,
                > {
                    #[allow(clippy::manual_map)]
                    match self.map.get(&unpack_type_id(*typeid)) {
                        None => None,
                        Some(h) => Some(h.values().map(|x| x.as_ref())),
                    }
                }

                /// Get all elements contained in this map, as mut.
                #[inline]
                #[allow(unused_qualifications)]
                pub fn get_all_mut<T>(
                    &mut self,
                ) -> Option<
                    core::iter::Map<
                        ValuesMut<'_, u64, Box<dyn $trait_name>>,
                        fn(&mut Box<dyn $trait_name>) -> &mut T,
                    >,
                >
                where
                    T: $trait_name,
                {
                    #[allow(clippy::manual_map)]
                    match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
                        None => None,
                        Some(h) => Some(
                            h.values_mut()
                                .map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
                        ),
                    }
                }

                /// Get all [`TypeId`]`s` contained in this map, as mut.
                #[inline]
                #[allow(unused_qualifications)]
                pub fn all_by_typeid_mut(
                    &mut self,
                    typeid: &TypeId,
                ) -> Option<
                    core::iter::Map<
                        ValuesMut<'_, u64, Box<dyn $trait_name>>,
                        fn(&mut Box<dyn $trait_name>) -> &mut dyn $trait_name,
                    >,
                > {
                    #[allow(clippy::manual_map)]
                    match self.map.get_mut(&unpack_type_id(*typeid)) {
                        None => None,
                        Some(h) => Some(h.values_mut().map(|x| x.as_mut())),
                    }
                }

                /// Get all [`TypeId`]`s` contained in this map.
                #[inline]
                #[allow(unused_qualifications)]
                pub fn all_typeids(
                    &self,
                ) -> core::iter::Map<
                    Keys<'_, u64, HashMap<u64, Box<dyn $trait_name>>>,
                    fn(&u64) -> TypeId,
                > {
                    self.map.keys().map(|x| pack_type_id(*x))
                }

                /// Run `func` for each element in this map.
                #[inline]
                #[allow(unused_qualifications)]
                pub fn for_each<F: FnMut(&TypeId, &Box<dyn $trait_name>) -> Result<(), Error>>(
                    &self,
                    func: &mut F,
                ) -> Result<(), Error> {
                    for (id, h) in self.map.iter() {
                        for x in h.values() {
                            func(&pack_type_id(*id), x)?;
                        }
                    }
                    Ok(())
                }

                /// Run `func` for each element in this map, getting a mutable borrow.
                #[inline]
                pub fn for_each_mut<
                    F: FnMut(&TypeId, &mut Box<dyn $trait_name>) -> Result<(), Error>,
                >(
                    &mut self,
                    func: &mut F,
                ) -> Result<(), Error> {
                    for (id, h) in self.map.iter_mut() {
                        for x in h.values_mut() {
                            func(&pack_type_id(*id), x)?;
                        }
                    }
                    Ok(())
                }

                /// Insert an element into this map.
                #[inline]
                #[allow(unused_qualifications)]
                pub fn insert<T>(&mut self, val: T, name: &str)
                where
                    T: $trait_name,
                {
                    let id = unpack_type_id(TypeId::of::<T>());
                    if !self.map.contains_key(&id) {
                        self.map.insert(id, HashMap::default());
                    }
                    self.map
                        .get_mut(&id)
                        .unwrap()
                        .insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), Box::new(val));
                }

                /// Returns the `len` of this map.
                #[must_use]
                #[inline]
                pub fn len(&self) -> usize {
                    self.map.len()
                }

                /// Returns `true` if this map is empty.
                #[must_use]
                pub fn is_empty(&self) -> bool {
                    self.map.is_empty()
                }

                /// Returns if the element with a given type is contained in this map.
                #[must_use]
                #[inline]
                pub fn contains_type<T>(&self) -> bool
                where
                    T: $trait_name,
                {
                    self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
                }

                /// Returns if the element by a given `name` is contained in this map.
                #[must_use]
                #[inline]
                pub fn contains<T>(&self, name: &str) -> bool
                where
                    T: $trait_name,
                {
                    match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
                        None => false,
                        Some(h) => h.contains_key(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())),
                    }
                }

                /// Create a new `SerdeAny` map.
                #[must_use]
                pub fn new() -> Self {
                    Self {
                        map: HashMap::default(),
                    }
                }
            }

            impl Default for NamedSerdeAnyMap {
                fn default() -> Self {
                    Self::new()
                }
            }
        }

        #[allow(unused_qualifications)]
        impl Serialize for dyn $trait_name {
            fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
            where
                S: Serializer,
            {
                use serde::ser::SerializeSeq;

                let id = $crate::bolts::anymap::unpack_type_id(self.type_id());
                let mut seq = se.serialize_seq(Some(2))?;
                seq.serialize_element(&id)?;
                seq.serialize_element(&$crate::bolts::serdeany::Wrap(self))?;
                seq.end()
            }
        }

        #[allow(unused_qualifications)]
        impl<'de> Deserialize<'de> for Box<dyn $trait_name> {
            fn deserialize<D>(deserializer: D) -> Result<Box<dyn $trait_name>, D::Error>
            where
                D: Deserializer<'de>,
            {
                deserializer.deserialize_seq($mod_name::BoxDynVisitor {})
            }
        }
    };
}

create_serde_registry_for_trait!(serdeany_registry, crate::bolts::serdeany::SerdeAny);
pub use serdeany_registry::*;

/// Register a `SerdeAny` type in the [`RegistryBuilder`]
#[cfg(feature = "std")]
#[macro_export]
macro_rules! register_at_startup {
    ($struct_type:ty) => {
        const _: () = {
            #[$crate::ctor]
            fn constructor() {
                $crate::bolts::serdeany::RegistryBuilder::register::<$struct_type>();
            }
        };
    };
}

/// Do nothing for `no_std`, you have to register it manually in `main()` with [`RegistryBuilder::register`]
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! register_at_startup {
    ($struct_type:ty) => {};
}

/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`] when on std
#[macro_export]
macro_rules! impl_serdeany {
    ($struct_name:ident < $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ > $(, < $( $opt:tt ),+ >)*) =>
    {
        impl < $( $lt $( : $clt $(+ $dlt )* )? ),+ >
            $crate::bolts::serdeany::SerdeAny
            for $struct_name < $( $lt ),+ >
        {
            fn as_any(&self) -> &dyn ::core::any::Any {
                self
            }

            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
                self
            }

            fn as_any_boxed(
                self: $crate::alloc::boxed::Box<$struct_name < $( $lt ),+ >>,
            ) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
                self
            }
        }

        $(
            $crate::register_at_startup!($struct_name < $( $opt ),+ >);
        )*
    };
    ($struct_name:ident) =>
    {
        impl
            $crate::bolts::serdeany::SerdeAny
            for $struct_name
        {
            fn as_any(&self) -> &dyn ::core::any::Any {
                self
            }

            fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
                self
            }

            fn as_any_boxed(
                self: $crate::alloc::boxed::Box<$struct_name>,
            ) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
                self
            }
        }

        $crate::register_at_startup!($struct_name);
    };
}