fix anymap traverse all
This commit is contained in:
parent
5d2e7b5bc2
commit
4e1d844b7d
@ -1,11 +1,10 @@
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::ffi::c_void;
|
||||
use core::ptr;
|
||||
|
||||
use crate::executors::{Executor, ExitKind};
|
||||
use crate::inputs::Input;
|
||||
use crate::metamap::NamedAnyMap;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
|
||||
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
|
||||
@ -15,7 +14,7 @@ where
|
||||
I: Input,
|
||||
{
|
||||
harness: HarnessFunction<I>,
|
||||
observers: NamedAnyMap,
|
||||
observers: NamedAnyMap<dyn Observer>,
|
||||
}
|
||||
|
||||
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
|
||||
@ -35,6 +34,14 @@ where
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn observers(&self) -> &NamedAnyMap<dyn Observer> {
|
||||
&self.observers
|
||||
}
|
||||
|
||||
fn observers_mut(&mut self) -> &mut NamedAnyMap<dyn Observer> {
|
||||
&mut self.observers
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> InMemoryExecutor<I>
|
||||
@ -48,6 +55,7 @@ where
|
||||
}
|
||||
Self {
|
||||
harness: harness_fn,
|
||||
observers: NamedAnyMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
pub mod inmemory;
|
||||
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::Observer;
|
||||
use crate::metamap::NamedAnyMap;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
|
||||
pub enum ExitKind {
|
||||
@ -22,29 +22,33 @@ where
|
||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &NamedAnyMap;
|
||||
fn observers(&self) -> &NamedAnyMap<dyn Observer>;
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers_mut(&mut self) -> &mut NamedAnyMap;
|
||||
fn observers_mut(&mut self) -> &mut NamedAnyMap<dyn Observer>;
|
||||
|
||||
/// Add a linked observer
|
||||
fn add_observer(&mut self, observer: Box<dyn Observer>, name: &'static str) {
|
||||
self.observers_mut().push(observer);
|
||||
fn add_observer(&mut self, observer: Box<dyn Observer>) {
|
||||
self.observers_mut().insert(observer, observer.name());
|
||||
}
|
||||
|
||||
/// Reset the state of all the observes linked to this executor
|
||||
fn reset_observers(&mut self) -> Result<(), AflError> {
|
||||
for observer in self.observers_mut() {
|
||||
observer.reset()?;
|
||||
for typeid in self.observers().all_typeids() {
|
||||
for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() {
|
||||
observer.reset()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the post exec hook for all the observes linked to this executor
|
||||
fn post_exec_observers(&mut self) -> Result<(), AflError> {
|
||||
self.observers_mut()
|
||||
.iter()
|
||||
.map(|x| x.post_exec())
|
||||
.fold(Ok(()), |acc, x| if x.is_err() { x } else { acc })
|
||||
for typeid in self.observers().all_typeids() {
|
||||
for observer in self.observers_mut().all_by_typeid_mut(typeid).unwrap() {
|
||||
observer.post_exec()?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ 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;
|
||||
@ -17,7 +18,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) -> Result<u32, AflError>;
|
||||
fn is_interesting(&mut self, input: &I, executor: &dyn Executor<I>) -> Result<u32, AflError>;
|
||||
|
||||
/// 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> {
|
||||
@ -28,6 +29,8 @@ where
|
||||
fn discard_metadata(&mut self, _input: &I) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// A Reducer function is used to aggregate values for the novelty search
|
||||
@ -78,16 +81,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a usable history map of the given size
|
||||
pub fn create_history_map<T>(map_size: usize) -> Rc<RefCell<Vec<T>>>
|
||||
where
|
||||
T: Default + Clone,
|
||||
{
|
||||
{
|
||||
Rc::new(RefCell::new(vec![T::default(); map_size]))
|
||||
}
|
||||
}
|
||||
|
||||
/// The most common AFL-like feedback type
|
||||
pub struct MapFeedback<T, R, O>
|
||||
where
|
||||
@ -96,11 +89,11 @@ where
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
/// The observer this feedback struct observes
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Vec<T>,
|
||||
/// Name identifier of this instance
|
||||
name: &'static str,
|
||||
/// Phantom Data of Reducer
|
||||
phantom: PhantomData<R>,
|
||||
phantom: PhantomData<(R, O)>,
|
||||
}
|
||||
|
||||
impl<T, R, O, I> Feedback<I> for MapFeedback<T, R, O>
|
||||
@ -110,9 +103,8 @@ where
|
||||
O: MapObserver<T>,
|
||||
I: Input,
|
||||
{
|
||||
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||
fn is_interesting(&mut self, _input: &I, executor: &dyn Executor<I>) -> Result<u32, AflError> {
|
||||
let mut interesting = 0;
|
||||
|
||||
// TODO optimize
|
||||
let size = self.map_observer.borrow().map().len();
|
||||
let mut history_map = self.history_map.borrow_mut();
|
||||
@ -129,6 +121,10 @@ where
|
||||
|
||||
Ok(interesting)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, O> MapFeedback<T, R, O>
|
||||
@ -137,11 +133,11 @@ where
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Create new MapFeedback using a map observer
|
||||
pub fn new(map_observer: Rc<RefCell<O>>, map_size: usize) -> Self {
|
||||
/// Create new MapFeedback
|
||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
||||
Self {
|
||||
map_observer: map_observer,
|
||||
history_map: create_history_map::<T>(map_size),
|
||||
history_map: vec![T::default(); map_size],
|
||||
name: name,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -155,13 +151,10 @@ where
|
||||
{
|
||||
/// Create new MapFeedback using a map observer, and a map.
|
||||
/// The map can be shared.
|
||||
pub fn with_history_map(
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
) -> Self {
|
||||
pub fn with_history_map(name: &'static str, history_map: Vec<T>) -> Self {
|
||||
Self {
|
||||
map_observer: map_observer,
|
||||
history_map: history_map,
|
||||
name: name,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -206,11 +199,11 @@ where
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
/// The observer this feedback struct observes
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Vec<T>,
|
||||
/// Name identifier of this instance
|
||||
name: &'static str,
|
||||
/// Phantom Data of Reducer
|
||||
phantom: PhantomData<R>,
|
||||
phantom: PhantomData<(R, O)>,
|
||||
/// Track novel entries indexes
|
||||
novelties: Vec<usize>,
|
||||
}
|
||||
@ -254,6 +247,10 @@ where
|
||||
self.novelties.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, O> MapTrackerFeedback<T, R, O>
|
||||
|
@ -2,7 +2,7 @@ use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use core::any::{Any, TypeId};
|
||||
use core::slice::{Iter, IterMut};
|
||||
use hashbrown::hash_map::{Values, ValuesMut};
|
||||
use hashbrown::hash_map::{Keys, Values, ValuesMut};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
pub struct MetaMap {
|
||||
@ -241,11 +241,22 @@ impl MetaInstanceMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NamedAnyMap {
|
||||
map: HashMap<TypeId, HashMap<&'static str, Box<dyn Any>>>,
|
||||
pub trait AsAny {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
impl NamedAnyMap {
|
||||
pub struct NamedAnyMap<B>
|
||||
where
|
||||
B: ?Sized + Any + AsAny,
|
||||
{
|
||||
map: HashMap<TypeId, HashMap<&'static str, Box<B>>>,
|
||||
}
|
||||
|
||||
impl<B> NamedAnyMap<B>
|
||||
where
|
||||
B: ?Sized + Any + AsAny,
|
||||
{
|
||||
pub fn get<T>(&self, name: &'static str) -> Option<&T>
|
||||
where
|
||||
T: Any,
|
||||
@ -254,7 +265,14 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get(&name)
|
||||
.map(|x| x.as_ref().downcast_ref::<T>().unwrap()),
|
||||
.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(typeid) {
|
||||
None => None,
|
||||
Some(h) => h.get(&name).map(|x| x.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,27 +284,42 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get_mut(&name)
|
||||
.map(|x| x.as_mut().downcast_mut::<T>().unwrap()),
|
||||
.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(typeid) {
|
||||
None => None,
|
||||
Some(h) => h.get(&name).map(|x| x.as_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all<T>(
|
||||
&self,
|
||||
) -> Option<core::iter::Map<Values<'_, &'static str, Box<dyn Any>>, fn(&Box<dyn Any>) -> &T>>
|
||||
) -> Option<core::iter::Map<Values<'_, &'static str, Box<B>>, fn(&Box<B>) -> &T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get(&TypeId::of::<T>()) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values().map(|x| x.as_ref().downcast_ref::<T>().unwrap())),
|
||||
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<'_, &'static str, Box<B>>, fn(&Box<B>) -> &B>> {
|
||||
match self.map.get(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<'_, &'static str, Box<dyn Any>>, fn(&mut Box<dyn Any>) -> &mut T>,
|
||||
>
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, &'static str, Box<B>>, fn(&mut Box<B>) -> &mut T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
@ -294,23 +327,32 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => Some(
|
||||
h.values_mut()
|
||||
.map(|x| x.as_mut().downcast_mut::<T>().unwrap()),
|
||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert<T>(&mut self, t: T, name: &'static str)
|
||||
where
|
||||
T: Any,
|
||||
pub fn all_by_typeid_mut(
|
||||
&mut self,
|
||||
typeid: &TypeId,
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, &'static str, Box<B>>, fn(&mut Box<B>) -> &mut B>>
|
||||
{
|
||||
let typeid = TypeId::of::<T>();
|
||||
match self.map.get_mut(typeid) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values_mut().map(|x| x.as_mut())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_typeids(&self) -> Keys<'_, TypeId, HashMap<&'static str, Box<B>>> {
|
||||
self.map.keys()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, val: Box<B>, name: &'static str) {
|
||||
let typeid = val.type_id();
|
||||
if !self.map.contains_key(&typeid) {
|
||||
self.map.insert(typeid, HashMap::default());
|
||||
}
|
||||
self.map
|
||||
.get_mut(&typeid)
|
||||
.unwrap()
|
||||
.insert(name, Box::new(t));
|
||||
self.map.get_mut(&typeid).unwrap().insert(name, val);
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
@ -1,16 +1,15 @@
|
||||
extern crate num;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::slice::from_raw_parts_mut;
|
||||
use core::any::Any;
|
||||
use core::slice::from_raw_parts_mut;
|
||||
use num::Integer;
|
||||
|
||||
use crate::metamap::AsAny;
|
||||
use crate::AflError;
|
||||
|
||||
/// Observers observe different information about the target.
|
||||
/// They can then be used by various sorts of feedback.
|
||||
pub trait Observer: Any {
|
||||
pub trait Observer: Any + AsAny {
|
||||
fn flush(&mut self) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
@ -20,6 +19,8 @@ pub trait Observer: Any {
|
||||
fn post_exec(&mut self) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
||||
@ -52,24 +53,41 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StdMapObserver<'a, T>
|
||||
pub struct StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
T: Integer + Copy + 'static,
|
||||
{
|
||||
map: &'a mut [T],
|
||||
map: &'static mut [T],
|
||||
initial: T,
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl<'a, T> Observer for StdMapObserver<'a, T>
|
||||
impl<T> Observer for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
fn reset(&mut self) -> Result<(), AflError> {
|
||||
self.reset_map()
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> MapObserver<T> for StdMapObserver<'a, T>
|
||||
impl<T> AsAny for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MapObserver<T> for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
@ -94,36 +112,29 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> StdMapObserver<'a, T>
|
||||
impl<T> StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
/// Creates a new MapObserver
|
||||
pub fn new(map: &'a 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() };
|
||||
Self {
|
||||
map: map,
|
||||
initial: initial,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new MapObserver from a raw pointer
|
||||
pub fn new_from_ptr(map_ptr: *mut T, len: usize) -> Self {
|
||||
pub fn new_from_ptr(name: &'static str, map_ptr: *mut T, len: usize) -> Self {
|
||||
unsafe {
|
||||
let initial = if len > 0 { *map_ptr } else { T::zero() };
|
||||
StdMapObserver {
|
||||
map: from_raw_parts_mut(map_ptr, len),
|
||||
initial: initial,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Into<Rc<RefCell<Self>>> for StdMapObserver<'a, T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
fn into(self) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user