NamedSerdeAnyMap observers

This commit is contained in:
Andrea Fioraldi 2020-12-08 12:37:49 +01:00
parent 4e1d844b7d
commit ff983ecf23
7 changed files with 295 additions and 64 deletions

View File

@ -85,14 +85,15 @@ where
/// Runs the input and triggers observers and feedback /// Runs the input and triggers observers and feedback
fn evaluate_input(&mut self, input: &I) -> Result<u32, AflError> { fn evaluate_input(&mut self, input: &I) -> Result<u32, AflError> {
self.reset_observers()?; self.executor_mut().reset_observers()?;
self.executor_mut().run_target(&input)?; self.executor_mut().run_target(&input)?;
self.set_executions(self.executions() + 1); self.set_executions(self.executions() + 1);
self.post_exec_observers()?; self.executor_mut().post_exec_observers()?;
let mut fitness = 0; let mut fitness = 0;
let observers = self.executor().observers();
for feedback in self.feedbacks_mut() { for feedback in self.feedbacks_mut() {
fitness += feedback.is_interesting(&input)?; fitness += feedback.is_interesting(&input, observers)?;
} }
Ok(fitness) Ok(fitness)
} }
@ -225,14 +226,6 @@ where
&mut self.metadatas &mut self.metadatas
} }
fn observers(&self) -> &[Rc<RefCell<dyn Observer>>] {
&self.observers
}
fn observers_mut(&mut self) -> &mut Vec<Rc<RefCell<dyn Observer>>> {
&mut self.observers
}
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] { fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] {
&self.feedbacks &self.feedbacks
} }

View File

@ -3,7 +3,7 @@ use core::ptr;
use crate::executors::{Executor, ExitKind}; use crate::executors::{Executor, ExitKind};
use crate::inputs::Input; use crate::inputs::Input;
use crate::metamap::NamedAnyMap; use crate::serde_anymap::NamedSerdeAnyMap;
use crate::observers::Observer; use crate::observers::Observer;
use crate::AflError; use crate::AflError;
@ -14,7 +14,7 @@ where
I: Input, I: Input,
{ {
harness: HarnessFunction<I>, harness: HarnessFunction<I>,
observers: NamedAnyMap<dyn Observer>, observers: NamedSerdeAnyMap<dyn Observer>,
} }
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null(); static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
@ -35,11 +35,11 @@ where
Ok(ret) Ok(ret)
} }
fn observers(&self) -> &NamedAnyMap<dyn Observer> { fn observers(&self) -> &NamedSerdeAnyMap<dyn Observer> {
&self.observers &self.observers
} }
fn observers_mut(&mut self) -> &mut NamedAnyMap<dyn Observer> { fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap<dyn Observer> {
&mut self.observers &mut self.observers
} }
} }
@ -55,7 +55,7 @@ where
} }
Self { Self {
harness: harness_fn, harness: harness_fn,
observers: NamedAnyMap::new(), observers: NamedSerdeAnyMap::new(),
} }
} }
} }

View File

@ -1,7 +1,7 @@
pub mod inmemory; pub mod inmemory;
use crate::inputs::Input; use crate::inputs::Input;
use crate::metamap::NamedAnyMap; use crate::serde_anymap::NamedSerdeAnyMap;
use crate::observers::Observer; use crate::observers::Observer;
use crate::AflError; use crate::AflError;
@ -12,8 +12,6 @@ pub enum ExitKind {
Timeout, Timeout,
} }
// TODO unbox input
pub trait Executor<I> pub trait Executor<I>
where where
I: Input, I: Input,
@ -22,33 +20,26 @@ where
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>; fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
/// Get the linked observers /// Get the linked observers
fn observers(&self) -> &NamedAnyMap<dyn Observer>; fn observers(&self) -> &NamedSerdeAnyMap<dyn Observer>;
/// Get the linked observers /// Get the linked observers
fn observers_mut(&mut self) -> &mut NamedAnyMap<dyn Observer>; fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap<dyn Observer>;
/// Add a linked observer /// Add a linked observer
fn add_observer(&mut self, observer: Box<dyn Observer>) { fn add_observer(&mut self, observer: Box<dyn Observer>) {
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 /// Reset the state of all the observes linked to this executor
fn reset_observers(&mut self) -> Result<(), AflError> { fn reset_observers(&mut self) -> Result<(), AflError> {
for typeid in self.observers().all_typeids() { self.observers_mut().for_each_mut(|_, x| Ok(x.reset()?))?;
for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() {
observer.reset()?;
}
}
Ok(()) Ok(())
} }
/// Run the post exec hook for all the observes linked to this executor /// Run the post exec hook for all the observes linked to this executor
fn post_exec_observers(&mut self) -> Result<(), AflError> { fn post_exec_observers(&mut self) -> Result<(), AflError> {
for typeid in self.observers().all_typeids() { self.observers_mut().for_each_mut(|_, x| Ok(x.post_exec()?))?;
for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() {
observer.post_exec()?;
}
}
Ok(()) Ok(())
} }
} }

View File

