diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 6f536b636e..3685543e56 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -85,14 +85,15 @@ where /// Runs the input and triggers observers and feedback fn evaluate_input(&mut self, input: &I) -> Result { - self.reset_observers()?; + self.executor_mut().reset_observers()?; self.executor_mut().run_target(&input)?; self.set_executions(self.executions() + 1); - self.post_exec_observers()?; + self.executor_mut().post_exec_observers()?; let mut fitness = 0; + let observers = self.executor().observers(); for feedback in self.feedbacks_mut() { - fitness += feedback.is_interesting(&input)?; + fitness += feedback.is_interesting(&input, observers)?; } Ok(fitness) } @@ -225,14 +226,6 @@ where &mut self.metadatas } - fn observers(&self) -> &[Rc>] { - &self.observers - } - - fn observers_mut(&mut self) -> &mut Vec>> { - &mut self.observers - } - fn feedbacks(&self) -> &[Box>] { &self.feedbacks } diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index 5963a52d14..f1903b2695 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -3,7 +3,7 @@ use core::ptr; use crate::executors::{Executor, ExitKind}; use crate::inputs::Input; -use crate::metamap::NamedAnyMap; +use crate::serde_anymap::NamedSerdeAnyMap; use crate::observers::Observer; use crate::AflError; @@ -14,7 +14,7 @@ where I: Input, { harness: HarnessFunction, - observers: NamedAnyMap, + observers: NamedSerdeAnyMap, } static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null(); @@ -35,11 +35,11 @@ where Ok(ret) } - fn observers(&self) -> &NamedAnyMap { + fn observers(&self) -> &NamedSerdeAnyMap { &self.observers } - fn observers_mut(&mut self) -> &mut NamedAnyMap { + fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap { &mut self.observers } } @@ -55,7 +55,7 @@ where } Self { harness: harness_fn, - observers: NamedAnyMap::new(), + observers: NamedSerdeAnyMap::new(), } } } diff --git a/afl/src/executors/mod.rs b/afl/src/executors/mod.rs index e17d13b146..f71933454f 100644 --- a/afl/src/executors/mod.rs +++ b/afl/src/executors/mod.rs @@ -1,7 +1,7 @@ pub mod inmemory; use crate::inputs::Input; -use crate::metamap::NamedAnyMap; +use crate::serde_anymap::NamedSerdeAnyMap; use crate::observers::Observer; use crate::AflError; @@ -12,8 +12,6 @@ pub enum ExitKind { Timeout, } -// TODO unbox input - pub trait Executor where I: Input, @@ -22,33 +20,26 @@ where fn run_target(&mut self, input: &I) -> Result; /// Get the linked observers - fn observers(&self) -> &NamedAnyMap; + fn observers(&self) -> &NamedSerdeAnyMap; /// Get the linked observers - fn observers_mut(&mut self) -> &mut NamedAnyMap; + fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap; /// Add a linked observer fn add_observer(&mut self, observer: Box) { - self.observers_mut().insert(observer, observer.name()); + let name = observer.name(); + self.observers_mut().insert(observer, name); } /// Reset the state of all the observes linked to this executor fn reset_observers(&mut self) -> Result<(), AflError> { - for typeid in self.observers().all_typeids() { - for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() { - observer.reset()?; - } - } + self.observers_mut().for_each_mut(|_, x| Ok(x.reset()?))?; Ok(()) } /// Run the post exec hook for all the observes linked to this executor fn post_exec_observers(&mut self) -> Result<(), AflError> { - for typeid in self.observers().all_typeids() { - for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() { - observer.post_exec()?; - } - } + self.observers_mut().for_each_mut(|_, x| Ok(x.post_exec()?))?; Ok(()) } } diff --git a/afl/src/feedbacks/mod.rs b/afl/src/feedbacks/mod.rs index 7fe07f7efd..e22cc25144 100644 --- a/afl/src/feedbacks/mod.rs +++ b/afl/src/feedbacks/mod.rs @@ -1,16 +1,11 @@ -use alloc::rc::Rc; use alloc::vec::Vec; -use core::any::Any; -use core::cell::RefCell; use core::marker::PhantomData; use num::Integer; -use serde::{Deserialize, Serialize}; use crate::corpus::{Testcase, TestcaseMetadata}; -use crate::executors::Executor; use crate::inputs::Input; -use crate::observers::MapObserver; -use crate::serde_anymap::SerdeAny; +use crate::observers::{Observer, MapObserver}; +use crate::serde_anymap::NamedSerdeAnyMap; use crate::AflError; pub trait Feedback @@ -18,7 +13,7 @@ where I: Input, { /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) - fn is_interesting(&mut self, input: &I, executor: &dyn Executor) -> Result; + fn is_interesting(&mut self, input: &I, observers: &NamedSerdeAnyMap) -> Result; /// Append to the testcase the generated metadata in case of a new corpus item fn append_metadata(&mut self, _testcase: &mut Testcase) -> Result<(), AflError> { @@ -100,21 +95,20 @@ impl Feedback for MapFeedback where T: Integer + Copy + 'static, R: Reducer, - O: MapObserver, + O: MapObserver + 'static, I: Input, { - fn is_interesting(&mut self, _input: &I, executor: &dyn Executor) -> Result { + fn is_interesting(&mut self, _input: &I, observers: &NamedSerdeAnyMap) -> Result { let mut interesting = 0; // TODO optimize - let size = self.map_observer.borrow().map().len(); - let mut history_map = self.history_map.borrow_mut(); - let observer = self.map_observer.borrow(); + let observer = observers.get::(self.name).unwrap(); + let size = observer.map().len(); for i in 0..size { - let history = history_map[i]; + let history = self.history_map[i]; let item = observer.map()[i]; let reduced = R::reduce(history, item); if history != reduced { - history_map[i] = reduced; + self.history_map[i] = reduced; interesting += 1; } } @@ -160,6 +154,7 @@ where } } +/* #[derive(Serialize, Deserialize)] pub struct MapNoveltiesMetadata { novelties: Vec, @@ -290,9 +285,10 @@ where } } } +*/ pub type MaxMapFeedback = MapFeedback, O>; pub type MinMapFeedback = MapFeedback, O>; -pub type MaxMapTrackerFeedback = MapFeedback, O>; -pub type MinMapTrackerFeedback = MapFeedback, O>; +//pub type MaxMapTrackerFeedback = MapFeedback, O>; +//pub type MinMapTrackerFeedback = MapFeedback, O>; diff --git a/afl/src/metamap.rs b/afl/src/metamap.rs index 42d5dc23c1..dbc33500ae 100644 --- a/afl/src/metamap.rs +++ b/afl/src/metamap.rs @@ -291,7 +291,7 @@ where pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> { match self.map.get_mut(typeid) { None => None, - Some(h) => h.get(&name).map(|x| x.as_mut()), + Some(h) => h.get_mut(&name).map(|x| x.as_mut()), } } diff --git a/afl/src/observers/mod.rs b/afl/src/observers/mod.rs index 54ae4097e4..bc9d9ac8ef 100644 --- a/afl/src/observers/mod.rs +++ b/afl/src/observers/mod.rs @@ -3,13 +3,14 @@ extern crate num; use core::any::Any; use core::slice::from_raw_parts_mut; use num::Integer; +use serde::{Deserialize, Serialize}; -use crate::metamap::AsAny; +use crate::serde_anymap::{SerdeAny, SliceMut}; use crate::AflError; /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. -pub trait Observer: Any + AsAny { +pub trait Observer: SerdeAny + 'static { fn flush(&mut self) -> Result<(), AflError> { Ok(()) } @@ -35,7 +36,7 @@ where fn map_mut(&mut self) -> &mut [T]; /// Get the initial value for reset() - fn initial(&self) -> &T; + fn initial(&self) -> T; /// Get the initial value for reset() fn initial_mut(&mut self) -> &mut T; @@ -46,25 +47,27 @@ where /// Reset the map fn reset_map(&mut self) -> Result<(), AflError> { // Normal memset, see https://rust.godbolt.org/z/Trs5hv + let initial = self.initial(); for i in self.map_mut().iter_mut() { - *i = T::zero(); + *i = initial; } Ok(()) } } +#[derive(Serialize, Deserialize)] pub struct StdMapObserver where T: Integer + Copy + 'static, { - map: &'static mut [T], + map: SliceMut<'static, T>, initial: T, name: &'static str, } impl Observer for StdMapObserver where - T: Integer + Copy, + T: Integer + Copy + 'static + serde::Serialize, { fn reset(&mut self) -> Result<(), AflError> { self.reset_map() @@ -75,9 +78,9 @@ where } } -impl AsAny for StdMapObserver +impl SerdeAny for StdMapObserver where - T: Integer + Copy, + T: Integer + Copy + 'static + serde::Serialize, { fn as_any(&self) -> &dyn Any { self @@ -92,15 +95,21 @@ where T: Integer + Copy, { fn map(&self) -> &[T] { - &self.map + match &self.map { + SliceMut::Ref(r) => r, + SliceMut::Owned(v) => v.as_slice() + } } fn map_mut(&mut self) -> &mut [T] { - &mut self.map + match &mut self.map { + SliceMut::Ref(r) => r, + SliceMut::Owned(v) => v.as_mut_slice() + } } - fn initial(&self) -> &T { - &self.initial + fn initial(&self) -> T { + self.initial } fn initial_mut(&mut self) -> &mut T { @@ -120,7 +129,7 @@ where pub fn new(name: &'static str, map: &'static mut [T]) -> Self { let initial = if map.len() > 0 { map[0] } else { T::zero() }; Self { - map: map, + map: SliceMut::Ref(map), initial: initial, name: name, } @@ -131,7 +140,7 @@ where unsafe { let initial = if len > 0 { *map_ptr } else { T::zero() }; StdMapObserver { - map: from_raw_parts_mut(map_ptr, len), + map: SliceMut::Ref(from_raw_parts_mut(map_ptr, len)), initial: initial, name: name, } diff --git a/afl/src/serde_anymap.rs b/afl/src/serde_anymap.rs index 72d8bf7fd6..7d625e2693 100644 --- a/afl/src/serde_anymap.rs +++ b/afl/src/serde_anymap.rs @@ -5,6 +5,10 @@ use alloc::boxed::Box; use core::any::{Any, TypeId}; use core::default::Default; use core::fmt; +use core::slice::{Iter, IterMut}; +use hashbrown::hash_map::{Keys, Values, ValuesMut}; + +use crate::AflError; pub fn pack_type_id(id: u64) -> TypeId { unsafe { *(&id as *const u64 as *const TypeId) } @@ -199,3 +203,241 @@ impl SerdeAnyMap { } } } + +#[derive(Serialize, Deserialize)] +pub struct NamedSerdeAnyMap +where + B: ?Sized + SerdeAny, +{ + map: HashMap>>, +} + +impl NamedSerdeAnyMap +where + B: ?Sized + SerdeAny, +{ + pub fn get(&self, name: &'static str) -> Option<&T> + where + T: Any, + { + match self.map.get(&unpack_type_id(TypeId::of::())) { + None => None, + Some(h) => h + .get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())) + .map(|x| x.as_any().downcast_ref::().unwrap()), + } + } + + pub fn by_typeid(&self, name: &'static str, typeid: &TypeId) -> Option<&B> { + match self.map.get(&unpack_type_id(*typeid)) { + None => None, + Some(h) => h.get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())).map(|x| x.as_ref()), + } + } + + pub fn get_mut(&mut self, name: &'static str) -> Option<&mut T> + where + T: Any, + { + match self.map.get_mut(&unpack_type_id(TypeId::of::())) { + None => None, + Some(h) => h + .get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())) + .map(|x| x.as_any_mut().downcast_mut::().unwrap()), + } + } + + pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> { + 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(|x| x.as_mut()), + } + } + + pub fn get_all( + &self, + ) -> Option>, fn(&Box) -> &T>> + where + T: Any, + { + match self.map.get(&unpack_type_id(TypeId::of::())) { + None => None, + Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::().unwrap())), + } + } + + pub fn all_by_typeid( + &self, + typeid: &TypeId, + ) -> Option>, fn(&Box) -> &B>> { + match self.map.get(&unpack_type_id(*typeid)) { + None => None, + Some(h) => Some(h.values().map(|x| x.as_ref())), + } + } + + pub fn get_all_mut( + &mut self, + ) -> Option>, fn(&mut Box) -> &mut T>> + where + T: Any, + { + match self.map.get_mut(&unpack_type_id(TypeId::of::())) { + None => None, + Some(h) => Some( + h.values_mut() + .map(|x| x.as_any_mut().downcast_mut::().unwrap()), + ), + } + } + + pub fn all_by_typeid_mut( + &mut self, + typeid: &TypeId, + ) -> Option>, fn(&mut Box) -> &mut B>> + { + match self.map.get_mut(&unpack_type_id(*typeid)) { + None => None, + Some(h) => Some(h.values_mut().map(|x| x.as_mut())), + } + } + + pub fn all_typeids(&self) -> core::iter::Map>>, fn(&u64) -> TypeId> { + self.map.keys().map(|x| pack_type_id(*x)) + } + + pub fn for_each(&self, func: fn(&TypeId, &Box) -> Result<(), AflError>) -> Result<(), AflError> { + for (id, h) in self.map.iter() { + for x in h.values() { + func(&pack_type_id(*id), x)?; + } + } + Ok(()) + } + + pub fn for_each_mut(&mut self, func: fn(&TypeId, &mut Box) -> Result<(), AflError>) -> Result<(), AflError> { + for (id, h) in self.map.iter_mut() { + for x in h.values_mut() { + func(&pack_type_id(*id), x)?; + } + } + Ok(()) + } + + pub fn insert(&mut self, val: Box, name: &'static str) { + let id = unpack_type_id(val.type_id()); + 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()), val); + } + + pub fn len(&self) -> usize { + self.map.len() + } + + pub fn contains_type(&self) -> bool + where + T: Any, + { + self.map.contains_key(&unpack_type_id(TypeId::of::())) + } + + pub fn contains(&self, name: &'static str) -> bool + where + T: Any, + { + match self.map.get(&unpack_type_id(TypeId::of::())) { + None => false, + Some(h) => h.contains_key(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())), + } + } + + pub fn new() -> Self { + Self { + map: HashMap::default(), + } + } +} + +impl Default for NamedSerdeAnyMap +where + B: ?Sized + SerdeAny, +{ + fn default() -> Self { + Self::new() + } +} + +#[derive(Serialize)] +pub enum Ptr<'a, T: 'a + ?Sized> { + Ref(&'a T), + Owned(Box), +} + +impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for Ptr<'a, T> +where + Box: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Ptr::Owned) + } +} + +#[derive(Serialize)] +pub enum PtrMut<'a, T: 'a + ?Sized> { + Ref(&'a mut T), + Owned(Box), +} + +impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for PtrMut<'a, T> +where + Box: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(PtrMut::Owned) + } +} + +#[derive(Serialize)] +pub enum Slice<'a, T: 'a + Sized> { + Ref(&'a [T]), + Owned(Vec), +} + +impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for Slice<'a, T> +where + Vec: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(Slice::Owned) + } +} + +#[derive(Serialize)] +pub enum SliceMut<'a, T: 'a + Sized> { + Ref(&'a mut [T]), + Owned(Vec), +} + +impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for SliceMut<'a, T> +where + Vec: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(SliceMut::Owned) + } +} +