fuzzer arg missing atm
This commit is contained in:
parent
95281dbfef
commit
a939f052d3
@ -5,6 +5,7 @@ pub use testcase::Testcase;
|
|||||||
|
|
||||||
use alloc::{vec::Vec};
|
use alloc::{vec::Vec};
|
||||||
use core::{cell::RefCell};
|
use core::{cell::RefCell};
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
@ -101,6 +102,8 @@ impl CorpusScheduler for RandCorpusScheduler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||||
pub struct InMemoryCorpus<I>
|
pub struct InMemoryCorpus<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -108,7 +111,7 @@ where
|
|||||||
entries: Vec<RefCell<Testcase<I>>>,
|
entries: Vec<RefCell<Testcase<I>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, SC> Corpus<I> for InMemoryCorpus<I>
|
impl<I> Corpus<I> for InMemoryCorpus<I>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
@ -151,54 +154,4 @@ where
|
|||||||
fn get(&self, idx: usize) -> Result<&RefCell<Testcase<I>>, Error> {
|
fn get(&self, idx: usize) -> Result<&RefCell<Testcase<I>>, Error> {
|
||||||
Ok(&self.entries[idx])
|
Ok(&self.entries[idx])
|
||||||
}
|
}
|
||||||
|
|
||||||
/*/// Add an entry to the corpus and return its index
|
|
||||||
#[inline]
|
|
||||||
fn add<R, S>(state: &mut S, testcase: Testcase<I>) -> Result<usize, Error>
|
|
||||||
where
|
|
||||||
S: HasCorpus<Self, I> + HasRand<R>,
|
|
||||||
R: Rand
|
|
||||||
{
|
|
||||||
state.corpus_mut().entries.push(RefCell::new(testcase));
|
|
||||||
let idx = state.corpus().entries.len() - 1;
|
|
||||||
// Scheduler hook
|
|
||||||
SC::on_add(state, idx, state.corpus().entries[idx].borrow())?;
|
|
||||||
Ok(idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replaces the testcase at the given idx
|
|
||||||
#[inline]
|
|
||||||
fn replace<R, S>(state: &mut S, idx: usize, testcase: Testcase<I>) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
S: HasCorpus<Self, I> + HasRand<R>,
|
|
||||||
R: Rand
|
|
||||||
{
|
|
||||||
if state.corpus().entries.len() < idx {
|
|
||||||
return Err(Error::KeyNotFound(format!("Index {} out of bounds", idx)));
|
|
||||||
}
|
|
||||||
state.corpus_mut().entries[idx] = RefCell::new(testcase);
|
|
||||||
// Scheduler hook
|
|
||||||
SC::on_replace(state, idx, state.corpus().entries[idx])?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes an entry from the corpus, returning it if it was present.
|
|
||||||
#[inline]
|
|
||||||
fn remove<R, S>(state: &mut S, idx: usize) -> Result<Option<Testcase<I>>, Error>
|
|
||||||
where
|
|
||||||
S: HasCorpus<Self, I> + HasRand<R>,
|
|
||||||
R: Rand
|
|
||||||
{
|
|
||||||
let testcase = match state.corpus_mut()
|
|
||||||
.entries
|
|
||||||
.iter()
|
|
||||||
.position(|x| ptr::eq(x.as_ptr(), entry))
|
|
||||||
{
|
|
||||||
Some(i) => Some(state.corpus_mut().entries.remove(i).into_inner()),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
// Scheduler hook
|
|
||||||
SC::on_remove(state, idx, &testcase)?;
|
|
||||||
Ok(testcase)
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new Testcase instace given an input and a fitness
|
||||||
|
#[inline]
|
||||||
|
pub fn with_fitness(input: I, fitness: u32) -> Self {
|
||||||
|
Testcase {
|
||||||
|
input: Some(input.into()),
|
||||||
|
filename: None,
|
||||||
|
fitness: fitness,
|
||||||
|
metadatas: SerdeAnyMap::new(),
|
||||||
|
exec_time: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn default() -> Self {
|
pub fn default() -> Self {
|
||||||
Testcase {
|
Testcase {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::bolts::llmp::LlmpSender;
|
use crate::bolts::llmp::LlmpSender;
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{string::ToString, vec::Vec};
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::bolts::llmp::LlmpReceiver;
|
use crate::bolts::llmp::LlmpReceiver;
|
||||||
@ -16,16 +17,13 @@ use crate::{
|
|||||||
llmp::{self, LlmpClient, LlmpClientDescription, Tag},
|
llmp::{self, LlmpClient, LlmpClientDescription, Tag},
|
||||||
shmem::ShMem,
|
shmem::ShMem,
|
||||||
},
|
},
|
||||||
corpus::Corpus,
|
|
||||||
events::{BrokerEventResult, Event, EventManager},
|
events::{BrokerEventResult, Event, EventManager},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
feedbacks::FeedbacksTuple,
|
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::State,
|
state::{IfInteresting},
|
||||||
stats::Stats,
|
stats::Stats,
|
||||||
utils::Rand,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -250,21 +248,17 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle arriving events in the client
|
// Handle arriving events in the client
|
||||||
fn handle_in_client<C, E, FT, OC, OFT, OT, R>(
|
fn handle_in_client<E, OT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
sender_id: u32,
|
sender_id: u32,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
_executor: &mut E,
|
_executor: &mut E,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
|
S: IfInteresting<I>
|
||||||
{
|
{
|
||||||
match event {
|
match event {
|
||||||
Event::NewTestcase {
|
Event::NewTestcase {
|
||||||
@ -284,7 +278,7 @@ where
|
|||||||
// TODO include ExitKind in NewTestcase
|
// TODO include ExitKind in NewTestcase
|
||||||
let fitness = state.is_interesting(&input, &observers, ExitKind::Ok)?;
|
let fitness = state.is_interesting(&input, &observers, ExitKind::Ok)?;
|
||||||
if fitness > 0 {
|
if fitness > 0 {
|
||||||
if !state.add_if_interesting(input, fitness)?.is_none() {
|
if !state.add_if_interesting(&input, fitness)?.is_none() {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("Added received Testcase");
|
println!("Added received Testcase");
|
||||||
}
|
}
|
||||||
@ -317,19 +311,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process<C, E, FT, OC, OFT, OT, R>(
|
fn process<E, OT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
|
S: IfInteresting<I>
|
||||||
{
|
{
|
||||||
// TODO: Get around local event copy by moving handle_in_client
|
// TODO: Get around local event copy by moving handle_in_client
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
@ -358,19 +348,11 @@ where
|
|||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fire<C, FT, OC, OFT, R>(
|
fn fire<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error> {
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
let serialized = postcard::to_allocvec(&event)?;
|
let serialized = postcard::to_allocvec(&event)?;
|
||||||
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
|
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -380,17 +362,13 @@ where
|
|||||||
/// Serialize the current state and corpus during an executiont to bytes.
|
/// Serialize the current state and corpus during an executiont to bytes.
|
||||||
/// On top, add the current llmp event manager instance to be restored
|
/// On top, add the current llmp event manager instance to be restored
|
||||||
/// This method is needed when the fuzzer run crashes and has to restart.
|
/// This method is needed when the fuzzer run crashes and has to restart.
|
||||||
pub fn serialize_state_mgr<C, FT, I, OC, OFT, R, SH, ST>(
|
pub fn serialize_state_mgr<I, S, SH, ST>(
|
||||||
state: &State<C, FT, I, OC, OFT, R>,
|
state: &S,
|
||||||
mgr: &LlmpEventManager<I, SH, ST>,
|
mgr: &LlmpEventManager<I, SH, ST>,
|
||||||
) -> Result<Vec<u8>, Error>
|
) -> Result<Vec<u8>, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
S: Serialize,
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
SH: ShMem,
|
SH: ShMem,
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
{
|
{
|
||||||
@ -398,20 +376,16 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
||||||
pub fn deserialize_state_mgr<C, FT, I, OC, OFT, R, SH, ST>(
|
pub fn deserialize_state_mgr<I, S, SH, ST>(
|
||||||
state_corpus_serialized: &[u8],
|
state_corpus_serialized: &[u8],
|
||||||
) -> Result<(State<C, FT, I, OC, OFT, R>, LlmpEventManager<I, SH, ST>), Error>
|
) -> Result<(S, LlmpEventManager<I, SH, ST>), Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
S: DeserializeOwned,
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
SH: ShMem,
|
SH: ShMem,
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
{
|
{
|
||||||
let tuple: (State<C, FT, I, OC, OFT, R>, _) = postcard::from_bytes(&state_corpus_serialized)?;
|
let tuple: (S, _) = postcard::from_bytes(&state_corpus_serialized)?;
|
||||||
Ok((
|
Ok((
|
||||||
tuple.0,
|
tuple.0,
|
||||||
LlmpEventManager::existing_client_from_description(&tuple.1)?,
|
LlmpEventManager::existing_client_from_description(&tuple.1)?,
|
||||||
@ -447,16 +421,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
/// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner.
|
||||||
fn on_restart<C, FT, OC, OFT, R>(
|
fn on_restart<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
S: Serialize,
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
{
|
||||||
// First, reset the page to 0 so the next iteration can read read from the beginning of this page
|
// First, reset the page to 0 so the next iteration can read read from the beginning of this page
|
||||||
unsafe { self.sender.reset() };
|
unsafe { self.sender.reset() };
|
||||||
@ -465,35 +435,24 @@ where
|
|||||||
.send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized)
|
.send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process<C, E, FT, OC, OFT, OT, R>(
|
fn process<E, OT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
|
S: IfInteresting<I>
|
||||||
{
|
{
|
||||||
self.llmp_mgr.process(state, executor)
|
self.llmp_mgr.process(state, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fire<C, FT, OC, OFT, R>(
|
fn fire<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error> {
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
||||||
self.llmp_mgr.fire(state, event)
|
self.llmp_mgr.fire(state, event)
|
||||||
}
|
}
|
||||||
@ -530,24 +489,20 @@ where
|
|||||||
/// A restarting state is a combination of restarter and runner, that can be used on systems without `fork`.
|
/// A restarting state is a combination of restarter and runner, that can be used on systems without `fork`.
|
||||||
/// The restarter will start a new process each time the child crashes or timeouts.
|
/// The restarter will start a new process each time the child crashes or timeouts.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn setup_restarting_mgr<I, C, FT, OC, OFT, R, SH, ST>(
|
pub fn setup_restarting_mgr<I, S, SH, ST>(
|
||||||
//mgr: &mut LlmpEventManager<I, SH, ST>,
|
//mgr: &mut LlmpEventManager<I, SH, ST>,
|
||||||
stats: ST,
|
stats: ST,
|
||||||
broker_port: u16,
|
broker_port: u16,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Option<State<C, FT, I, OC, OFT, R>>,
|
Option<S>,
|
||||||
LlmpRestartingEventManager<I, SH, ST>,
|
LlmpRestartingEventManager<I, SH, ST>,
|
||||||
),
|
),
|
||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I, R>,
|
S: DeserializeOwned,
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
SH: ShMem,
|
SH: ShMem,
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
{
|
{
|
||||||
@ -607,7 +562,7 @@ where
|
|||||||
// Restoring from a previous run, deserialize state and corpus.
|
// Restoring from a previous run, deserialize state and corpus.
|
||||||
Some((_sender, _tag, msg)) => {
|
Some((_sender, _tag, msg)) => {
|
||||||
println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len());
|
println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len());
|
||||||
let (state, mgr): (State<C, FT, I, OC, OFT, R>, LlmpEventManager<I, SH, ST>) =
|
let (state, mgr): (S, LlmpEventManager<I, SH, ST>) =
|
||||||
deserialize_state_mgr(&msg)?;
|
deserialize_state_mgr(&msg)?;
|
||||||
|
|
||||||
(Some(state), LlmpRestartingEventManager::new(mgr, sender))
|
(Some(state), LlmpRestartingEventManager::new(mgr, sender))
|
||||||
|
@ -3,15 +3,10 @@ use alloc::{string::ToString, vec::Vec};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
|
||||||
events::{BrokerEventResult, Event, EventManager},
|
events::{BrokerEventResult, Event, EventManager},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor},
|
||||||
feedbacks::FeedbacksTuple,
|
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
|
||||||
state::State,
|
|
||||||
stats::Stats,
|
stats::Stats,
|
||||||
utils::Rand,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -33,19 +28,13 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
ST: Stats, //CE: CustomEvent<I, OT>,
|
ST: Stats, //CE: CustomEvent<I, OT>,
|
||||||
{
|
{
|
||||||
fn process<C, E, FT, OC, OFT, OT, R>(
|
fn process<E, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
_executor: &mut E,
|
_executor: &mut E,
|
||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
E: Executor<I>
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
{
|
||||||
let count = self.events.len();
|
let count = self.events.len();
|
||||||
while self.events.len() > 0 {
|
while self.events.len() > 0 {
|
||||||
@ -55,17 +44,11 @@ where
|
|||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fire<C, FT, OC, OFT, R>(
|
fn fire<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
{
|
||||||
match Self::handle_in_broker(&mut self.stats, &event)? {
|
match Self::handle_in_broker(&mut self.stats, &event)? {
|
||||||
BrokerEventResult::Forward => self.events.push(event),
|
BrokerEventResult::Forward => self.events.push(event),
|
||||||
@ -132,18 +115,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle arriving events in the client
|
// Handle arriving events in the client
|
||||||
fn handle_in_client<C, FT, OC, OFT, R>(
|
fn handle_in_client<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error> {
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
match event {
|
match event {
|
||||||
_ => Err(Error::Unknown(format!(
|
_ => Err(Error::Unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {:?}.",
|
"Received illegal message that message should not have arrived: {:?}.",
|
||||||
|
@ -9,13 +9,9 @@ use core::{fmt, marker::PhantomData, time::Duration};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
executors::{Executor},
|
||||||
executors::{Executor, HasObservers},
|
|
||||||
feedbacks::FeedbacksTuple,
|
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::State,
|
|
||||||
utils::Rand,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -162,19 +158,13 @@ where
|
|||||||
|
|
||||||
/// Lookup for incoming events and process them.
|
/// Lookup for incoming events and process them.
|
||||||
/// Return the number of processes events or an error
|
/// Return the number of processes events or an error
|
||||||
fn process<C, E, FT, OC, OFT, OT, R>(
|
fn process<E, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
E: Executor<I>;
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple;
|
|
||||||
|
|
||||||
/// Serialize all observers for this type and manager
|
/// Serialize all observers for this type and manager
|
||||||
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
||||||
@ -194,17 +184,10 @@ where
|
|||||||
|
|
||||||
/// For restarting event managers, implement a way to forward state to their next peers.
|
/// For restarting event managers, implement a way to forward state to their next peers.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn on_restart<C, FT, OC, OFT, R>(
|
fn on_restart<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error> {
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,17 +196,11 @@ where
|
|||||||
fn await_restart_safe(&mut self) {}
|
fn await_restart_safe(&mut self) {}
|
||||||
|
|
||||||
/// Send off an event to the broker
|
/// Send off an event to the broker
|
||||||
fn fire<C, FT, OC, OFT, R>(
|
fn fire<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>;
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An eventmgr for tests, and as placeholder if you really don't need an event manager.
|
/// An eventmgr for tests, and as placeholder if you really don't need an event manager.
|
||||||
@ -235,35 +212,22 @@ impl<I> EventManager<I> for NopEventManager<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn process<C, E, FT, OC, OFT, OT, R>(
|
fn process<E, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
_executor: &mut E,
|
_executor: &mut E,
|
||||||
) -> Result<usize, Error>
|
) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
E: Executor<I>,
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
{
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fire<C, FT, OC, OFT, R>(
|
fn fire<S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
_event: Event<I>,
|
_event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error> {
|
||||||
where
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
R: Rand,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,52 +54,42 @@ where
|
|||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec<C, EM, FT, OC, OFT, R>(
|
fn pre_exec<EM, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
_event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
_input: &I,
|
input: &I,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
unsafe {
|
unsafe {
|
||||||
set_oncrash_ptrs::<C, EM, FT, I, OC, OFT, OT, R>(
|
set_oncrash_ptrs(
|
||||||
_state,
|
state,
|
||||||
_event_mgr,
|
event_mgr,
|
||||||
self.observers(),
|
self.observers(),
|
||||||
_input,
|
input,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec<C, EM, FT, OC, OFT, R>(
|
fn post_exec<EM, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &State<C, FT, I, OC, OFT, R>,
|
_state: &S,
|
||||||
_event_mgr: &mut EM,
|
_event_mgr: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
unsafe {
|
unsafe {
|
||||||
reset_oncrash_ptrs::<C, EM, FT, I, OT, R>();
|
reset_oncrash_ptrs();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -148,8 +138,6 @@ where
|
|||||||
/// depnding on different corpus or state.
|
/// depnding on different corpus or state.
|
||||||
/// * `name` - the name of this executor (to address it along the way)
|
/// * `name` - the name of this executor (to address it along the way)
|
||||||
/// * `harness_fn` - the harness, executiong the function
|
/// * `harness_fn` - the harness, executiong the function
|
||||||
/// * `on_crash_fn` - When an in-mem harness crashes, it may safe some state to continue fuzzing later.
|
|
||||||
/// Do that that in this function. The program will crash afterwards.
|
|
||||||
/// * `observers` - the observers observing the target during execution
|
/// * `observers` - the observers observing the target during execution
|
||||||
pub fn new<C, EM, FT, OC, OFT, R>(
|
pub fn new<C, EM, FT, OC, OFT, R>(
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
@ -161,9 +149,9 @@ where
|
|||||||
where
|
where
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
OC: Corpus<I, R>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -181,25 +169,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
unsafe fn tidy_up_on_exit<EM>(mgr: &EM)
|
|
||||||
where
|
|
||||||
EM: EventManager<I>,
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
|
|
||||||
match manager.llmp {
|
|
||||||
IsClient { client } => {
|
|
||||||
let map = client.out_maps.last().unwrap();
|
|
||||||
/// wait until we can drop the message safely.
|
|
||||||
map.await_save_to_unmap_blocking();
|
|
||||||
/// Make sure all pages are unmapped.
|
|
||||||
drop(manager);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub mod unix_signals {
|
pub mod unix_signals {
|
||||||
@ -242,15 +211,15 @@ pub mod unix_signals {
|
|||||||
/// This is needed for certain non-rust side effects, as well as unix signal handling.
|
/// This is needed for certain non-rust side effects, as well as unix signal handling.
|
||||||
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
|
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
|
||||||
|
|
||||||
pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<C, EM, FT, I, OC, OFT, OT, R>(
|
unsafe fn inmem_handle_crash<C, EM, FT, I, OC, OFT, OT, R>(
|
||||||
_sig: c_int,
|
_sig: c_int,
|
||||||
info: siginfo_t,
|
info: siginfo_t,
|
||||||
_void: c_void,
|
_void: c_void,
|
||||||
) where
|
) where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
OC: Corpus<I, R>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -324,14 +293,14 @@ pub mod unix_signals {
|
|||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe extern "C" fn libaflrs_executor_inmem_handle_timeout<C, EM, FT, I, OC, OFT, OT, R>(
|
unsafe fn inmem_handle_timeout<C, EM, FT, I, OC, OFT, OT, R>(
|
||||||
_sig: c_int,
|
_sig: c_int,
|
||||||
_info: siginfo_t,
|
_info: siginfo_t,
|
||||||
_void: c_void,
|
_void: c_void,
|
||||||
) where
|
) where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
OC: Corpus<I, R>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
@ -384,21 +353,12 @@ pub mod unix_signals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn set_oncrash_ptrs<C, EM, FT, I, OC, OFT, OT, R>(
|
pub unsafe fn set_oncrash_ptrs<EM, I, OT, S>(
|
||||||
state: &mut State<C, FT, I, OC, OFT, R>,
|
state: &mut S,
|
||||||
event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
input: &I,
|
input: &I,
|
||||||
) where
|
) {
|
||||||
EM: EventManager<I>,
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
{
|
|
||||||
CURRENT_INPUT_PTR = input as *const _ as *const c_void;
|
CURRENT_INPUT_PTR = input as *const _ as *const c_void;
|
||||||
STATE_PTR = state as *mut _ as *mut c_void;
|
STATE_PTR = state as *mut _ as *mut c_void;
|
||||||
EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
|
EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
|
||||||
@ -406,19 +366,18 @@ pub mod unix_signals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn reset_oncrash_ptrs<C, EM, FT, I, OT, R>() {
|
pub unsafe fn reset_oncrash_ptrs() {
|
||||||
CURRENT_INPUT_PTR = ptr::null();
|
CURRENT_INPUT_PTR = ptr::null();
|
||||||
STATE_PTR = ptr::null_mut();
|
STATE_PTR = ptr::null_mut();
|
||||||
EVENT_MGR_PTR = ptr::null_mut();
|
EVENT_MGR_PTR = ptr::null_mut();
|
||||||
OBSERVERS_PTR = ptr::null_mut();
|
OBSERVERS_PTR = ptr::null();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO clearly state that manager should be static (maybe put the 'static lifetime?)
|
|
||||||
pub unsafe fn setup_crash_handlers<C, EM, FT, I, OC, OFT, OT, R>()
|
pub unsafe fn setup_crash_handlers<C, EM, FT, I, OC, OFT, OT, R>()
|
||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I>,
|
||||||
OC: Corpus<I, R>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
@ -441,7 +400,7 @@ pub mod unix_signals {
|
|||||||
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
|
libc::sigemptyset(&mut sa.sa_mask as *mut libc::sigset_t);
|
||||||
sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
|
sa.sa_flags = SA_NODEFER | SA_SIGINFO | SA_ONSTACK;
|
||||||
sa.sa_sigaction =
|
sa.sa_sigaction =
|
||||||
libaflrs_executor_inmem_handle_crash::<C, EM, FT, I, OC, OFT, OT, R> as usize;
|
inmem_handle_crash::<C, EM, FT, I, OC, OFT, OT, R> as usize;
|
||||||
for (sig, msg) in &[
|
for (sig, msg) in &[
|
||||||
(SIGSEGV, "segfault"),
|
(SIGSEGV, "segfault"),
|
||||||
(SIGBUS, "sigbus"),
|
(SIGBUS, "sigbus"),
|
||||||
@ -456,7 +415,7 @@ pub mod unix_signals {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sa.sa_sigaction =
|
sa.sa_sigaction =
|
||||||
libaflrs_executor_inmem_handle_timeout::<C, EM, FT, I, OC, OFT, OT, R> as usize;
|
inmem_handle_timeout::<C, EM, FT, I, OC, OFT, OT, R> as usize;
|
||||||
if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 {
|
if sigaction(SIGUSR2, &mut sa as *mut sigaction, ptr::null_mut()) < 0 {
|
||||||
panic!("Could not set up sigusr2 handler for timeouts");
|
panic!("Could not set up sigusr2 handler for timeouts");
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,9 @@ use core::marker::PhantomData;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
bolts::tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
||||||
corpus::Corpus,
|
|
||||||
events::EventManager,
|
events::EventManager,
|
||||||
feedbacks::FeedbacksTuple,
|
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::State,
|
|
||||||
utils::Rand,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -84,18 +80,13 @@ where
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Called right before exexution starts
|
/// Called right before exexution starts
|
||||||
fn pre_exec<C, EM, FT, OC, OFT, R>(
|
fn pre_exec<EM, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut State<C, FT, I, OC, OFT, R>,
|
_state: &mut S,
|
||||||
_event_mgr: &mut EM,
|
_event_mgr: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -103,18 +94,13 @@ where
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Called right after execution finished.
|
/// Called right after execution finished.
|
||||||
fn post_exec<C, EM, FT, OC, OFT, R>(
|
fn post_exec<EM, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &State<C, FT, I, OC, OFT, R>,
|
_state: &S,
|
||||||
_event_mgr: &mut EM,
|
_event_mgr: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
C: Corpus<I, R>,
|
|
||||||
OC: Corpus<I, R>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
{
|
{
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6,7 +6,7 @@ use crate::{
|
|||||||
executors::{Executor},
|
executors::{Executor},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
stages::StagesTuple,
|
stages::StagesTuple,
|
||||||
state::{HasRand, HasCorpus},
|
state::{HasRand, HasCorpus, HasExecutions},
|
||||||
utils::{Rand, current_milliseconds, current_time},
|
utils::{Rand, current_milliseconds, current_time},
|
||||||
Error
|
Error
|
||||||
};
|
};
|
||||||
@ -70,6 +70,7 @@ where
|
|||||||
{
|
{
|
||||||
scheduler: CS,
|
scheduler: CS,
|
||||||
stages: ST,
|
stages: ST,
|
||||||
|
phantom: PhantomData<I>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CS, ST, I> HasStages<ST, I> for StdFuzzer<CS, ST, I>
|
impl<CS, ST, I> HasStages<ST, I> for StdFuzzer<CS, ST, I>
|
||||||
@ -139,7 +140,7 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
S: HasCorpus<C, I> + HasRand<R>,
|
S: HasCorpus<C, I> + HasRand<R> + HasExecutions,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
R: Rand
|
R: Rand
|
||||||
{
|
{
|
||||||
@ -152,7 +153,7 @@ where
|
|||||||
manager.fire(
|
manager.fire(
|
||||||
state,
|
state,
|
||||||
Event::UpdateStats {
|
Event::UpdateStats {
|
||||||
executions: state.executions(),
|
executions: *state.executions(),
|
||||||
time: current_time(),
|
time: current_time(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
},
|
},
|
||||||
@ -173,6 +174,7 @@ where
|
|||||||
Self {
|
Self {
|
||||||
scheduler: scheduler,
|
scheduler: scheduler,
|
||||||
stages: stages,
|
stages: stages,
|
||||||
|
phantom: PhantomData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@ impl From<ParseIntError> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// TODO: no_std test
|
// TODO: no_std test
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -198,3 +199,4 @@ mod tests {
|
|||||||
assert_eq!(state.corpus().count(), corpus_deserialized.count());
|
assert_eq!(state.corpus().count(), corpus_deserialized.count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
@ -175,7 +175,7 @@ where
|
|||||||
R: Rand,
|
R: Rand,
|
||||||
{
|
{
|
||||||
scheduled: SM,
|
scheduled: SM,
|
||||||
phantom: PhantomData<(I, R, S)>,
|
phantom: PhantomData<(C, I, R, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S, SM> Mutator<I> for HavocBytesMutator<C, I, R, S, SM>
|
impl<C, I, R, S, SM> Mutator<I> for HavocBytesMutator<C, I, R, S, SM>
|
||||||
@ -258,9 +258,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, I, R, S, SM> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
|
impl<C, I, R, S> Default for HavocBytesMutator<C, I, R, S, StdScheduledMutator<I, R, S>>
|
||||||
where
|
where
|
||||||
SM: ScheduledMutator<I, S> + HasMaxSize,
|
|
||||||
I: Input + HasBytesVec,
|
I: Input + HasBytesVec,
|
||||||
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
S: HasRand<R> + HasCorpus<C, I> + HasMetadata,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
inputs::{HasBytesVec, Input},
|
inputs::{HasBytesVec, Input},
|
||||||
state::{HasRand, HasCorpus, HasMetadata},
|
state::{HasRand, HasMetadata},
|
||||||
mutators::*,
|
mutators::*,
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
Error,
|
Error,
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
stages::Stage,
|
stages::Stage,
|
||||||
state::{HasRand},
|
state::{HasRand},
|
||||||
utils::Rand,
|
utils::Rand,
|
||||||
state::HasCorpus,
|
state::{HasCorpus, Evaluator},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
S: HasCorpus<C, I>,
|
S: HasCorpus<C, I> + Evaluator<I>,
|
||||||
C: Corpus<I>
|
C: Corpus<I>
|
||||||
{
|
{
|
||||||
let num = self.iterations(state);
|
let num = self.iterations(state);
|
||||||
@ -57,7 +57,7 @@ where
|
|||||||
self.mutator_mut()
|
self.mutator_mut()
|
||||||
.mutate(state, &mut input_mut, i as i32)?;
|
.mutate(state, &mut input_mut, i as i32)?;
|
||||||
|
|
||||||
let fitness = state.process_input(input_mut, executor, manager)?;
|
let fitness = state.evaluate_input(input_mut, executor, manager)?;
|
||||||
|
|
||||||
self.mutator_mut().post_exec(state, fitness, i as i32)?;
|
self.mutator_mut().post_exec(state, fitness, i as i32)?;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventManager<I>,
|
EM: EventManager<I>,
|
||||||
E: Executor<I>,
|
E: Executor<I>,
|
||||||
S: HasCorpus<C, I>,
|
S: HasCorpus<C, I> + Evaluator<I>,
|
||||||
C: Corpus<I>
|
C: Corpus<I>
|
||||||
{
|
{
|
||||||
self.perform_mutational(executor, state, manager, corpus_idx)
|
self.perform_mutational(executor, state, manager, corpus_idx)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! The fuzzer, and state are the core pieces of every good fuzzer
|
//! The fuzzer, and state are the core pieces of every good fuzzer
|
||||||
|
|
||||||
use core::{fmt::Debug, marker::PhantomData};
|
use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{
|
use std::{
|
||||||
@ -36,6 +36,18 @@ where
|
|||||||
fn corpus_mut(&mut self) -> &mut C;
|
fn corpus_mut(&mut self) -> &mut C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for elements offering a corpus of solutions
|
||||||
|
pub trait HasSolutions<C, I>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
/// The solutions corpus
|
||||||
|
fn solutions(&self) -> &C;
|
||||||
|
/// The solutions corpus (mut)
|
||||||
|
fn solutions_mut(&mut self) -> &mut C;
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait for elements offering a rand
|
/// Trait for elements offering a rand
|
||||||
pub trait HasRand<R>
|
pub trait HasRand<R>
|
||||||
where
|
where
|
||||||
@ -64,46 +76,409 @@ pub trait HasMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for elements offering a feedbacks tuple
|
||||||
|
pub trait HasFeedbacks<FT, I>
|
||||||
|
where
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
I: Input
|
||||||
|
{
|
||||||
|
/// The feedbacks tuple
|
||||||
|
fn feedbacks(&self) -> &FT;
|
||||||
|
|
||||||
|
/// The feedbacks tuple (mut)
|
||||||
|
fn feedbacks_mut(&mut self) -> &mut FT;
|
||||||
|
|
||||||
|
/// Resets all metadata holds by feedbacks
|
||||||
|
#[inline]
|
||||||
|
fn discard_feedbacks_metadata(&mut self, input: &I) -> Result<(), Error> {
|
||||||
|
// TODO: This could probably be automatic in the feedback somehow?
|
||||||
|
self.feedbacks_mut().discard_metadata_all(&input)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new testcase, appending the metadata from each feedback
|
||||||
|
#[inline]
|
||||||
|
fn testcase_with_feedbacks_metadata(&mut self, input: I, fitness: u32) -> Result<Testcase<I>, Error> {
|
||||||
|
let mut testcase = Testcase::with_fitness(input, fitness);
|
||||||
|
self.feedbacks_mut().append_metadata_all(&mut testcase)?;
|
||||||
|
Ok(testcase)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for elements offering an objective feedbacks tuple
|
||||||
|
pub trait HasObjectives<FT, I>
|
||||||
|
where
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
I: Input
|
||||||
|
{
|
||||||
|
/// The objective feedbacks tuple
|
||||||
|
fn objectives(&self) -> &FT;
|
||||||
|
|
||||||
|
/// The objective feedbacks tuple (mut)
|
||||||
|
fn objectives_mut(&mut self) -> &mut FT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for the execution counter
|
||||||
|
pub trait HasExecutions
|
||||||
|
{
|
||||||
|
/// The executions counter
|
||||||
|
fn executions(&self) -> &usize;
|
||||||
|
|
||||||
|
/// The executions counter (mut)
|
||||||
|
fn executions_mut(&mut self) -> &mut usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for the starting time
|
||||||
|
pub trait HasStartTime
|
||||||
|
{
|
||||||
|
/// The starting time
|
||||||
|
fn start_time(&self) -> &Duration;
|
||||||
|
|
||||||
|
/// The starting time (mut)
|
||||||
|
fn start_time_mut(&mut self) -> &mut Duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add to the state if interesting
|
||||||
|
pub trait IfInteresting<I>
|
||||||
|
where
|
||||||
|
I: Input
|
||||||
|
{
|
||||||
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
|
fn is_interesting<OT>(
|
||||||
|
&mut self,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: ExitKind,
|
||||||
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple;
|
||||||
|
|
||||||
|
/// Adds this input to the corpus, if it's intersting, and return the index
|
||||||
|
fn add_if_interesting(&mut self, input: &I, fitness: u32) -> Result<Option<usize>, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Evaluate an input modyfing the state of the fuzzer and returning a fitness
|
||||||
|
pub trait Evaluator<I>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
/// Runs the input and triggers observers and feedback
|
||||||
|
fn evaluate_input<E, EM>(
|
||||||
|
&mut self,
|
||||||
|
input: I,
|
||||||
|
executor: &mut E,
|
||||||
|
event_mgr: &mut EM,
|
||||||
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
E: Executor<I>,
|
||||||
|
EM: EventManager<I>;
|
||||||
|
}
|
||||||
|
|
||||||
/// The state a fuzz run.
|
/// The state a fuzz run.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
||||||
pub struct State<C, FT, I, OC, OFT, R>
|
pub struct State<C, FT, I, OFT, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
OC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
{
|
{
|
||||||
/// RNG instance
|
/// RNG instance
|
||||||
rand: R,
|
rand: R,
|
||||||
/// How many times the executor ran the harness/target
|
/// How many times the executor ran the harness/target
|
||||||
executions: usize,
|
executions: usize,
|
||||||
|
/// At what time the fuzzing started
|
||||||
|
start_time: Duration,
|
||||||
/// The corpus
|
/// The corpus
|
||||||
corpus: C,
|
corpus: C,
|
||||||
// TODO use Duration
|
|
||||||
/// At what time the fuzzing started
|
|
||||||
start_time: u64,
|
|
||||||
/// Metadata stored for this state by one of the components
|
|
||||||
metadata: SerdeAnyMap,
|
|
||||||
/// Feedbacks used to evaluate an input
|
/// Feedbacks used to evaluate an input
|
||||||
feedbacks: FT,
|
feedbacks: FT,
|
||||||
// Objective corpus
|
// Solutions corpus
|
||||||
objective_corpus: OC,
|
solutions: SC,
|
||||||
/// Objective Feedbacks
|
/// Objective Feedbacks
|
||||||
objective_feedbacks: OFT,
|
objectives: OFT,
|
||||||
|
/// Metadata stored for this state by one of the components
|
||||||
|
metadata: SerdeAnyMap,
|
||||||
|
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasRand<R> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// The rand instance
|
||||||
|
#[inline]
|
||||||
|
fn rand(&self) -> &R {
|
||||||
|
&self.rand
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The rand instance (mut)
|
||||||
|
#[inline]
|
||||||
|
fn rand_mut(&mut self) -> &mut R {
|
||||||
|
&mut self.rand
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasCorpus<C, I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// Returns the corpus
|
||||||
|
#[inline]
|
||||||
|
fn corpus(&self) -> &C {
|
||||||
|
&self.corpus
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the mutable corpus
|
||||||
|
#[inline]
|
||||||
|
fn corpus_mut(&mut self) -> &mut C {
|
||||||
|
&mut self.corpus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasSolutions<SC, I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// Returns the solutions corpus
|
||||||
|
#[inline]
|
||||||
|
fn solutions(&self) -> &SC {
|
||||||
|
&self.solutions
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the solutions corpus (mut)
|
||||||
|
#[inline]
|
||||||
|
fn solutions_mut(&mut self) -> &mut SC {
|
||||||
|
&mut self.solutions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasMetadata for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// Get all the metadata into an HashMap
|
||||||
|
#[inline]
|
||||||
|
fn metadata(&self) -> &SerdeAnyMap {
|
||||||
|
&self.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get all the metadata into an HashMap (mutable)
|
||||||
|
#[inline]
|
||||||
|
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
|
||||||
|
&mut self.metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasFeedbacks<FT, I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// The feedbacks tuple
|
||||||
|
#[inline]
|
||||||
|
fn feedbacks(&self) -> &FT {
|
||||||
|
&self.feedbacks
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The feedbacks tuple (mut)
|
||||||
|
#[inline]
|
||||||
|
fn feedbacks_mut(&mut self) -> &mut FT {
|
||||||
|
&mut self.feedbacks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasObjectives<OFT, I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// The objective feedbacks tuple
|
||||||
|
#[inline]
|
||||||
|
fn objectives(&self) -> &OFT {
|
||||||
|
&self.objectives
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The objective feedbacks tuple (mut)
|
||||||
|
#[inline]
|
||||||
|
fn objectives_mut(&mut self) -> &mut OFT {
|
||||||
|
&mut self.objectives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasExecutions for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// The executions counter
|
||||||
|
#[inline]
|
||||||
|
fn executions(&self) -> &usize {
|
||||||
|
&self.executions
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The executions counter (mut)
|
||||||
|
#[inline]
|
||||||
|
fn executions_mut(&mut self) -> &mut usize {
|
||||||
|
&mut self.executions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> HasStartTime for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// The starting time
|
||||||
|
#[inline]
|
||||||
|
fn start_time(&self) -> &Duration {
|
||||||
|
&self.start_time
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The starting time (mut)
|
||||||
|
#[inline]
|
||||||
|
fn start_time_mut(&mut self) -> &mut Duration {
|
||||||
|
&mut self.start_time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> IfInteresting<I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
|
fn is_interesting<OT>(
|
||||||
|
&mut self,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: ExitKind,
|
||||||
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
Ok(self
|
||||||
|
.feedbacks_mut()
|
||||||
|
.is_interesting_all(input, observers, exit_kind)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds this input to the corpus, if it's intersting, and return the index
|
||||||
|
#[inline]
|
||||||
|
fn add_if_interesting(&mut self, input: &I, fitness: u32) -> Result<Option<usize>, Error> {
|
||||||
|
if fitness > 0 {
|
||||||
|
let testcase = self.testcase_with_feedbacks_metadata(input.clone(), fitness)?;
|
||||||
|
Ok(Some(self.corpus.add(testcase)?)) // TODO scheduler hook
|
||||||
|
} else {
|
||||||
|
self.discard_feedbacks_metadata(input)?;
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> Evaluator<I> for State<C, FT, I, OFT, R, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
I: Input,
|
||||||
|
R: Rand,
|
||||||
|
FT: FeedbacksTuple<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
OFT: FeedbacksTuple<I>,
|
||||||
|
{
|
||||||
|
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
||||||
|
#[inline]
|
||||||
|
fn evaluate_input<E, EM, OT>(
|
||||||
|
&mut self,
|
||||||
|
// TODO probably we can take a ref to input and pass a cloned one to add_if_interesting
|
||||||
|
input: I,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
) -> Result<u32, Error>
|
||||||
|
where
|
||||||
|
E: Executor<I> + HasObservers<OT>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
C: Corpus<I>,
|
||||||
|
EM: EventManager<I>,
|
||||||
|
{
|
||||||
|
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
|
||||||
|
let observers = executor.observers();
|
||||||
|
|
||||||
|
if is_solution {
|
||||||
|
// If the input is a solution, add it to the respective corpus
|
||||||
|
self.solutions_mut().add(Testcase::new(input.clone()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let idx = Some(self.add_if_interesting(&input, fitness)?) {
|
||||||
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
|
manager.fire(
|
||||||
|
self,
|
||||||
|
Event::NewTestcase {
|
||||||
|
input: input,
|
||||||
|
observers_buf,
|
||||||
|
corpus_size: self.corpus().count() + 1,
|
||||||
|
client_config: "TODO".into(),
|
||||||
|
time: crate::utils::current_time(),
|
||||||
|
executions: *self.executions(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(fitness)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<C, FT, OC, OFT, R> State<C, FT, BytesInput, OC, OFT, R>
|
impl<C, FT, OFT, R, SC> State<C, FT, BytesInput, OFT, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<BytesInput>,
|
C: Corpus<BytesInput>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<BytesInput>,
|
FT: FeedbacksTuple<BytesInput>,
|
||||||
OC: Corpus<BytesInput>,
|
SC: Corpus<BytesInput>,
|
||||||
OFT: FeedbacksTuple<BytesInput>,
|
OFT: FeedbacksTuple<BytesInput>,
|
||||||
{
|
{
|
||||||
pub fn load_from_directory<E, OT, EM>(
|
pub fn load_from_directory<E, OT, EM>(
|
||||||
@ -133,12 +508,12 @@ where
|
|||||||
println!("Loading file {:?} ...", &path);
|
println!("Loading file {:?} ...", &path);
|
||||||
let bytes = fs::read(&path)?;
|
let bytes = fs::read(&path)?;
|
||||||
let input = BytesInput::new(bytes);
|
let input = BytesInput::new(bytes);
|
||||||
let (fitness, obj_fitness) = self.evaluate_input(&input, executor, manager)?;
|
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
|
||||||
if self.add_if_interesting(input, fitness)?.is_none() {
|
if self.add_if_interesting(&input, fitness)?.is_none() {
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
println!("File {:?} was not interesting, skipped.", &path);
|
||||||
}
|
}
|
||||||
if obj_fitness > 0 {
|
if is_solution {
|
||||||
println!("File {:?} is an objective, however will be not added as an initial testcase.", &path);
|
println!("File {:?} is a solution, however will be not considered as it is an initial testcase.", &path);
|
||||||
}
|
}
|
||||||
} else if attr.is_dir() {
|
} else if attr.is_dir() {
|
||||||
self.load_from_directory(executor, manager, &path)?;
|
self.load_from_directory(executor, manager, &path)?;
|
||||||
@ -176,159 +551,23 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OC, OFT, R> HasRand<R> for State<C, FT, I, OC, OFT, R>
|
|
||||||
|
impl<C, FT, I, OFT, R, SC> State<C, FT, I, OFT, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
FT: FeedbacksTuple<I>,
|
||||||
OC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OFT: FeedbacksTuple<I>,
|
||||||
{
|
{
|
||||||
/// The rand instance
|
|
||||||
fn rand(&self) -> &R {
|
|
||||||
&self.rand
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The rand instance (mut)
|
|
||||||
fn rand_mut(&mut self) -> &mut R {
|
|
||||||
&mut self.rand
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl<C, FT, I, OC, OFT, R> HasCorpus<C, I> for State<C, FT, I, OC, OFT, R>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
OC: Corpus<I>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
/// Returns the corpus
|
|
||||||
fn corpus(&self) -> &C {
|
|
||||||
&self.corpus
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the mutable corpus
|
|
||||||
fn corpus_mut(&mut self) -> &mut C {
|
|
||||||
&mut self.corpus
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for elements offering metadata
|
|
||||||
impl<C, FT, I, OC, OFT, R> HasMetadata for State<C, FT, I, OC, OFT, R>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
OC: Corpus<I>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
/// Get all the metadata into an HashMap
|
|
||||||
#[inline]
|
|
||||||
fn metadata(&self) -> &SerdeAnyMap {
|
|
||||||
&self.metadata
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get all the metadata into an HashMap (mutable)
|
|
||||||
#[inline]
|
|
||||||
fn metadata_mut(&mut self) -> &mut SerdeAnyMap {
|
|
||||||
&mut self.metadata
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, FT, I, OC, OFT, R> State<C, FT, I, OC, OFT, R>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
I: Input,
|
|
||||||
R: Rand,
|
|
||||||
FT: FeedbacksTuple<I>,
|
|
||||||
OC: Corpus<I>,
|
|
||||||
OFT: FeedbacksTuple<I>,
|
|
||||||
{
|
|
||||||
/// Get executions
|
|
||||||
#[inline]
|
|
||||||
pub fn executions(&self) -> usize {
|
|
||||||
self.executions
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set executions
|
|
||||||
#[inline]
|
|
||||||
pub fn set_executions(&mut self, executions: usize) {
|
|
||||||
self.executions = executions
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn start_time(&self) -> u64 {
|
|
||||||
self.start_time
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
pub fn set_start_time(&mut self, ms: u64) {
|
|
||||||
self.start_time = ms
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns vector of feebacks
|
|
||||||
#[inline]
|
|
||||||
pub fn feedbacks(&self) -> &FT {
|
|
||||||
&self.feedbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns vector of feebacks (mutable)
|
|
||||||
#[inline]
|
|
||||||
pub fn feedbacks_mut(&mut self) -> &mut FT {
|
|
||||||
&mut self.feedbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns vector of objective feebacks
|
|
||||||
#[inline]
|
|
||||||
pub fn objective_feedbacks(&self) -> &OFT {
|
|
||||||
&self.objective_feedbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns vector of objective feebacks (mutable)
|
|
||||||
#[inline]
|
|
||||||
pub fn objective_feedbacks_mut(&mut self) -> &mut OFT {
|
|
||||||
&mut self.objective_feedbacks
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the objective corpus
|
|
||||||
#[inline]
|
|
||||||
pub fn objective_corpus(&self) -> &OC {
|
|
||||||
&self.objective_corpus
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the mutable objective corpus
|
|
||||||
#[inline]
|
|
||||||
pub fn objective_corpus_mut(&mut self) -> &mut OC {
|
|
||||||
&mut self.objective_corpus
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO move some of these, like evaluate_input, to FuzzingEngine
|
|
||||||
#[inline]
|
|
||||||
pub fn is_interesting<OT>(
|
|
||||||
&mut self,
|
|
||||||
input: &I,
|
|
||||||
observers: &OT,
|
|
||||||
exit_kind: ExitKind,
|
|
||||||
) -> Result<u32, Error>
|
|
||||||
where
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
|
||||||
Ok(self
|
|
||||||
.feedbacks_mut()
|
|
||||||
.is_interesting_all(input, observers, exit_kind)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs the input and triggers observers and feedback
|
/// Runs the input and triggers observers and feedback
|
||||||
pub fn evaluate_input<E, EM, OT>(
|
pub fn execute_input<E, EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
) -> Result<(u32, u32), Error>
|
) -> Result<(u32, bool), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I> + HasObservers<OT>,
|
E: Executor<I> + HasObservers<OT>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
@ -341,121 +580,18 @@ where
|
|||||||
let exit_kind = executor.run_target(input)?;
|
let exit_kind = executor.run_target(input)?;
|
||||||
executor.post_exec(&self, event_mgr, input)?;
|
executor.post_exec(&self, event_mgr, input)?;
|
||||||
|
|
||||||
self.set_executions(self.executions() + 1);
|
*self.executions_mut() += 1;
|
||||||
executor.post_exec_observers()?;
|
executor.post_exec_observers()?;
|
||||||
|
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
let objective_fitness =
|
|
||||||
self.objective_feedbacks
|
|
||||||
.is_interesting_all(&input, observers, exit_kind.clone())?;
|
|
||||||
let fitness = self
|
let fitness = self
|
||||||
.feedbacks_mut()
|
.feedbacks_mut()
|
||||||
.is_interesting_all(&input, observers, exit_kind)?;
|
.is_interesting_all(&input, observers, exit_kind)?;
|
||||||
Ok((fitness, objective_fitness))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets all current feedbacks
|
let is_solution = self.objectives_mut().is_interesting_all(&input, observers, exit_kind.clone())? > 0;
|
||||||
#[inline]
|
|
||||||
pub fn discard_input(&mut self, input: &I) -> Result<(), Error> {
|
|
||||||
// TODO: This could probably be automatic in the feedback somehow?
|
|
||||||
self.feedbacks_mut().discard_metadata_all(&input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new testcase, appending the metadata from each feedback
|
Ok((fitness, is_solution))
|
||||||
#[inline]
|
|
||||||
pub fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result<Testcase<I>, Error> {
|
|
||||||
let mut testcase = Testcase::new(input);
|
|
||||||
testcase.set_fitness(fitness);
|
|
||||||
self.feedbacks_mut().append_metadata_all(&mut testcase)?;
|
|
||||||
Ok(testcase)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a testcase from this input, if it's intersting
|
|
||||||
#[inline]
|
|
||||||
pub fn testcase_if_interesting(
|
|
||||||
&mut self,
|
|
||||||
input: I,
|
|
||||||
fitness: u32,
|
|
||||||
) -> Result<Option<Testcase<I>>, Error> {
|
|
||||||
if fitness > 0 {
|
|
||||||
Ok(Some(self.input_to_testcase(input, fitness)?))
|
|
||||||
} else {
|
|
||||||
self.discard_input(&input)?;
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds this input to the corpus, if it's intersting
|
|
||||||
#[inline]
|
|
||||||
pub fn add_if_interesting(&mut self, input: I, fitness: u32) -> Result<Option<usize>, Error>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
|
||||||
if fitness > 0 {
|
|
||||||
let testcase = self.input_to_testcase(input, fitness)?;
|
|
||||||
Ok(Some(C::add(self, testcase)?))
|
|
||||||
} else {
|
|
||||||
self.discard_input(&input)?;
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Adds this input to the objective corpus, if it's an objective
|
|
||||||
#[inline]
|
|
||||||
pub fn add_if_objective(&mut self, input: I, fitness: u32) -> Result<Option<usize>, Error>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
{
|
|
||||||
if fitness > 0 {
|
|
||||||
let testcase = self.input_to_testcase(input, fitness)?;
|
|
||||||
Ok(Some(self.objective_corpus.add(testcase)))
|
|
||||||
} else {
|
|
||||||
self.discard_input(&input)?;
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
|
||||||
#[inline]
|
|
||||||
pub fn process_input<E, EM, OT>(
|
|
||||||
&mut self,
|
|
||||||
// TODO probably we can take a ref to input and pass a cloned one to add_if_interesting
|
|
||||||
input: I,
|
|
||||||
executor: &mut E,
|
|
||||||
manager: &mut EM,
|
|
||||||
) -> Result<u32, Error>
|
|
||||||
where
|
|
||||||
E: Executor<I> + HasObservers<OT>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
C: Corpus<I>,
|
|
||||||
EM: EventManager<I>,
|
|
||||||
{
|
|
||||||
let (fitness, obj_fitness) = self.evaluate_input(&input, executor, manager)?;
|
|
||||||
let observers = executor.observers();
|
|
||||||
|
|
||||||
if obj_fitness > 0 {
|
|
||||||
self.add_if_objective(input.clone(), obj_fitness)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if fitness > 0 {
|
|
||||||
let observers_buf = manager.serialize_observers(observers)?;
|
|
||||||
manager.fire(
|
|
||||||
self,
|
|
||||||
Event::NewTestcase {
|
|
||||||
input: input.clone(),
|
|
||||||
observers_buf,
|
|
||||||
corpus_size: self.corpus().count() + 1,
|
|
||||||
client_config: "TODO".into(),
|
|
||||||
time: crate::utils::current_time(),
|
|
||||||
executions: self.executions(),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
self.add_if_interesting(input, fitness)?;
|
|
||||||
} else {
|
|
||||||
self.discard_input(&input)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(fitness)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_initial_inputs<G, E, OT, EM>(
|
pub fn generate_initial_inputs<G, E, OT, EM>(
|
||||||
@ -475,8 +611,8 @@ where
|
|||||||
{
|
{
|
||||||
let mut added = 0;
|
let mut added = 0;
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let input = generator.generate(rand)?;
|
let input = generator.generate(self.rand_mut())?;
|
||||||
let fitness = self.process_input(input, executor, manager)?;
|
let fitness = self.evaluate_input(input, executor, manager)?;
|
||||||
if fitness > 0 {
|
if fitness > 0 {
|
||||||
added += 1;
|
added += 1;
|
||||||
}
|
}
|
||||||
@ -493,15 +629,16 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(corpus: C, feedbacks: FT, objective_corpus: OC, objective_feedbacks: OFT) -> Self {
|
pub fn new(rand: R, corpus: C, feedbacks: FT, solutions: SC, objectives: OFT) -> Self {
|
||||||
Self {
|
Self {
|
||||||
corpus,
|
rand,
|
||||||
executions: 0,
|
executions: 0,
|
||||||
start_time: current_milliseconds(),
|
start_time: Duration::from_millis(0),
|
||||||
metadata: SerdeAnyMap::default(),
|
metadata: SerdeAnyMap::default(),
|
||||||
feedbacks: feedbacks,
|
corpus,
|
||||||
objective_corpus: objective_corpus,
|
feedbacks,
|
||||||
objective_feedbacks: objective_feedbacks,
|
solutions,
|
||||||
|
objectives,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user