@ -1,16 +1,11 @@
use alloc::rc::Rc;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::any::Any;
use core::cell::RefCell;
use core::marker::PhantomData; use core::marker::PhantomData;
use num::Integer; use num::Integer;
use serde::{Deserialize, Serialize};
use crate::corpus::{Testcase, TestcaseMetadata}; use crate::corpus::{Testcase, TestcaseMetadata};
use crate::executors::Executor;
use crate::inputs::Input; use crate::inputs::Input;
use crate::observers::MapObserver; use crate::observers::{Observer, MapObserver};
use crate::serde_anymap::SerdeAny; use crate::serde_anymap::NamedSerdeAnyMap;
use crate::AflError; use crate::AflError;
pub trait Feedback<I> pub trait Feedback<I>
@ -18,7 +13,7 @@ where
I: Input, I: Input,
{ {
/// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55) /// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55)
fn is_interesting(&mut self, input: &I, executor: &dyn Executor<I>) -> Result<u32, AflError>; fn is_interesting(&mut self, input: &I, observers: &NamedSerdeAnyMap<dyn Observer>) -> Result<u32, AflError>;
/// Append to the testcase the generated metadata in case of a new corpus item /// Append to the testcase the generated metadata in case of a new corpus item
fn append_metadata(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> { fn append_metadata(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> {
@ -100,21 +95,20 @@ impl<T, R, O, I> Feedback<I> for MapFeedback<T, R, O>
where where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
R: Reducer<T>, R: Reducer<T>,
O: MapObserver<T>, O: MapObserver<T> + 'static,
I: Input, I: Input,
{ {
fn is_interesting(&mut self, _input: &I, executor: &dyn Executor<I>) -> Result<u32, AflError> { fn is_interesting(&mut self, _input: &I, observers: &NamedSerdeAnyMap<dyn Observer>) -> Result<u32, AflError> {
let mut interesting = 0; let mut interesting = 0;
// TODO optimize // TODO optimize
let size = self.map_observer.borrow().map().len(); let observer = observers.get::<O>(self.name).unwrap();
let mut history_map = self.history_map.borrow_mut(); let size = observer.map().len();
let observer = self.map_observer.borrow();
for i in 0..size { for i in 0..size {
let history = history_map[i]; let history = self.history_map[i];
let item = observer.map()[i]; let item = observer.map()[i];
let reduced = R::reduce(history, item); let reduced = R::reduce(history, item);
if history != reduced { if history != reduced {
history_map[i] = reduced; self.history_map[i] = reduced;
interesting += 1; interesting += 1;
} }
} }
@ -160,6 +154,7 @@ where
} }
} }
/*
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct MapNoveltiesMetadata { pub struct MapNoveltiesMetadata {
novelties: Vec<usize>, novelties: Vec<usize>,
@ -290,9 +285,10 @@ where
} }
} }
} }
*/
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>; pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>; pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
pub type MaxMapTrackerFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>; //pub type MaxMapTrackerFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
pub type MinMapTrackerFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>; //pub type MinMapTrackerFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;

View File

@ -291,7 +291,7 @@ where
pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> { pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> {
match self.map.get_mut(typeid) { match self.map.get_mut(typeid) {
None => None, None => None,
Some(h) => h.get(&name).map(|x| x.as_mut()), Some(h) => h.get_mut(&name).map(|x| x.as_mut()),
} }
} }

View File

@ -3,13 +3,14 @@ extern crate num;
use core::any::Any; use core::any::Any;
use core::slice::from_raw_parts_mut; use core::slice::from_raw_parts_mut;
use num::Integer; use num::Integer;
use serde::{Deserialize, Serialize};
use crate::metamap::AsAny; use crate::serde_anymap::{SerdeAny, SliceMut};
use crate::AflError; use crate::AflError;
/// Observers observe different information about the target. /// Observers observe different information about the target.
/// They can then be used by various sorts of feedback. /// 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> { fn flush(&mut self) -> Result<(), AflError> {
Ok(()) Ok(())
} }
@ -35,7 +36,7 @@ where
fn map_mut(&mut self) -> &mut [T]; fn map_mut(&mut self) -> &mut [T];
/// Get the initial value for reset() /// Get the initial value for reset()
fn initial(&self) -> &T; fn initial(&self) -> T;
/// Get the initial value for reset() /// Get the initial value for reset()
fn initial_mut(&mut self) -> &mut T; fn initial_mut(&mut self) -> &mut T;
@ -46,25 +47,27 @@ where
/// Reset the map /// Reset the map
fn reset_map(&mut self) -> Result<(), AflError> { fn reset_map(&mut self) -> Result<(), AflError> {
// Normal memset, see https://rust.godbolt.org/z/Trs5hv // Normal memset, see https://rust.godbolt.org/z/Trs5hv
let initial = self.initial();
for i in self.map_mut().iter_mut() { for i in self.map_mut().iter_mut() {
*i = T::zero(); *i = initial;
} }
Ok(()) Ok(())
} }
} }
#[derive(Serialize, Deserialize)]
pub struct StdMapObserver<T> pub struct StdMapObserver<T>
where where
T: Integer + Copy + 'static, T: Integer + Copy + 'static,
{ {
map: &'static mut [T], map: SliceMut<'static, T>,
initial: T, initial: T,
name: &'static str, name: &'static str,
} }
impl<T> Observer for StdMapObserver<T> impl<T> Observer for StdMapObserver<T>
where where
T: Integer + Copy, T: Integer + Copy + 'static + serde::Serialize,
{ {
fn reset(&mut self) -> Result<(), AflError> { fn reset(&mut self) -> Result<(), AflError> {
self.reset_map() self.reset_map()
@ -75,9 +78,9 @@ where
} }
} }
impl<T> AsAny for StdMapObserver<T> impl<T> SerdeAny for StdMapObserver<T>
where where
T: Integer + Copy, T: Integer + Copy + 'static + serde::Serialize,
{ {
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
@ -92,15 +95,21 @@ where
T: Integer + Copy, T: Integer + Copy,
{ {
fn map(&self) -> &[T] { 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] { 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 { fn initial(&self) -> T {
&self.initial self.initial
} }
fn initial_mut(&mut self) -> &mut T { fn initial_mut(&mut self) -> &mut T {
@ -120,7 +129,7 @@ where
pub fn new(name: &'static str, map: &'static mut [T]) -> Self { pub fn new(name: &'static str, map: &'static mut [T]) -> Self {
let initial = if map.len() > 0 { map[0] } else { T::zero() }; let initial = if map.len() > 0 { map[0] } else { T::zero() };
Self { Self {
map: map, map: SliceMut::Ref(map),
initial: initial, initial: initial,
name: name, name: name,
} }
@ -131,7 +140,7 @@ where
unsafe { unsafe {
let initial = if len > 0 { *map_ptr } else { T::zero() }; let initial = if len > 0 { *map_ptr } else { T::zero() };
StdMapObserver { StdMapObserver {
map: from_raw_parts_mut(map_ptr, len), map: SliceMut::Ref(from_raw_parts_mut(map_ptr, len)),
initial: initial, initial: initial,
name: name, name: name,
} }

View File

@ -5,6 +5,10 @@ use alloc::boxed::Box;
use core::any::{Any, TypeId}; use core::any::{Any, TypeId};
use core::default::Default; use core::default::Default;
use core::fmt; 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 { pub fn pack_type_id(id: u64) -> TypeId {
unsafe { *(&id as *const u64 as *const TypeId) } unsafe { *(&id as *const u64 as *const TypeId) }
@ -199,3 +203,241 @@ impl SerdeAnyMap {
} }
} }
} }
#[derive(Serialize, Deserialize)]
pub struct NamedSerdeAnyMap<B>
where
B: ?Sized + SerdeAny,
{
map: HashMap<u64, HashMap<u64, Box<B>>>,
}
impl<B> NamedSerdeAnyMap<B>
where
B: ?Sized + SerdeAny,
{
pub fn get<T>(&self, name: &'static str) -> Option<&T>
where
T: Any,
{
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()),
}
}
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<T>(&mut self, name: &'static str) -> Option<&mut T>
where
T: Any,
{
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()),
}
}
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<T>(
&self,
) -> Option<core::iter::Map<Values<'_, u64, Box<B>>, fn(&Box<B>) -> &T>>
where
T: Any,
{
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())),
}
}
pub fn all_by_typeid(
&self,
typeid: &TypeId,
) -> Option<core::iter::Map<Values<'_, u64, Box<B>>, fn(&Box<B>) -> &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<T>(
&mut self,
) -> Option<core::iter::Map<ValuesMut<'_, u64, Box<B>>, fn(&mut Box<B>) -> &mut T>>
where
T: Any,
{
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()),
),
}
}
pub fn all_by_typeid_mut(
&mut self,
typeid: &TypeId,
) -> Option<core::iter::Map<ValuesMut<'_, u64, Box<B>>, fn(&mut Box<B>) -> &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<Keys<'_, u64, HashMap<u64, Box<B>>>, fn(&u64) -> TypeId> {
self.map.keys().map(|x| pack_type_id(*x))
}
pub fn for_each(&self, func: fn(&TypeId, &Box<B>) -> 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<B>) -> 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<B>, 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<T>(&self) -> bool
where
T: Any,
{
self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
}
pub fn contains<T>(&self, name: &'static str) -> bool
where
T: Any,
{
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())),
}
}
pub fn new() -> Self {
Self {
map: HashMap::default(),
}
}
}
impl<B> Default for NamedSerdeAnyMap<B>
where
B: ?Sized + SerdeAny,
{
fn default() -> Self {
Self::new()
}
}
#[derive(Serialize)]
pub enum Ptr<'a, T: 'a + ?Sized> {
Ref(&'a T),
Owned(Box<T>),
}
impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for Ptr<'a, T>
where
Box<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<T>),
}
impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for PtrMut<'a, T>
where
Box<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<T>),
}
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for Slice<'a, T>
where
Vec<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<T>),
}
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for SliceMut<'a, T>
where
Vec<T>: Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Deserialize::deserialize(deserializer).map(SliceMut::Owned)
}
}