variable sized map observer

This commit is contained in:
Andrea Fioraldi 2020-12-17 17:42:04 +01:00
parent a625904399
commit 1e315baa56
4 changed files with 188 additions and 9 deletions

View File

@ -189,7 +189,7 @@ where
let mut interesting = 0; let mut interesting = 0;
// TODO optimize // TODO optimize
let observer = observers.match_name_type::<O>(&self.name).unwrap(); let observer = observers.match_name_type::<O>(&self.name).unwrap();
let size = observer.map().len(); let size = observer.usable_count();
for i in 0..size { for i in 0..size {
let history = self.history_map[i]; let history = self.history_map[i];
let item = observer.map()[i]; let item = observer.map()[i];

View File

@ -2,7 +2,7 @@ extern crate num;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::serde_anymap::ArrayMut; use crate::serde_anymap::{Cptr, ArrayMut};
use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList}; use crate::tuples::{MatchNameAndType, MatchType, Named, TupleList};
use crate::AflError; use crate::AflError;
@ -92,6 +92,11 @@ where
/// Get the map (mutable) /// Get the map (mutable)
fn map_mut(&mut self) -> &mut [T]; fn map_mut(&mut self) -> &mut [T];
/// Get the number of usable entries in the map (all by default)
fn usable_count(&self) -> usize {
self.map().len()
}
/// Get the initial value for reset() /// Get the initial value for reset()
fn initial(&self) -> T; fn initial(&self) -> T;
@ -106,7 +111,8 @@ where
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(); let initial = self.initial();
for i in self.map_mut().iter_mut() { let cnt = self.usable_count();
for i in self.map_mut()[0..cnt].iter_mut() {
*i = initial; *i = initial;
} }
Ok(()) Ok(())
@ -204,6 +210,102 @@ where
} }
} }
#[derive(Serialize, Deserialize)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct VariableMapObserver<T>
where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{
map: ArrayMut<T>,
size: Cptr<usize>,
initial: T,
name: String,
}
impl<T> Observer for VariableMapObserver<T>
where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn reset(&mut self) -> Result<(), AflError> {
self.reset_map()
}
}
impl<T> Named for VariableMapObserver<T>
where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
}
}
impl<T> MapObserver<T> for VariableMapObserver<T>
where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{
#[inline]
fn map(&self) -> &[T] {
self.map.as_slice()
}
#[inline]
fn map_mut(&mut self) -> &mut [T] {
self.map.as_mut_slice()
}
#[inline]
fn usable_count(&self) -> usize {
*self.size.as_ref()
}
#[inline]
fn initial(&self) -> T {
self.initial
}
#[inline]
fn initial_mut(&mut self) -> &mut T {
&mut self.initial
}
#[inline]
fn set_initial(&mut self, initial: T) {
self.initial = initial
}
}
impl<T> VariableMapObserver<T>
where
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
{
/// Creates a new MapObserver
pub fn new(name: &'static str, map: &'static mut [T], size: &usize) -> Self {
let initial = if map.len() > 0 { map[0] } else { T::default() };
Self {
map: ArrayMut::Cptr((map.as_mut_ptr(), map.len())),
size: Cptr::Cptr(size as *const _),
name: name.into(),
initial,
}
}
/// Creates a new MapObserver from a raw pointer
pub fn new_from_ptr(name: &'static str, map_ptr: *mut T, max_len: usize, size_ptr: *const usize) -> Self {
unsafe {
let initial = if max_len > 0 { *map_ptr } else { T::default() };
VariableMapObserver {
map: ArrayMut::Cptr((map_ptr, max_len)),
size: Cptr::Cptr(size_ptr),
name: name.into(),
initial,
}
}
}
}
/* /*
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg(test)] #[cfg(test)]

View File

@ -629,7 +629,84 @@ impl<'a, T: Sized> SliceMut<'a, T> {
} }
} }
pub enum Array<T: Sized + serde::Serialize> { pub enum Cptr<T: Sized> {
Cptr(*const T),
Owned(Box<T>),
}
impl<T: Sized + serde::Serialize> serde::Serialize for Cptr<T> {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.as_ref().serialize(se)
}
}
impl<'de, T: Sized + serde::de::DeserializeOwned> Deserialize<'de> for Cptr<T>
where
Vec<T>: Deserialize<'de>,
{
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Deserialize::deserialize(de).map(Cptr::Owned)
}
}
impl<T: Sized> Cptr<T> {
pub fn as_ref(&self) -> &T {
match self {
Cptr::Cptr(p) => unsafe { p.as_ref().unwrap() },
Cptr::Owned(v) => v.as_ref(),
}
}
}
pub enum CptrMut<T: Sized> {
Cptr(*mut T),
Owned(Box<T>),
}
impl<T: Sized + serde::Serialize> serde::Serialize for CptrMut<T> {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.as_ref().serialize(se)
}
}
impl<'de, T: Sized + serde::de::DeserializeOwned> Deserialize<'de> for CptrMut<T>
where
Vec<T>: Deserialize<'de>,
{
fn deserialize<D>(de: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Deserialize::deserialize(de).map(CptrMut::Owned)
}
}
impl<T: Sized> CptrMut<T> {
pub fn as_ref(&self) -> &T {
match self {
CptrMut::Cptr(p) => unsafe { p.as_ref().unwrap() },
CptrMut::Owned(b) => b.as_ref(),
}
}
pub fn as_mut(&mut self) -> &mut T {
match self {
CptrMut::Cptr(p) => unsafe { p.as_mut().unwrap() },
CptrMut::Owned(b) => b.as_mut(),
}
}
}
pub enum Array<T: Sized> {
Cptr((*const T, usize)), Cptr((*const T, usize)),
Owned(Vec<T>), Owned(Vec<T>),
} }
@ -655,7 +732,7 @@ where
} }
} }
impl<T: Sized + serde::Serialize> Array<T> { impl<T: Sized> Array<T> {
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
match self { match self {
Array::Cptr(p) => unsafe { core::slice::from_raw_parts(p.0, p.1) }, Array::Cptr(p) => unsafe { core::slice::from_raw_parts(p.0, p.1) },
@ -664,7 +741,7 @@ impl<T: Sized + serde::Serialize> Array<T> {
} }
} }
pub enum ArrayMut<T: Sized + serde::Serialize> { pub enum ArrayMut<T: Sized> {
Cptr((*mut T, usize)), Cptr((*mut T, usize)),
Owned(Vec<T>), Owned(Vec<T>),
} }
@ -690,7 +767,7 @@ where
} }
} }
impl<T: Sized + serde::Serialize> ArrayMut<T> { impl<T: Sized> ArrayMut<T> {
pub fn as_slice(&self) -> &[T] { pub fn as_slice(&self) -> &[T] {
match self { match self {
ArrayMut::Cptr(p) => unsafe { core::slice::from_raw_parts(p.0, p.1) }, ArrayMut::Cptr(p) => unsafe { core::slice::from_raw_parts(p.0, p.1) },

View File

@ -14,7 +14,7 @@ use afl::feedbacks::MaxMapFeedback;
use afl::generators::RandPrintablesGenerator; use afl::generators::RandPrintablesGenerator;
use afl::mutators::scheduled::HavocBytesMutator; use afl::mutators::scheduled::HavocBytesMutator;
use afl::mutators::HasMaxSize; use afl::mutators::HasMaxSize;
use afl::observers::StdMapObserver; use afl::observers::VariableMapObserver;
use afl::stages::mutational::StdMutationalStage; use afl::stages::mutational::StdMutationalStage;
use afl::tuples::tuple_list; use afl::tuples::tuple_list;
use afl::utils::StdRand; use afl::utils::StdRand;
@ -66,7 +66,7 @@ pub extern "C" fn fuzz_main_loop() {
} }
println!("We're a client, let's fuzz :)"); println!("We're a client, let's fuzz :)");
let edges_observer = StdMapObserver::new_from_ptr(&NAME_COV_MAP, unsafe { fuzz_hitcounts_map.as_mut_ptr() }, unsafe { fuzz_edges_id }); let edges_observer = VariableMapObserver::new(&NAME_COV_MAP, unsafe { &mut fuzz_hitcounts_map }, unsafe { &fuzz_edges_id });
let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer); let edges_feedback = MaxMapFeedback::new_with_observer(&NAME_COV_MAP, &edges_observer);
let executor = InMemoryExecutor::new("QEMUFuzzer", harness, tuple_list!(edges_observer)); let executor = InMemoryExecutor::new("QEMUFuzzer", harness, tuple_list!(edges_observer));