bolts: Make xxh3 hashing optional with xxh3
feature flag (else use ahash
for everything) (#1478)
* Make xxh3 hashing optional (and default to ahash) * make xxh3 default anyway * move import * fix no_alloc * No ahash without alloc * fix import * Keep xxh3 as default for libafl as well * no randomness for xoshiro
This commit is contained in:
parent
ab837cbbf5
commit
61ad4a6ee8
@ -16,7 +16,7 @@ features = ["document-features"]
|
|||||||
all-features = true
|
all-features = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "llmp_broker_timeouts", "rand_trait", "fork", "prelude", "gzip", "regex", "serdeany_autoreg", "tui_monitor"]
|
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "llmp_broker_timeouts", "rand_trait", "fork", "prelude", "gzip", "regex", "serdeany_autoreg", "tui_monitor", "libafl_bolts/xxh3"]
|
||||||
document-features = ["dep:document-features"]
|
document-features = ["dep:document-features"]
|
||||||
|
|
||||||
#! # Feature Flags
|
#! # Feature Flags
|
||||||
|
@ -17,7 +17,7 @@ features = ["document-features"]
|
|||||||
all-features = true
|
all-features = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "rand_trait", "prelude", "gzip", "serdeany_autoreg", "alloc"]
|
default = ["std", "derive", "llmp_compression", "llmp_small_maps", "rand_trait", "prelude", "gzip", "serdeany_autoreg", "alloc", "xxh3"]
|
||||||
document-features = ["dep:document-features"]
|
document-features = ["dep:document-features"]
|
||||||
|
|
||||||
#! # Feature Flags
|
#! # Feature Flags
|
||||||
@ -56,6 +56,11 @@ errors_backtrace = ["backtrace"]
|
|||||||
## Enables gzip compression in certain parts of the lib
|
## Enables gzip compression in certain parts of the lib
|
||||||
gzip = ["miniz_oxide", "alloc"]
|
gzip = ["miniz_oxide", "alloc"]
|
||||||
|
|
||||||
|
## Replaces `ahash` with the potentially faster [`xxh3`](https://github.com/Cyan4973/xxHash) in some parts of the lib.
|
||||||
|
## This yields a stable and fast hash, but may increase the resulting binary size slightly
|
||||||
|
## This also enables certain hashing and rand features in `no_std` no-alloc.
|
||||||
|
xxh3 = ["xxhash-rust"]
|
||||||
|
|
||||||
#! ### SerdeAny features
|
#! ### SerdeAny features
|
||||||
|
|
||||||
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
## Automatically register all `#[derive(SerdeAny)]` types at startup.
|
||||||
@ -89,7 +94,7 @@ libafl_derive = { version = "0.11.0", optional = true, path = "../libafl_derive"
|
|||||||
rustversion = "1.0"
|
rustversion = "1.0"
|
||||||
tuple_list = { version = "0.1.3" }
|
tuple_list = { version = "0.1.3" }
|
||||||
hashbrown = { version = "0.14", features = ["serde", "ahash"], default-features=false, optional = true } # A faster hashmap, nostd compatible
|
hashbrown = { version = "0.14", features = ["serde", "ahash"], default-features=false, optional = true } # A faster hashmap, nostd compatible
|
||||||
xxhash-rust = { version = "0.8.5", features = ["xxh3"] } # xxh3 hashing for rust
|
xxhash-rust = { version = "0.8.5", features = ["xxh3"], optional = true } # xxh3 hashing for rust
|
||||||
serde = { version = "1.0", default-features = false, features = ["derive"] } # serialization lib
|
serde = { version = "1.0", default-features = false, features = ["derive"] } # serialization lib
|
||||||
erased-serde = { version = "0.3.21", default-features = false, optional = true } # erased serde
|
erased-serde = { version = "0.3.21", default-features = false, optional = true } # erased serde
|
||||||
postcard = { version = "1.0", features = ["alloc"], default-features = false, optional = true } # no_std compatible serde serialization format
|
postcard = { version = "1.0", features = ["alloc"], default-features = false, optional = true } # no_std compatible serde serialization format
|
||||||
|
@ -12,6 +12,8 @@ use std::{
|
|||||||
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::hasher_std;
|
||||||
|
|
||||||
static BUILD_ID: OnceLock<Uuid> = OnceLock::new();
|
static BUILD_ID: OnceLock<Uuid> = OnceLock::new();
|
||||||
|
|
||||||
/// Returns a [Uuid] uniquely representing the build of the current binary.
|
/// Returns a [Uuid] uniquely representing the build of the current binary.
|
||||||
@ -81,7 +83,7 @@ fn from_type_id<H: Hasher>(mut hasher: H) -> H {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn calculate() -> Uuid {
|
fn calculate() -> Uuid {
|
||||||
let hasher = xxhash_rust::xxh3::Xxh3::with_seed(0);
|
let hasher = hasher_std();
|
||||||
|
|
||||||
let hasher = from_exe(hasher.clone()).unwrap_or(hasher);
|
let hasher = from_exe(hasher.clone()).unwrap_or(hasher);
|
||||||
let mut hasher = from_type_id(hasher);
|
let mut hasher = from_type_id(hasher);
|
||||||
|
@ -130,15 +130,27 @@ pub mod serdeany;
|
|||||||
pub mod shmem;
|
pub mod shmem;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod staterestore;
|
pub mod staterestore;
|
||||||
|
// TODO: reenable once ahash works in no-alloc
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
pub mod tuples;
|
pub mod tuples;
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
#[cfg(all(not(feature = "xxh3"), feature = "alloc"))]
|
||||||
|
use core::hash::BuildHasher;
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
|
use core::hash::Hasher;
|
||||||
use core::{iter::Iterator, time};
|
use core::{iter::Iterator, time};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
// There's a bug in ahash that doesn't let it build in `alloc` without once_cell right now.
|
||||||
|
// TODO: re-enable once <https://github.com/tkaitchuck/aHash/issues/155> is resolved.
|
||||||
|
#[cfg(all(not(feature = "xxh3"), feature = "alloc"))]
|
||||||
|
use ahash::RandomState;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
#[cfg(feature = "xxh3")]
|
||||||
|
use xxhash_rust::xxh3::xxh3_64;
|
||||||
|
|
||||||
/// The client ID == the sender id.
|
/// The client ID == the sender id.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
@ -209,6 +221,34 @@ fn display_error_backtrace(_f: &mut fmt::Formatter, _err: &ErrorBacktrace) -> fm
|
|||||||
fmt::Result::Ok(())
|
fmt::Result::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the hasher for the input with a given hash, depending on features:
|
||||||
|
/// [`xxh3_64`](https://docs.rs/xxhash-rust/latest/xxhash_rust/xxh3/fn.xxh3_64.html)
|
||||||
|
/// if the `xxh3` feature is used, /// else [`ahash`](https://docs.rs/ahash/latest/ahash/).
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
|
#[must_use]
|
||||||
|
pub fn hasher_std() -> impl Hasher + Clone {
|
||||||
|
#[cfg(feature = "xxh3")]
|
||||||
|
return xxhash_rust::xxh3::Xxh3::new();
|
||||||
|
#[cfg(not(feature = "xxh3"))]
|
||||||
|
RandomState::with_seeds(0, 0, 0, 0).build_hasher()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hashes the input with a given hash, depending on features:
|
||||||
|
/// [`xxh3_64`](https://docs.rs/xxhash-rust/latest/xxhash_rust/xxh3/fn.xxh3_64.html)
|
||||||
|
/// if the `xxh3` feature is used, /// else [`ahash`](https://docs.rs/ahash/latest/ahash/).
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
|
#[must_use]
|
||||||
|
pub fn hash_std(input: &[u8]) -> u64 {
|
||||||
|
#[cfg(feature = "xxh3")]
|
||||||
|
return xxh3_64(input);
|
||||||
|
#[cfg(not(feature = "xxh3"))]
|
||||||
|
{
|
||||||
|
let mut hasher = hasher_std();
|
||||||
|
hasher.write(input);
|
||||||
|
hasher.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Main error struct for `LibAFL`
|
/// Main error struct for `LibAFL`
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -4,12 +4,11 @@ use core::{debug_assert, fmt::Debug};
|
|||||||
#[cfg(feature = "rand_trait")]
|
#[cfg(feature = "rand_trait")]
|
||||||
use rand_core::{self, impls::fill_bytes_via_next, RngCore};
|
use rand_core::{self, impls::fill_bytes_via_next, RngCore};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
use xxhash_rust::xxh3::xxh3_64_with_seed;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::current_nanos;
|
use crate::current_nanos;
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
const HASH_CONST: u64 = 0xa5b35705;
|
use crate::hash_std;
|
||||||
|
|
||||||
/// The standard rand implementation for `LibAFL`.
|
/// The standard rand implementation for `LibAFL`.
|
||||||
/// It is usually the right choice, with very good speed and a reasonable randomness.
|
/// It is usually the right choice, with very good speed and a reasonable randomness.
|
||||||
@ -98,6 +97,7 @@ macro_rules! default_rand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Derive Default by calling `new(DEFAULT_SEED)` on each of the following Rand types.
|
// Derive Default by calling `new(DEFAULT_SEED)` on each of the following Rand types.
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
default_rand!(Xoshiro256StarRand);
|
default_rand!(Xoshiro256StarRand);
|
||||||
default_rand!(XorShift64Rand);
|
default_rand!(XorShift64Rand);
|
||||||
default_rand!(Lehmer64Rand);
|
default_rand!(Lehmer64Rand);
|
||||||
@ -145,6 +145,7 @@ macro_rules! impl_random {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
impl_random!(Xoshiro256StarRand);
|
impl_random!(Xoshiro256StarRand);
|
||||||
impl_random!(XorShift64Rand);
|
impl_random!(XorShift64Rand);
|
||||||
impl_random!(Lehmer64Rand);
|
impl_random!(Lehmer64Rand);
|
||||||
@ -157,10 +158,12 @@ pub struct Xoshiro256StarRand {
|
|||||||
rand_seed: [u64; 4],
|
rand_seed: [u64; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: re-enable ahash works without alloc
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
impl Rand for Xoshiro256StarRand {
|
impl Rand for Xoshiro256StarRand {
|
||||||
#[allow(clippy::unreadable_literal)]
|
#[allow(clippy::unreadable_literal)]
|
||||||
fn set_seed(&mut self, seed: u64) {
|
fn set_seed(&mut self, seed: u64) {
|
||||||
self.rand_seed[0] = xxh3_64_with_seed(&HASH_CONST.to_le_bytes(), seed);
|
self.rand_seed[0] = hash_std(&seed.to_be_bytes());
|
||||||
self.rand_seed[1] = self.rand_seed[0] ^ 0x1234567890abcdef;
|
self.rand_seed[1] = self.rand_seed[0] ^ 0x1234567890abcdef;
|
||||||
self.rand_seed[2] = self.rand_seed[0] & 0x0123456789abcdef;
|
self.rand_seed[2] = self.rand_seed[0] & 0x0123456789abcdef;
|
||||||
self.rand_seed[3] = self.rand_seed[0] | 0x01abcde43f567908;
|
self.rand_seed[3] = self.rand_seed[0] | 0x01abcde43f567908;
|
||||||
@ -187,6 +190,7 @@ impl Rand for Xoshiro256StarRand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
impl Xoshiro256StarRand {
|
impl Xoshiro256StarRand {
|
||||||
/// Creates a new Xoshiro rand with the given seed
|
/// Creates a new Xoshiro rand with the given seed
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -376,9 +380,9 @@ impl XkcdRand {
|
|||||||
mod tests {
|
mod tests {
|
||||||
//use xxhash_rust::xxh3::xxh3_64_with_seed;
|
//use xxhash_rust::xxh3::xxh3_64_with_seed;
|
||||||
|
|
||||||
use crate::rands::{
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
Rand, RomuDuoJrRand, RomuTrioRand, StdRand, XorShift64Rand, Xoshiro256StarRand,
|
use crate::rands::Xoshiro256StarRand;
|
||||||
};
|
use crate::rands::{Rand, RomuDuoJrRand, RomuTrioRand, StdRand, XorShift64Rand};
|
||||||
|
|
||||||
fn test_single_rand<R: Rand>(rand: &mut R) {
|
fn test_single_rand<R: Rand>(rand: &mut R) {
|
||||||
assert_ne!(rand.next(), rand.next());
|
assert_ne!(rand.next(), rand.next());
|
||||||
@ -395,6 +399,7 @@ mod tests {
|
|||||||
test_single_rand(&mut RomuTrioRand::with_seed(0));
|
test_single_rand(&mut RomuTrioRand::with_seed(0));
|
||||||
test_single_rand(&mut RomuDuoJrRand::with_seed(0));
|
test_single_rand(&mut RomuDuoJrRand::with_seed(0));
|
||||||
test_single_rand(&mut XorShift64Rand::with_seed(0));
|
test_single_rand(&mut XorShift64Rand::with_seed(0));
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
test_single_rand(&mut Xoshiro256StarRand::with_seed(0));
|
test_single_rand(&mut Xoshiro256StarRand::with_seed(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use $crate::{
|
use $crate::{
|
||||||
anymap::{pack_type_id, unpack_type_id},
|
anymap::{pack_type_id, unpack_type_id},
|
||||||
|
hash_std,
|
||||||
serdeany::{DeserializeCallback, DeserializeCallbackSeed},
|
serdeany::{DeserializeCallback, DeserializeCallbackSeed},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -346,7 +347,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
.get(&hash_std(name.as_bytes()))
|
||||||
.map(|x| x.as_any().downcast_ref::<T>().unwrap()),
|
.map(|x| x.as_any().downcast_ref::<T>().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +360,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
match self.map.get(&unpack_type_id(*typeid)) {
|
match self.map.get(&unpack_type_id(*typeid)) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
.get(&hash_std(name.as_bytes()))
|
||||||
.map(AsRef::as_ref),
|
.map(AsRef::as_ref),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,7 +375,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
.get_mut(&hash_std(name.as_bytes()))
|
||||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -390,7 +391,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
||||||
None => None,
|
None => None,
|
||||||
Some(h) => h
|
Some(h) => h
|
||||||
.get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
.get_mut(&hash_std(name.as_bytes()))
|
||||||
.map(AsMut::as_mut),
|
.map(AsMut::as_mut),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -552,7 +553,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
self.map
|
self.map
|
||||||
.get_mut(&id)
|
.get_mut(&id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), Box::new(val));
|
.insert(hash_std(name.as_bytes()), Box::new(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the `len` of this map.
|
/// Returns the `len` of this map.
|
||||||
@ -587,7 +588,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
{
|
{
|
||||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(h) => h.contains_key(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())),
|
Some(h) => h.contains_key(&hash_std(name.as_bytes())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,9 @@ use core::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
|
pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
|
||||||
use xxhash_rust::xxh3::xxh3_64;
|
|
||||||
|
|
||||||
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
|
use crate::hash_std;
|
||||||
use crate::Named;
|
use crate::Named;
|
||||||
|
|
||||||
/// Returns if the type `T` is equal to `U`
|
/// Returns if the type `T` is equal to `U`
|
||||||
@ -87,7 +88,7 @@ pub trait HasNameId {
|
|||||||
|
|
||||||
/// Gets the `name_id` for this entry
|
/// Gets the `name_id` for this entry
|
||||||
fn name_id(&self) -> u64 {
|
fn name_id(&self) -> u64 {
|
||||||
xxh3_64(self.const_name().as_bytes())
|
hash_std(self.const_name().as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user