Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ serde = { version = "1.0.228", default-features = false } # serialization lib
serde_json = { version = "1.0.149", default-features = false }
serde_yaml = { version = "0.9.34" } # For parsing the injections yaml file
serial_test = { version = "3.2.0", default-features = false }
spin = "0.11.0"
static_assertions = "1.1.0"
strum = "0.28.0"
strum_macros = "0.28.0"
Expand Down
1 change: 1 addition & 0 deletions crates/serde_anymap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ libafl_core = { workspace = true }
postcard = { workspace = true }
serde = { workspace = true, features = ["derive"] }
static_assertions = { workspace = true }
spin = { workspace = true, features = ["mutex"] }

[lints]
workspace = true
98 changes: 35 additions & 63 deletions crates/serde_anymap/src/serdeany.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,19 @@ where
/// Creates the [`serde`] registry for serialization and deserialization of [`SerdeAny`].
/// Each element needs to be registered so that it can be deserialized.
pub mod serdeany_registry {

use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::{any::TypeId, fmt};
use core::{any::TypeId, cell::RefCell, fmt};

use hashbrown::{
DefaultHashBuilder, HashMap,
hash_map::{Values, ValuesMut},
};
use libafl_core::{Error, format};
use serde::{Deserialize, Serialize, de};
use spin::Mutex;

use crate::serdeany::{
DeserializeCallback, DeserializeCallbackSeed, SerdeAny, TypeRepr, type_repr,
Expand Down Expand Up @@ -153,17 +153,16 @@ pub mod serdeany_registry {
{
let id: TypeRepr = visitor.next_element()?.unwrap();

let registry = &raw const REGISTRY;
let cb = unsafe {
(*registry)
let cb = REGISTRY
.lock()
.borrow()
.deserializers
.as_ref()
.ok_or_else(||
de::Error::custom(super::ERR_EMPTY_TYPES_REGISTER))?
.get(&id)
.ok_or_else(|| de::Error::custom(format_args!("Cannot deserialize the unregistered type with id {id}. Enable the `serde_autoreg` feature in libafl_bolts or register all requried types manually.")))?
.0
};
.0;
let seed = DeserializeCallbackSeed::<dyn crate::serdeany::SerdeAny> { cb };
let obj: Self::Value = visitor.next_element_seed(seed)?.unwrap();
Ok(obj)
Expand Down Expand Up @@ -208,10 +207,10 @@ pub mod serdeany_registry {
}
}

static mut REGISTRY: Registry = Registry {
static REGISTRY: Mutex<RefCell<Registry>> = Mutex::new(RefCell::new(Registry {
deserializers: None,
finalized: false,
};
}));

/// This sugar must be used to register all the structs which
/// have trait objects that can be serialized and deserialized in the program
Expand All @@ -221,30 +220,16 @@ pub mod serdeany_registry {
#[expect(unused_qualifications)]
impl RegistryBuilder {
/// Register a given struct type for trait object (de)serialization
///
/// # Safety
/// This may never be called concurrently or at the same time as `finalize`.
/// It dereferences the `REGISTRY` hashmap and adds the given type to it.
pub unsafe fn register<T>()
pub fn register<T>()
where
T: crate::serdeany::SerdeAny + Serialize + serde::de::DeserializeOwned,
{
let registry = &raw mut REGISTRY;
unsafe {
(*registry).register::<T>();
}
REGISTRY.lock().borrow_mut().register::<T>();
}

/// Finalize the registry, no more registrations are allowed after this call
///
/// # Safety
/// This may never be called concurrently or at the same time as `register`.
/// It dereferences the `REGISTRY` hashmap and adds the given type to it.
pub unsafe fn finalize() {
let registry = &raw mut REGISTRY;
unsafe {
(*registry).finalize();
}
pub fn finalize() {
REGISTRY.lock().borrow_mut().finalize();
}
}

Expand Down Expand Up @@ -380,16 +365,15 @@ pub mod serdeany_registry {
#[cfg(not(feature = "stable_anymap"))]
let type_repr = &type_repr;

let registry = &raw const REGISTRY;
assert!(
unsafe {
(*registry)
.deserializers
.as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER)
.get(type_repr)
.is_some()
},
REGISTRY
.lock()
.borrow()
.deserializers
.as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER)
.get(type_repr)
.is_some(),
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.",
core::any::type_name::<T>(),
core::any::type_name::<T>()
Expand Down Expand Up @@ -667,16 +651,15 @@ pub mod serdeany_registry {
let type_repr = type_repr::<T>();
#[cfg(not(feature = "stable_anymap"))]
let type_repr = &type_repr;
let registry = &raw const REGISTRY;
assert!(
unsafe {
(*registry)
.deserializers
.as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER)
.get(type_repr)
.is_some()
},
REGISTRY
.lock()
.borrow()
.deserializers
.as_ref()
.expect(super::ERR_EMPTY_TYPES_REGISTER)
.get(type_repr)
.is_some(),
"Type {} was inserted without registration! Call RegistryBuilder::register::<{}>() or use serdeany_autoreg.",
core::any::type_name::<T>(),
core::any::type_name::<T>()
Expand Down Expand Up @@ -852,12 +835,8 @@ macro_rules! create_register {
$crate::ctor::declarative::ctor! {
/// Automatically register this type
#[ctor(anonymous)]
unsafe fn register() {
// # Safety
// This `register` call will always run at startup and never in parallel.
unsafe {
$crate::serdeany::RegistryBuilder::register::<$struct_type>();
}
fn register() {
$crate::serdeany::RegistryBuilder::register::<$struct_type>();
}
}
};
Expand Down Expand Up @@ -889,9 +868,7 @@ macro_rules! create_manual_register {
#[macro_export]
macro_rules! create_manual_register {
($struct_type:ty) => {
unsafe {
$crate::serdeany::RegistryBuilder::register::<$struct_type>();
}
$crate::serdeany::RegistryBuilder::register::<$struct_type>();
};
}

Expand Down Expand Up @@ -926,10 +903,7 @@ macro_rules! impl_serdeany {
impl< $( $lt $( : $clt $(+ $dlt )* )? ),+ > $struct_name < $( $lt ),+ > {

/// Manually register this type at a later point in time
///
/// # Safety
/// This may never be called concurrently as it dereferences the `RegistryBuilder` without acquiring a lock.
pub unsafe fn register() {
pub fn register() {
$(
$crate::create_manual_register!($struct_name < $( $opt ),+ >);
)*
Expand Down Expand Up @@ -971,7 +945,7 @@ macro_rules! impl_serdeany {
/// # Safety
/// This may never be called concurrently as it dereferences the `RegistryBuilder` without acquiring a lock.
#[expect(unused)]
pub unsafe fn register() {
pub fn register() {
$crate::create_manual_register!($struct_name);
}
}
Expand Down Expand Up @@ -1000,10 +974,8 @@ mod tests {

#[test]
fn test_deserialize_serialize() {
unsafe {
RegistryBuilder::register::<MyType>();
RegistryBuilder::register::<inner::MyType>();
}
RegistryBuilder::register::<MyType>();
RegistryBuilder::register::<inner::MyType>();

let val = MyType(1);
let serialized = postcard::to_allocvec(&val).unwrap();
Expand Down
Loading