map observers file
This commit is contained in:
parent
ffab1e021e
commit
a8dd59f588
@ -18,7 +18,7 @@ pub fn unpack_type_id(id: TypeId) -> u64 {
|
|||||||
unsafe { *(&id as *const _ as *const u64) }
|
unsafe { *(&id as *const _ as *const u64) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An any object
|
/// A (de)serializable Any trait
|
||||||
pub trait SerdeAny: Any + erased_serde::Serialize {
|
pub trait SerdeAny: Any + erased_serde::Serialize {
|
||||||
/// returns this as Any trait
|
/// returns this as Any trait
|
||||||
fn as_any(&self) -> &dyn Any;
|
fn as_any(&self) -> &dyn Any;
|
||||||
@ -142,8 +142,12 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
finalized: false,
|
finalized: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// This shugar must be used to register all the structs which
|
||||||
|
/// have trait objects that can be serialized and deserialized in the program
|
||||||
pub struct RegistryBuilder {}
|
pub struct RegistryBuilder {}
|
||||||
|
|
||||||
impl RegistryBuilder {
|
impl RegistryBuilder {
|
||||||
|
/// Register a given struct type for trait object (de)serialization
|
||||||
pub fn register<T>()
|
pub fn register<T>()
|
||||||
where
|
where
|
||||||
T: $trait_name + Serialize + serde::de::DeserializeOwned,
|
T: $trait_name + Serialize + serde::de::DeserializeOwned,
|
||||||
@ -153,6 +157,7 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finalize the registry, no more registrations are allowed after this call
|
||||||
pub fn finalize() {
|
pub fn finalize() {
|
||||||
unsafe {
|
unsafe {
|
||||||
REGISTRY.finalize();
|
REGISTRY.finalize();
|
||||||
@ -161,6 +166,8 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
/// A (de)serializable anymap containing (de)serializable trait objects registered
|
||||||
|
/// in the registry
|
||||||
pub struct SerdeAnyMap {
|
pub struct SerdeAnyMap {
|
||||||
map: HashMap<u64, Box<dyn $trait_name>>,
|
map: HashMap<u64, Box<dyn $trait_name>>,
|
||||||
}
|
}
|
||||||
|
@ -488,7 +488,7 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size +1) as u64) as usize;
|
let off = rand.below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + rand.below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
@ -517,7 +517,7 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size +1) as u64) as usize;
|
let off = rand.below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + rand.below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
@ -549,7 +549,7 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size +1) as u64) as usize;
|
let off = rand.below((size + 1) as u64) as usize;
|
||||||
let mut len = 1 + rand.below(16) as usize;
|
let mut len = 1 + rand.below(16) as usize;
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
|
@ -304,8 +304,7 @@ where
|
|||||||
scheduled.add_mutation(mutation_bytesswap);
|
scheduled.add_mutation(mutation_bytesswap);
|
||||||
|
|
||||||
scheduled.add_mutation(mutation_tokeninsert);
|
scheduled.add_mutation(mutation_tokeninsert);
|
||||||
/*scheduled.add_mutation(mutation_tokenreplace);
|
scheduled.add_mutation(mutation_tokenreplace);
|
||||||
*/
|
|
||||||
|
|
||||||
scheduled.add_mutation(mutation_crossover_insert);
|
scheduled.add_mutation(mutation_crossover_insert);
|
||||||
scheduled.add_mutation(mutation_crossover_replace);
|
scheduled.add_mutation(mutation_crossover_replace);
|
||||||
|
@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use mutations::buffer_copy;
|
use mutations::buffer_copy;
|
||||||
|
|
||||||
|
/// A state metadata holding a list of tokens
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct TokensMetadata {
|
pub struct TokensMetadata {
|
||||||
tokens: Vec<Vec<u8>>,
|
tokens: Vec<Vec<u8>>,
|
||||||
@ -32,9 +33,7 @@ impl SerdeAny for TokensMetadata {
|
|||||||
|
|
||||||
impl TokensMetadata {
|
impl TokensMetadata {
|
||||||
pub fn new(tokens: Vec<Vec<u8>>) -> Self {
|
pub fn new(tokens: Vec<Vec<u8>>) -> Self {
|
||||||
Self {
|
Self { tokens: tokens }
|
||||||
tokens: tokens
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +65,7 @@ where
|
|||||||
let token = &meta.tokens[rand.below(meta.tokens.len() as u64) as usize];
|
let token = &meta.tokens[rand.below(meta.tokens.len() as u64) as usize];
|
||||||
|
|
||||||
let size = input.bytes().len();
|
let size = input.bytes().len();
|
||||||
let off = rand.below((size +1) as u64) as usize;
|
let off = rand.below((size + 1) as u64) as usize;
|
||||||
let mut len = token.len();
|
let mut len = token.len();
|
||||||
|
|
||||||
if size + len > mutator.max_size() {
|
if size + len > mutator.max_size() {
|
||||||
@ -88,7 +87,7 @@ where
|
|||||||
pub fn mutation_tokenreplace<I, M, R, S>(
|
pub fn mutation_tokenreplace<I, M, R, S>(
|
||||||
_: &mut M,
|
_: &mut M,
|
||||||
rand: &mut R,
|
rand: &mut R,
|
||||||
state: &S,
|
state: &mut S,
|
||||||
input: &mut I,
|
input: &mut I,
|
||||||
) -> Result<MutationResult, AflError>
|
) -> Result<MutationResult, AflError>
|
||||||
where
|
where
|
||||||
|
340
afl/src/observers/map.rs
Normal file
340
afl/src/observers/map.rs
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
use alloc::string::{String, ToString};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
bolts::{
|
||||||
|
ownedref::{ArrayMut, Cptr},
|
||||||
|
tuples::Named,
|
||||||
|
},
|
||||||
|
observers::Observer,
|
||||||
|
AflError,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
||||||
|
pub trait MapObserver<T>: Observer
|
||||||
|
where
|
||||||
|
T: Default + Copy,
|
||||||
|
{
|
||||||
|
/// Get the map
|
||||||
|
fn map(&self) -> &[T];
|
||||||
|
|
||||||
|
/// Get the map (mutable)
|
||||||
|
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()
|
||||||
|
fn initial(&self) -> T;
|
||||||
|
|
||||||
|
/// Get the initial value for reset()
|
||||||
|
fn initial_mut(&mut self) -> &mut T;
|
||||||
|
|
||||||
|
/// Set the initial value for reset()
|
||||||
|
fn set_initial(&mut self, initial: T);
|
||||||
|
|
||||||
|
/// Reset the map
|
||||||
|
#[inline]
|
||||||
|
fn reset_map(&mut self) -> Result<(), AflError> {
|
||||||
|
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
|
||||||
|
let initial = self.initial();
|
||||||
|
let cnt = self.usable_count();
|
||||||
|
for i in self.map_mut()[0..cnt].iter_mut() {
|
||||||
|
*i = initial;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The Map Observer retrieves the state of a map,
|
||||||
|
/// that will get updated by the target.
|
||||||
|
/// A well-known example is the AFL-Style coverage map.
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
|
pub struct StdMapObserver<T>
|
||||||
|
where
|
||||||
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
{
|
||||||
|
map: ArrayMut<T>,
|
||||||
|
initial: T,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Observer for StdMapObserver<T>
|
||||||
|
where
|
||||||
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self) -> Result<(), AflError> {
|
||||||
|
self.reset_map()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Named for StdMapObserver<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 StdMapObserver<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 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> StdMapObserver<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]) -> Self {
|
||||||
|
let initial = if map.len() > 0 { map[0] } else { T::default() };
|
||||||
|
Self {
|
||||||
|
map: ArrayMut::Cptr((map.as_mut_ptr(), map.len())),
|
||||||
|
name: name.to_string(),
|
||||||
|
initial,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new MapObserver from a raw pointer
|
||||||
|
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::default() };
|
||||||
|
StdMapObserver {
|
||||||
|
map: ArrayMut::Cptr((map_ptr, len)),
|
||||||
|
name: name.to_string(),
|
||||||
|
initial,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Overlooking a variable bitmap
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[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 pre_exec(&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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Map observer with hitcounts postprocessing
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
||||||
|
pub struct HitcountsMapObserver<M>
|
||||||
|
where
|
||||||
|
M: MapObserver<u8>,
|
||||||
|
{
|
||||||
|
base: M,
|
||||||
|
}
|
||||||
|
|
||||||
|
static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
||||||
|
0, 1, 2, 0, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
||||||
|
32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||||
|
64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
|
];
|
||||||
|
|
||||||
|
impl<M> Observer for HitcountsMapObserver<M>
|
||||||
|
where
|
||||||
|
M: MapObserver<u8>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self) -> Result<(), AflError> {
|
||||||
|
self.reset_map()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn post_exec(&mut self) -> Result<(), AflError> {
|
||||||
|
for x in self.map_mut().iter_mut() {
|
||||||
|
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Named for HitcountsMapObserver<M>
|
||||||
|
where
|
||||||
|
M: MapObserver<u8>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
self.base.name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> MapObserver<u8> for HitcountsMapObserver<M>
|
||||||
|
where
|
||||||
|
M: MapObserver<u8>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn map(&self) -> &[u8] {
|
||||||
|
self.base.map()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn map_mut(&mut self) -> &mut [u8] {
|
||||||
|
self.base.map_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn usable_count(&self) -> usize {
|
||||||
|
self.base.usable_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn initial(&self) -> u8 {
|
||||||
|
self.base.initial()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn initial_mut(&mut self) -> &mut u8 {
|
||||||
|
self.base.initial_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_initial(&mut self, initial: u8) {
|
||||||
|
self.base.set_initial(initial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> HitcountsMapObserver<M>
|
||||||
|
where
|
||||||
|
M: MapObserver<u8>,
|
||||||
|
{
|
||||||
|
/// Creates a new MapObserver
|
||||||
|
pub fn new(base: M) -> Self {
|
||||||
|
Self { base: base }
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,12 @@
|
|||||||
extern crate num;
|
pub mod map;
|
||||||
|
pub use map::*;
|
||||||
|
|
||||||
use alloc::{
|
use alloc::string::{String, ToString};
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{
|
bolts::tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
||||||
ownedref::{ArrayMut, Cptr},
|
|
||||||
tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
|
||||||
},
|
|
||||||
utils::current_time,
|
utils::current_time,
|
||||||
AflError,
|
AflError,
|
||||||
};
|
};
|
||||||
@ -152,335 +147,6 @@ impl Named for TimeObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
|
||||||
pub trait MapObserver<T>: Observer
|
|
||||||
where
|
|
||||||
T: Default + Copy,
|
|
||||||
{
|
|
||||||
/// Get the map
|
|
||||||
fn map(&self) -> &[T];
|
|
||||||
|
|
||||||
/// Get the map (mutable)
|
|
||||||
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()
|
|
||||||
fn initial(&self) -> T;
|
|
||||||
|
|
||||||
/// Get the initial value for reset()
|
|
||||||
fn initial_mut(&mut self) -> &mut T;
|
|
||||||
|
|
||||||
/// Set the initial value for reset()
|
|
||||||
fn set_initial(&mut self, initial: T);
|
|
||||||
|
|
||||||
/// Reset the map
|
|
||||||
#[inline]
|
|
||||||
fn reset_map(&mut self) -> Result<(), AflError> {
|
|
||||||
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
|
|
||||||
let initial = self.initial();
|
|
||||||
let cnt = self.usable_count();
|
|
||||||
for i in self.map_mut()[0..cnt].iter_mut() {
|
|
||||||
*i = initial;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The Map Observer retrieves the state of a map,
|
|
||||||
/// that will get updated by the target.
|
|
||||||
/// A well-known example is the AFL-Style coverage map.
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
|
||||||
pub struct StdMapObserver<T>
|
|
||||||
where
|
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
|
||||||
{
|
|
||||||
map: ArrayMut<T>,
|
|
||||||
initial: T,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Observer for StdMapObserver<T>
|
|
||||||
where
|
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec(&mut self) -> Result<(), AflError> {
|
|
||||||
self.reset_map()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Named for StdMapObserver<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 StdMapObserver<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 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> StdMapObserver<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]) -> Self {
|
|
||||||
let initial = if map.len() > 0 { map[0] } else { T::default() };
|
|
||||||
Self {
|
|
||||||
map: ArrayMut::Cptr((map.as_mut_ptr(), map.len())),
|
|
||||||
name: name.to_string(),
|
|
||||||
initial,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new MapObserver from a raw pointer
|
|
||||||
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::default() };
|
|
||||||
StdMapObserver {
|
|
||||||
map: ArrayMut::Cptr((map_ptr, len)),
|
|
||||||
name: name.to_string(),
|
|
||||||
initial,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Overlooking a variable bitmap
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
||||||
#[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 pre_exec(&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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Map observer with hitcounts postprocessing
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
||||||
#[serde(bound = "M: serde::de::DeserializeOwned")]
|
|
||||||
pub struct HitcountsMapObserver<M>
|
|
||||||
where
|
|
||||||
M: MapObserver<u8>,
|
|
||||||
{
|
|
||||||
base: M,
|
|
||||||
}
|
|
||||||
|
|
||||||
static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
|
||||||
0, 1, 2, 0, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
|
||||||
32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
|
||||||
64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
|
||||||
];
|
|
||||||
|
|
||||||
impl<M> Observer for HitcountsMapObserver<M>
|
|
||||||
where
|
|
||||||
M: MapObserver<u8>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec(&mut self) -> Result<(), AflError> {
|
|
||||||
self.reset_map()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn post_exec(&mut self) -> Result<(), AflError> {
|
|
||||||
for x in self.map_mut().iter_mut() {
|
|
||||||
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M> Named for HitcountsMapObserver<M>
|
|
||||||
where
|
|
||||||
M: MapObserver<u8>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn name(&self) -> &str {
|
|
||||||
self.base.name()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M> MapObserver<u8> for HitcountsMapObserver<M>
|
|
||||||
where
|
|
||||||
M: MapObserver<u8>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn map(&self) -> &[u8] {
|
|
||||||
self.base.map()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn map_mut(&mut self) -> &mut [u8] {
|
|
||||||
self.base.map_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn usable_count(&self) -> usize {
|
|
||||||
self.base.usable_count()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn initial(&self) -> u8 {
|
|
||||||
self.base.initial()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn initial_mut(&mut self) -> &mut u8 {
|
|
||||||
self.base.initial_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn set_initial(&mut self, initial: u8) {
|
|
||||||
self.base.set_initial(initial);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M> HitcountsMapObserver<M>
|
|
||||||
where
|
|
||||||
M: MapObserver<u8>,
|
|
||||||
{
|
|
||||||
/// Creates a new MapObserver
|
|
||||||
pub fn new(base: M) -> Self {
|
|
||||||
Self { base: base }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use std::{env, path::PathBuf};
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
use afl::{
|
use afl::{
|
||||||
bolts::{shmem::AflShmem, tuples::tuple_list, serdeany::RegistryBuilder},
|
bolts::{serdeany::RegistryBuilder, shmem::AflShmem, tuples::tuple_list},
|
||||||
corpus::{Corpus, InMemoryCorpus},
|
corpus::{Corpus, InMemoryCorpus},
|
||||||
events::setup_restarting_mgr,
|
events::setup_restarting_mgr,
|
||||||
events::SimpleStats,
|
events::SimpleStats,
|
||||||
@ -92,15 +92,13 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, broker_port: u16) -> Result<(), AflError> {
|
|||||||
|
|
||||||
// Create a PNG dictionary of not existing
|
// Create a PNG dictionary of not existing
|
||||||
if state.metadata().get::<TokensMetadata>().is_none() {
|
if state.metadata().get::<TokensMetadata>().is_none() {
|
||||||
state.add_metadata(TokensMetadata::new(
|
state.add_metadata(TokensMetadata::new(vec![
|
||||||
vec![
|
vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header
|
||||||
vec![137, 80, 78, 71, 13, 10, 26, 10], // PNG header
|
"IHDR".as_bytes().to_vec(),
|
||||||
"IHDR".as_bytes().to_vec(),
|
"IDAT".as_bytes().to_vec(),
|
||||||
"IDAT".as_bytes().to_vec(),
|
"PLTE".as_bytes().to_vec(),
|
||||||
"PLTE".as_bytes().to_vec(),
|
"IEND".as_bytes().to_vec(),
|
||||||
"IEND".as_bytes().to_vec(),
|
]));
|
||||||
]
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a basic mutator with a mutational stage
|
// Setup a basic mutator with a mutational stage
|
||||||
|
Loading…
x
Reference in New Issue
Block a user