diff --git a/libafl/benches/hash_speeds.rs b/libafl/benches/hash_speeds.rs index 1e2b016c9f..a443dfc7e6 100644 --- a/libafl/benches/hash_speeds.rs +++ b/libafl/benches/hash_speeds.rs @@ -10,7 +10,7 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use libafl::utils::{Rand, StdRand}; fn criterion_benchmark(c: &mut Criterion) { - let mut rand = StdRand::new(0); + let mut rand = StdRand::with_seed(0); let mut bench_vec: Vec = vec![]; for _ in 0..2 << 16 { bench_vec.push(rand.below(256) as u8); diff --git a/libafl/benches/rand_speeds.rs b/libafl/benches/rand_speeds.rs index 486343d0cc..4ae294298c 100644 --- a/libafl/benches/rand_speeds.rs +++ b/libafl/benches/rand_speeds.rs @@ -6,11 +6,11 @@ use libafl::utils::{ }; fn criterion_benchmark(c: &mut Criterion) { - let mut xorshift = XorShift64Rand::new(1); - let mut xoshiro = Xoshiro256StarRand::new(1); - let mut romu = RomuDuoJrRand::new(1); - let mut lehmer = Lehmer64Rand::new(1); - let mut romu_trio = RomuTrioRand::new(1); + let mut xorshift = XorShift64Rand::with_seed(1); + let mut xoshiro = Xoshiro256StarRand::with_seed(1); + let mut romu = RomuDuoJrRand::with_seed(1); + let mut lehmer = Lehmer64Rand::with_seed(1); + let mut romu_trio = RomuTrioRand::with_seed(1); c.bench_function("xorshift", |b| b.iter(|| black_box(xorshift.next()))); c.bench_function("xoshiro", |b| b.iter(|| black_box(xoshiro.next()))); diff --git a/libafl/src/bolts/serdeany.rs b/libafl/src/bolts/serdeany.rs index c12d346e3f..1d0062b36f 100644 --- a/libafl/src/bolts/serdeany.rs +++ b/libafl/src/bolts/serdeany.rs @@ -505,11 +505,11 @@ pub use serdeany_registry::*; macro_rules! impl_serdeany { ($struct_name:ident) => { impl crate::bolts::serdeany::SerdeAny for $struct_name { - fn as_any(&self) -> &dyn Any { + fn as_any(&self) -> &dyn core::any::Any { self } - fn as_any_mut(&mut self) -> &mut dyn Any { + fn as_any_mut(&mut self) -> &mut dyn core::any::Any { self } } diff --git a/libafl/src/corpus/minset.rs b/libafl/src/corpus/minset.rs index 0afaa156a1..db9a17e102 100644 --- a/libafl/src/corpus/minset.rs +++ b/libafl/src/corpus/minset.rs @@ -1,12 +1,38 @@ -use core::marker::PhantomData; - use crate::{ + bolts::serdeany::SerdeAny, corpus::{Corpus, CorpusScheduler, Testcase}, inputs::{HasLen, Input}, - state::HasCorpus, + state::{HasCorpus, HasMetadata}, Error, }; +use core::{iter::IntoIterator, marker::PhantomData}; +use hashbrown::{HashMap, HashSet}; +use serde::{Deserialize, Serialize}; + +/// A testcase metadata saying if a testcase is favored +#[derive(Serialize, Deserialize)] +pub struct IsFavoredMetadata {} + +crate::impl_serdeany!(IsFavoredMetadata); + +/// A state metadata holding a map of favoreds testcases for each map entry +#[derive(Serialize, Deserialize)] +pub struct TopRatedsMetadata { + /// map index -> corpus index + pub map: HashMap, +} + +crate::impl_serdeany!(TopRatedsMetadata); + +impl TopRatedsMetadata { + pub fn new() -> Self { + Self { + map: HashMap::default(), + } + } +} + pub trait FavFactor where I: Input, @@ -30,24 +56,28 @@ where } } -pub struct MinimizerCorpusScheduler +pub struct MinimizerCorpusScheduler where CS: CorpusScheduler, F: FavFactor, I: Input, - S: HasCorpus, + IT: IntoIterator + SerdeAny, + for<'a> &'a IT: IntoIterator, + S: HasCorpus + HasMetadata, C: Corpus, { base: CS, - phantom: PhantomData<(C, F, I, S)>, + phantom: PhantomData<(C, F, I, IT, S)>, } -impl CorpusScheduler for MinimizerCorpusScheduler +impl CorpusScheduler for MinimizerCorpusScheduler where CS: CorpusScheduler, F: FavFactor, I: Input, - S: HasCorpus, + IT: IntoIterator + SerdeAny, + for<'a> &'a IT: IntoIterator, + S: HasCorpus + HasMetadata, C: Corpus, { /// Add an entry to the corpus and return its index @@ -77,27 +107,68 @@ where } } -impl MinimizerCorpusScheduler +impl MinimizerCorpusScheduler where CS: CorpusScheduler, F: FavFactor, I: Input, - S: HasCorpus, + IT: IntoIterator + SerdeAny, + for<'a> &'a IT: IntoIterator, + S: HasCorpus + HasMetadata, C: Corpus, { - /*pub fn update_score(&self, state: &mut S, idx: usize) -> Result<(), Error> { - let entry = state.corpus().get(idx)?.borrow_mut(); - let factor = F::compute(&mut *entry)?; - for elem in entry.get::() { - if let val = self.top_rated.get_mut(elem) { - if factor > F::compute(self.entries()[val].borrow())? { - continue + pub fn update_score(&self, state: &mut S, idx: usize) -> Result<(), Error> { + let mut new_favoreds = vec![]; + { + let mut entry = state.corpus().get(idx)?.borrow_mut(); + let factor = F::compute(&mut *entry)?; + for elem in entry.metadatas().get::().unwrap() { + // TODO proper check for TopRatedsMetadata and create a new one if not present + if let Some(old_idx) = state + .metadata() + .get::() + .unwrap() + .map + .get(&elem) + { + if factor > F::compute(&mut *state.corpus().get(*old_idx)?.borrow_mut())? { + continue; + } } - } - let _ = self.top_rated.insert(elem, idx); + new_favoreds.push((elem, idx)); + } } - }*/ + + for pair in new_favoreds { + state + .metadata_mut() + .get_mut::() + .unwrap() + .map + .insert(pair.0, pair.1); + } + Ok(()) + } + + pub fn cull(&self, state: &mut S) -> Result<(), Error> { + let mut acc = HashSet::new(); + let top_rated = state.metadata().get::().unwrap(); + + for key in top_rated.map.keys() { + if !acc.contains(key) { + let idx = top_rated.map.get(key).unwrap(); + let mut entry = state.corpus().get(*idx)?.borrow_mut(); + for elem in entry.metadatas().get::().unwrap() { + acc.insert(elem); + } + + entry.add_metadata(IsFavoredMetadata {}); + } + } + + Ok(()) + } pub fn new(base: CS) -> Self { Self { @@ -105,23 +176,4 @@ where phantom: PhantomData, } } -} - -/* -pub fn cull(&mut self) { - let mut acc = HashSet::new(); - self.minset.clear(); - - for key in self.top_rated.keys() { - if !acc.contains(key) { - let idx = self.top_rated.get(key).unwrap(); - let entry = self.entries()[idx].borrow(); - for elem in entry.get::() { - acc.insert(elem); - } - - self.minset.insert(idx); - } - } -} -*/ +} \ No newline at end of file diff --git a/libafl/src/corpus/testcase.rs b/libafl/src/corpus/testcase.rs index 0fd7793eae..8b8cad970a 100644 --- a/libafl/src/corpus/testcase.rs +++ b/libafl/src/corpus/testcase.rs @@ -120,9 +120,15 @@ where self.fitness = fitness; } + /// Get all the metadatas into an HashMap + #[inline] + pub fn metadatas(&self) -> &SerdeAnyMap { + &self.metadatas + } + /// Get all the metadatas into an HashMap (mutable) #[inline] - pub fn metadatas(&mut self) -> &mut SerdeAnyMap { + pub fn metadatas_mut(&mut self) -> &mut SerdeAnyMap { &mut self.metadatas } diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 14f37ffffe..3914af875c 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -2,7 +2,7 @@ use alloc::{ string::{String, ToString}, vec::Vec, }; -use core::marker::PhantomData; +use core::{iter::IntoIterator, marker::PhantomData}; use num::Integer; use serde::{Deserialize, Serialize}; @@ -73,6 +73,23 @@ where } } +/// A testcase metadata holding a list of indexes of a map +#[derive(Serialize, Deserialize)] +pub struct IndexesMetadata { + pub list: Vec, +} + +crate::impl_serdeany!(IndexesMetadata); + +impl IntoIterator for IndexesMetadata { + type Item = usize; + type IntoIter = alloc::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.list.into_iter() + } +} + /// The most common AFL-like feedback type #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "T: serde::de::DeserializeOwned")] diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 1b189acebc..bfd1f1f82a 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -10,7 +10,6 @@ use crate::{ }; use alloc::vec::Vec; -use core::any::Any; use serde::{Deserialize, Serialize}; use mutations::buffer_copy;