added time observer
This commit is contained in:
parent
95fff9d740
commit
db5183d43f
@ -220,7 +220,7 @@ where
|
|||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
executor.reset_observers()?;
|
executor.pre_exec_observers()?;
|
||||||
executor.run_target(&input)?;
|
executor.run_target(&input)?;
|
||||||
self.set_executions(self.executions() + 1);
|
self.set_executions(self.executions() + 1);
|
||||||
executor.post_exec_observers()?;
|
executor.post_exec_observers()?;
|
||||||
|
@ -31,8 +31,8 @@ where
|
|||||||
|
|
||||||
/// Reset the state of all the observes linked to this executor
|
/// Reset the state of all the observes linked to this executor
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reset_observers(&mut self) -> Result<(), AflError> {
|
fn pre_exec_observers(&mut self) -> Result<(), AflError> {
|
||||||
self.observers_mut().reset_all()
|
self.observers_mut().pre_exec_all()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
|
@ -309,6 +309,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: TimeFeedback
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct MapNoveltiesMetadata {
|
pub struct MapNoveltiesMetadata {
|
||||||
|
@ -6,35 +6,6 @@ use crate::{
|
|||||||
AflError,
|
AflError,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The result of a mutation.
|
|
||||||
/// If the mutation got skipped, the target
|
|
||||||
/// will not be executed with the returned input.
|
|
||||||
pub enum MutationResult {
|
|
||||||
Mutated,
|
|
||||||
Skipped,
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO maybe the mutator arg is not needed
|
|
||||||
/// The generic function type that identifies mutations
|
|
||||||
pub type MutationFunction<M, C, I, R> =
|
|
||||||
fn(&mut M, &mut R, &C, &mut I) -> Result<MutationResult, AflError>;
|
|
||||||
|
|
||||||
pub trait ComposedByMutations<C, I, R>
|
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
{
|
|
||||||
/// Get a mutation by index
|
|
||||||
fn mutation_by_idx(&self, index: usize) -> MutationFunction<Self, C, I, R>;
|
|
||||||
|
|
||||||
/// Get the number of mutations
|
|
||||||
fn mutations_count(&self) -> usize;
|
|
||||||
|
|
||||||
/// Add a mutation
|
|
||||||
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ARITH_MAX: u64 = 35;
|
const ARITH_MAX: u64 = 35;
|
||||||
|
|
||||||
const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
const INTERESTING_8: [i8; 9] = [-128, -1, 0, 1, 16, 32, 64, 100, 127];
|
||||||
@ -71,6 +42,36 @@ const INTERESTING_32: [i32; 27] = [
|
|||||||
2147483647,
|
2147483647,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// The result of a mutation.
|
||||||
|
/// If the mutation got skipped, the target
|
||||||
|
/// will not be executed with the returned input.
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum MutationResult {
|
||||||
|
Mutated,
|
||||||
|
Skipped,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO maybe the mutator arg is not needed
|
||||||
|
/// The generic function type that identifies mutations
|
||||||
|
pub type MutationFunction<M, C, I, R> =
|
||||||
|
fn(&mut M, &mut R, &C, &mut I) -> Result<MutationResult, AflError>;
|
||||||
|
|
||||||
|
pub trait ComposedByMutations<C, I, R>
|
||||||
|
where
|
||||||
|
C: Corpus<I, R>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
{
|
||||||
|
/// Get a mutation by index
|
||||||
|
fn mutation_by_idx(&self, index: usize) -> MutationFunction<Self, C, I, R>;
|
||||||
|
|
||||||
|
/// Get the number of mutations
|
||||||
|
fn mutations_count(&self) -> usize;
|
||||||
|
|
||||||
|
/// Add a mutation
|
||||||
|
fn add_mutation(&mut self, mutation: MutationFunction<Self, C, I, R>);
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn self_mem_move(data: &mut [u8], from: usize, to: usize, len: usize) {
|
fn self_mem_move(data: &mut [u8], from: usize, to: usize, len: usize) {
|
||||||
debug_assert!(from + len <= data.len());
|
debug_assert!(from + len <= data.len());
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::marker::PhantomData;
|
use core::{fmt, marker::PhantomData};
|
||||||
|
use fmt::Debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inputs::{HasBytesVec, Input},
|
inputs::{HasBytesVec, Input},
|
||||||
@ -56,6 +57,23 @@ where
|
|||||||
max_size: usize,
|
max_size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<C, I, R> Debug for StdScheduledMutator<C, I, R>
|
||||||
|
where
|
||||||
|
C: Corpus<I, R>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"StdScheduledMutator with {} Mutations, max_size: {}, for Input type {}",
|
||||||
|
self.mutations.len(),
|
||||||
|
self.max_size,
|
||||||
|
core::any::type_name::<I>()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<C, I, R> Mutator<C, I, R> for StdScheduledMutator<C, I, R>
|
impl<C, I, R> Mutator<C, I, R> for StdScheduledMutator<C, I, R>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
|
@ -4,11 +4,13 @@ use alloc::{
|
|||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
use core::time::Duration;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
serde_anymap::{ArrayMut, Cptr},
|
serde_anymap::{ArrayMut, Cptr},
|
||||||
tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
||||||
|
utils::current_time,
|
||||||
AflError,
|
AflError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,7 +24,7 @@ pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'st
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Resets the observer
|
/// Resets the observer
|
||||||
fn reset(&mut self) -> Result<(), AflError>;
|
fn pre_exec(&mut self) -> Result<(), AflError>;
|
||||||
|
|
||||||
/// This function is executed after each fuzz run
|
/// This function is executed after each fuzz run
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -48,11 +50,15 @@ pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned + 'st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A hastkel-style tuple of observers
|
||||||
pub trait ObserversTuple:
|
pub trait ObserversTuple:
|
||||||
MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned
|
MatchNameAndType + MatchType + serde::Serialize + serde::de::DeserializeOwned
|
||||||
{
|
{
|
||||||
/// Reset all executors in the tuple
|
/// Reset all executors in the tuple
|
||||||
fn reset_all(&mut self) -> Result<(), AflError>;
|
/// This is called right before the next execution.
|
||||||
|
fn pre_exec_all(&mut self) -> Result<(), AflError>;
|
||||||
|
/// Do whatever you need to do after a run.
|
||||||
|
/// This is called right after the last execution
|
||||||
fn post_exec_all(&mut self) -> Result<(), AflError>;
|
fn post_exec_all(&mut self) -> Result<(), AflError>;
|
||||||
//fn for_each(&self, f: fn(&dyn Observer));
|
//fn for_each(&self, f: fn(&dyn Observer));
|
||||||
//fn for_each_mut(&mut self, f: fn(&mut dyn Observer));
|
//fn for_each_mut(&mut self, f: fn(&mut dyn Observer));
|
||||||
@ -69,7 +75,7 @@ pub trait ObserversTuple:
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ObserversTuple for () {
|
impl ObserversTuple for () {
|
||||||
fn reset_all(&mut self) -> Result<(), AflError> {
|
fn pre_exec_all(&mut self) -> Result<(), AflError> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn post_exec_all(&mut self) -> Result<(), AflError> {
|
fn post_exec_all(&mut self) -> Result<(), AflError> {
|
||||||
@ -85,9 +91,9 @@ where
|
|||||||
Head: Observer,
|
Head: Observer,
|
||||||
Tail: ObserversTuple + TupleList,
|
Tail: ObserversTuple + TupleList,
|
||||||
{
|
{
|
||||||
fn reset_all(&mut self) -> Result<(), AflError> {
|
fn pre_exec_all(&mut self) -> Result<(), AflError> {
|
||||||
self.0.reset()?;
|
self.0.pre_exec()?;
|
||||||
self.1.reset_all()
|
self.1.pre_exec_all()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec_all(&mut self) -> Result<(), AflError> {
|
fn post_exec_all(&mut self) -> Result<(), AflError> {
|
||||||
@ -106,6 +112,44 @@ where
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A simple observer, just overlooking the runtime of the target.
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct TimeObserver {
|
||||||
|
name: String,
|
||||||
|
start_time: Duration,
|
||||||
|
last_runtime: Option<Duration>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeObserver {
|
||||||
|
/// Creates a new TimeObserver with the given name.
|
||||||
|
pub fn new(name: &'static str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
start_time: Duration::from_secs(0),
|
||||||
|
last_runtime: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Observer for TimeObserver {
|
||||||
|
fn pre_exec(&mut self) -> Result<(), AflError> {
|
||||||
|
self.last_runtime = None;
|
||||||
|
self.start_time = current_time();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec(&mut self) -> Result<(), AflError> {
|
||||||
|
self.last_runtime = Some(current_time() - self.start_time);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for TimeObserver {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
||||||
pub trait MapObserver<T>: Observer
|
pub trait MapObserver<T>: Observer
|
||||||
where
|
where
|
||||||
@ -163,7 +207,7 @@ where
|
|||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reset(&mut self) -> Result<(), AflError> {
|
fn pre_exec(&mut self) -> Result<(), AflError> {
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -235,6 +279,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Overlooking a variable bitmap
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
pub struct VariableMapObserver<T>
|
pub struct VariableMapObserver<T>
|
||||||
@ -252,7 +297,7 @@ where
|
|||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reset(&mut self) -> Result<(), AflError> {
|
fn pre_exec(&mut self) -> Result<(), AflError> {
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,17 +385,23 @@ where
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use crate::observers::StdMapObserver;
|
use crate::{
|
||||||
use crate::tuples::Named;
|
observers::{StdMapObserver, TimeObserver},
|
||||||
|
tuples::{tuple_list, tuple_list_type, Named},
|
||||||
|
};
|
||||||
|
|
||||||
static mut MAP: [u32; 4] = [0; 4];
|
static mut MAP: [u32; 4] = [0; 4];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_observer_serde() {
|
fn test_observer_serde() {
|
||||||
let obv = StdMapObserver::new("test", unsafe { &mut MAP });
|
let obv = tuple_list!(
|
||||||
|
TimeObserver::new("time"),
|
||||||
|
StdMapObserver::new("map", unsafe { &mut MAP })
|
||||||
|
);
|
||||||
let vec = postcard::to_allocvec(&obv).unwrap();
|
let vec = postcard::to_allocvec(&obv).unwrap();
|
||||||
println!("{:?}", vec);
|
println!("{:?}", vec);
|
||||||
let obv2: StdMapObserver<u32> = postcard::from_bytes(&vec).unwrap();
|
let obv2: tuple_list_type!(TimeObserver, StdMapObserver<u32>) =
|
||||||
assert_eq!(obv.name(), obv2.name());
|
postcard::from_bytes(&vec).unwrap();
|
||||||
|
assert_eq!(obv.0.name(), obv2.0.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// We need fixed names for many parts of this lib.
|
||||||
pub trait Named {
|
pub trait Named {
|
||||||
|
/// Provide the name of this element.
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user