lib compiles
This commit is contained in:
parent
c9174ecb38
commit
db12506e2d
@ -89,7 +89,7 @@ where
|
||||
println!("Loading file {:?} ...", &path);
|
||||
let bytes = std::fs::read(&path)?;
|
||||
let input = BytesInput::new(bytes);
|
||||
let fitness = self.evaluate_input(&input, engine.executor_mut())?;
|
||||
let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
|
||||
if self.add_if_interesting(corpus, input, fitness)?.is_none() {
|
||||
println!("File {:?} was not interesting, skipped.", &path);
|
||||
}
|
||||
@ -224,10 +224,15 @@ where
|
||||
where
|
||||
E: Executor<I> + HasObservers<OT>,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
{
|
||||
executor.pre_exec_observers()?;
|
||||
|
||||
executor.run_target(&input, &self, &corpus, &mut event_mgr)?;
|
||||
executor.pre_exec(&self, corpus, event_mgr, input)?;
|
||||
executor.run_target(input)?;
|
||||
executor.post_exec(&self, corpus, event_mgr, input)?;
|
||||
|
||||
self.set_executions(self.executions() + 1);
|
||||
executor.post_exec_observers()?;
|
||||
|
||||
@ -307,7 +312,7 @@ where
|
||||
let mut added = 0;
|
||||
for _ in 0..num {
|
||||
let input = generator.generate(rand)?;
|
||||
let fitness = self.evaluate_input(&input, engine.executor_mut())?;
|
||||
let fitness = self.evaluate_input(&input, engine.executor_mut(), corpus, manager)?;
|
||||
if !self.add_if_interesting(corpus, input, fitness)?.is_none() {
|
||||
added += 1;
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use alloc::boxed::Box;
|
||||
use core::{ffi::c_void, ptr};
|
||||
use os_signals::set_oncrash_ptrs;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
@ -24,88 +23,96 @@ use self::os_signals::reset_oncrash_ptrs;
|
||||
use self::os_signals::setup_crash_handlers;
|
||||
|
||||
/// The inmem executor harness
|
||||
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
|
||||
type OnCrashFunction<I, C, EM, FT, R> = dyn FnMut(ExitKind, &I, &State<I, R, FT>, &C, &mut EM);
|
||||
type HarnessFunction<E> = fn(&E, &[u8]) -> ExitKind;
|
||||
|
||||
/// The inmem executor simply calls a target function, then returns afterwards.
|
||||
pub struct InMemoryExecutor<I, OT, C, EM, FT, R>
|
||||
pub struct InMemoryExecutor<I, OT>
|
||||
where
|
||||
I: Input + HasTargetBytes,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
R: Rand,
|
||||
{
|
||||
/// The name of this executor instance, to address it from other components
|
||||
name: &'static str,
|
||||
/// The harness function, being executed for each fuzzing loop execution
|
||||
harness_fn: HarnessFunction<I>,
|
||||
harness_fn: HarnessFunction<Self>,
|
||||
/// The observers, observing each run
|
||||
observers: OT,
|
||||
/// A special function being called right before the process crashes. It may save state to restore fuzzing after respawn.
|
||||
on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I, OT, C, EM, FT, R> Executor<I> for InMemoryExecutor<I, OT, C, EM, FT, R>
|
||||
impl<I, OT> Executor<I> for InMemoryExecutor<I, OT>
|
||||
where
|
||||
I: Input + HasTargetBytes,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
R: Rand,
|
||||
{
|
||||
#[inline]
|
||||
fn run_target(
|
||||
|
||||
fn pre_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
input: &I,
|
||||
state: State<I, R, FT>,
|
||||
state: &State<I, R, FT>,
|
||||
corpus: &C,
|
||||
event_mgr: &EM,
|
||||
) -> Result<ExitKind, AflError> {
|
||||
#[cfg(unix)]
|
||||
event_mgr: &mut EM,
|
||||
input: &I,
|
||||
) -> Result<(), AflError> where
|
||||
R: Rand ,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
{
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
set_oncrash_ptrs::<EM, C, OT, FT, I, R>(
|
||||
state,
|
||||
corpus,
|
||||
event_mgr,
|
||||
input,
|
||||
&mut self.on_crash_fn,
|
||||
);
|
||||
}
|
||||
let bytes = input.target_bytes();
|
||||
let ret = (self.harness_fn)(self, bytes.as_slice());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn post_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError> where
|
||||
R: Rand ,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>, {
|
||||
#[cfg(unix)]
|
||||
unsafe {
|
||||
reset_oncrash_ptrs::<EM, C, OT, FT, I, R>();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn run_target(
|
||||
&mut self,
|
||||
input: &I,
|
||||
) -> Result<ExitKind, AflError> {
|
||||
let bytes = input.target_bytes();
|
||||
let ret = (self.harness_fn)(self, bytes.as_slice());
|
||||
Ok(ret)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, OT, C, EM, FT, R> Named for InMemoryExecutor<I, OT, C, EM, FT, R>
|
||||
impl<I, OT> Named for InMemoryExecutor<I, OT>
|
||||
where
|
||||
I: Input + HasTargetBytes,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
R: Rand,
|
||||
{
|
||||
fn name(&self) -> &str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, OT, C, EM, FT, R> HasObservers<OT> for InMemoryExecutor<I, OT, C, EM, FT, R>
|
||||
impl<I, OT> HasObservers<OT> for InMemoryExecutor<I, OT>
|
||||
where
|
||||
I: Input + HasTargetBytes,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
R: Rand,
|
||||
{
|
||||
#[inline]
|
||||
fn observers(&self) -> &OT {
|
||||
@ -118,14 +125,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, OT, C, EM, FT, R> InMemoryExecutor<I, OT, C, EM, FT, R>
|
||||
impl<I, OT> InMemoryExecutor<I, OT>
|
||||
where
|
||||
I: Input + HasTargetBytes,
|
||||
OT: ObserversTuple,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>,
|
||||
FT: FeedbacksTuple<I>,
|
||||
R: Rand,
|
||||
{
|
||||
/// Create a new in mem executor.
|
||||
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
||||
@ -135,15 +138,18 @@ where
|
||||
/// * `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
|
||||
pub fn new(
|
||||
pub fn new<R, FT, C, EM>(
|
||||
name: &'static str,
|
||||
harness_fn: HarnessFunction<I>,
|
||||
harness_fn: HarnessFunction<Self>,
|
||||
observers: OT,
|
||||
on_crash_fn: Box<OnCrashFunction<I, C, EM, FT, R>>,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_event_mgr: &mut EM,
|
||||
) -> Self {
|
||||
) -> Self where
|
||||
R: Rand ,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>, {
|
||||
#[cfg(feature = "std")]
|
||||
unsafe {
|
||||
setup_crash_handlers::<EM, C, OT, FT, I, R>();
|
||||
@ -151,9 +157,9 @@ where
|
||||
|
||||
Self {
|
||||
harness_fn,
|
||||
on_crash_fn,
|
||||
observers,
|
||||
name,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,7 +206,6 @@ pub mod unix_signals {
|
||||
corpus::Corpus,
|
||||
engines::State,
|
||||
events::EventManager,
|
||||
executors::inmemory::{ExitKind, OnCrashFunction},
|
||||
feedbacks::FeedbacksTuple,
|
||||
inputs::Input,
|
||||
observers::ObserversTuple,
|
||||
@ -209,13 +214,12 @@ pub mod unix_signals {
|
||||
|
||||
/// Pointers to values only needed on crash. As the program will not continue after a crash,
|
||||
/// we should (tm) be okay with raw pointers here,
|
||||
static mut corpus_ptr: *const c_void = ptr::null_mut();
|
||||
static mut state_ptr: *const c_void = ptr::null_mut();
|
||||
static mut event_mgr_ptr: *mut c_void = ptr::null_mut();
|
||||
static mut CORPUS_PTR: *const c_void = ptr::null_mut();
|
||||
static mut STATE_PTR: *const c_void = ptr::null_mut();
|
||||
static mut EVENT_MGR_PTR: *mut c_void = ptr::null_mut();
|
||||
/// The (unsafe) pointer to the current inmem input, for the current run.
|
||||
/// This is neede for certain non-rust side effects, as well as unix signal handling.
|
||||
static mut current_input_ptr: *const c_void = ptr::null();
|
||||
static mut on_crash_fn_ptr: *mut c_void = ptr::null_mut();
|
||||
static mut CURRENT_INPUT_PTR: *const c_void = ptr::null();
|
||||
|
||||
pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash<EM, C, OT, FT, I, R>(
|
||||
_sig: c_int,
|
||||
@ -229,7 +233,7 @@ pub mod unix_signals {
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
if current_input_ptr == ptr::null() {
|
||||
if CURRENT_INPUT_PTR == ptr::null() {
|
||||
println!(
|
||||
"We died accessing addr {}, but are not in client... Exiting.",
|
||||
info.si_addr() as usize
|
||||
@ -243,10 +247,10 @@ pub mod unix_signals {
|
||||
#[cfg(feature = "std")]
|
||||
let _ = stdout().flush();
|
||||
|
||||
let input = (current_input_ptr as *const I).as_ref().unwrap();
|
||||
let corpus = (corpus_ptr as *const C).as_ref().unwrap();
|
||||
let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap();
|
||||
let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap();
|
||||
/*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
|
||||
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
|
||||
let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
|
||||
let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
|
||||
|
||||
if !on_crash_fn_ptr.is_null() {
|
||||
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
|
||||
@ -256,7 +260,7 @@ pub mod unix_signals {
|
||||
corpus,
|
||||
manager,
|
||||
);
|
||||
}
|
||||
}*/
|
||||
|
||||
std::process::exit(139);
|
||||
}
|
||||
@ -274,15 +278,15 @@ pub mod unix_signals {
|
||||
R: Rand,
|
||||
{
|
||||
dbg!("TIMEOUT/SIGUSR2 received");
|
||||
if current_input_ptr.is_null() {
|
||||
if CURRENT_INPUT_PTR.is_null() {
|
||||
dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
|
||||
return;
|
||||
}
|
||||
|
||||
let input = (current_input_ptr as *const I).as_ref().unwrap();
|
||||
let corpus = (corpus_ptr as *const C).as_ref().unwrap();
|
||||
let state = (event_mgr_ptr as *const State<I, R, FT>).as_ref().unwrap();
|
||||
let manager = (event_mgr_ptr as *mut EM).as_mut().unwrap();
|
||||
/*let input = (CURRENT_INPUT_PTR as *const I).as_ref().unwrap();
|
||||
let corpus = (CORPUS_PTR as *const C).as_ref().unwrap();
|
||||
let state = (EVENT_MGR_PTR as *const State<I, R, FT>).as_ref().unwrap();
|
||||
let manager = (EVENT_MGR_PTR as *mut EM).as_mut().unwrap();
|
||||
|
||||
if !on_crash_fn_ptr.is_null() {
|
||||
(*(on_crash_fn_ptr as *mut Box<OnCrashFunction<I, C, EM, FT, R>>))(
|
||||
@ -292,7 +296,7 @@ pub mod unix_signals {
|
||||
corpus,
|
||||
manager,
|
||||
);
|
||||
}
|
||||
}*/
|
||||
|
||||
/* TODO: If we want to be on the safe side, we really need to do this:
|
||||
match manager.llmp {
|
||||
@ -317,8 +321,7 @@ pub mod unix_signals {
|
||||
state: &State<I, R, FT>,
|
||||
corpus: &C,
|
||||
event_mgr: &mut EM,
|
||||
input: I,
|
||||
on_crash_handler: &mut Box<OnCrashFunction<I, C, EM, FT, R>>,
|
||||
input: &I,
|
||||
) where
|
||||
EM: EventManager<I>,
|
||||
C: Corpus<I, R>,
|
||||
@ -327,20 +330,18 @@ pub mod unix_signals {
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
current_input_ptr = input as *const _ as *const c_void;
|
||||
corpus_ptr = corpus as *const _ as *const c_void;
|
||||
state_ptr = state as *const _ as *const c_void;
|
||||
event_mgr_ptr = event_mgr as *mut _ as *mut c_void;
|
||||
on_crash_fn_ptr = on_crash_handler as *mut _ as *mut c_void;
|
||||
CURRENT_INPUT_PTR = input as *const _ as *const c_void;
|
||||
CORPUS_PTR = corpus as *const _ as *const c_void;
|
||||
STATE_PTR = state as *const _ as *const c_void;
|
||||
EVENT_MGR_PTR = event_mgr as *mut _ as *mut c_void;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn reset_oncrash_ptrs<EM, C, OT, FT, I, R>() {
|
||||
current_input_ptr = ptr::null();
|
||||
corpus_ptr = ptr::null();
|
||||
state_ptr = ptr::null();
|
||||
event_mgr_ptr = ptr::null_mut();
|
||||
on_crash_fn_ptr = ptr::null_mut();
|
||||
CURRENT_INPUT_PTR = ptr::null();
|
||||
CORPUS_PTR = ptr::null();
|
||||
STATE_PTR = ptr::null();
|
||||
EVENT_MGR_PTR = ptr::null_mut();
|
||||
}
|
||||
|
||||
// TODO clearly state that manager should be static (maybe put the 'static lifetime?)
|
||||
|
@ -7,6 +7,10 @@ use core::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
engines::State,
|
||||
corpus::Corpus,
|
||||
feedbacks::FeedbacksTuple,
|
||||
events::EventManager,
|
||||
utils::Rand,
|
||||
inputs::{HasTargetBytes, Input},
|
||||
observers::ObserversTuple,
|
||||
tuples::{MatchNameAndType, MatchType, Named, TupleList},
|
||||
@ -74,30 +78,52 @@ pub trait Executor<I>: Named
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
/// Instruct the target about the input and run
|
||||
fn run_target<R, FT, C, EM>(
|
||||
fn pre_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
input: &I,
|
||||
state: &State<I, R, FT>,
|
||||
corpus: &C,
|
||||
event_mgr: &EM,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError> where
|
||||
R: Rand ,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>, { Ok(()) }
|
||||
|
||||
fn post_exec<R, FT, C, EM>(
|
||||
&mut self,
|
||||
_state: &State<I, R, FT>,
|
||||
_corpus: &C,
|
||||
_event_mgr: &mut EM,
|
||||
_input: &I,
|
||||
) -> Result<(), AflError> where
|
||||
R: Rand ,
|
||||
FT: FeedbacksTuple<I>,
|
||||
C: Corpus<I, R>,
|
||||
EM: EventManager<I>, { Ok(()) }
|
||||
|
||||
/// Instruct the target about the input and run
|
||||
fn run_target(
|
||||
&mut self,
|
||||
input: &I
|
||||
) -> Result<ExitKind, AflError>;
|
||||
|
||||
}
|
||||
|
||||
pub trait ExecutorsTuple<I>: MatchType + MatchNameAndType
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn for_each(&self, f: fn(&dyn Executor<I>));
|
||||
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>));
|
||||
//fn for_each(&self, f: fn(&dyn Executor<I>));
|
||||
//fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>));
|
||||
}
|
||||
|
||||
impl<I> ExecutorsTuple<I> for ()
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn for_each(&self, _f: fn(&dyn Executor<I>)) {}
|
||||
fn for_each_mut(&mut self, _f: fn(&mut dyn Executor<I>)) {}
|
||||
//fn for_each(&self, _f: fn(&dyn Executor<I>)) {}
|
||||
//fn for_each_mut(&mut self, _f: fn(&mut dyn Executor<I>)) {}
|
||||
}
|
||||
|
||||
impl<Head, Tail, I> ExecutorsTuple<I> for (Head, Tail)
|
||||
@ -106,7 +132,7 @@ where
|
||||
Tail: ExecutorsTuple<I> + TupleList,
|
||||
I: Input,
|
||||
{
|
||||
fn for_each(&self, f: fn(&dyn Executor<I>)) {
|
||||
/*fn for_each(&self, f: fn(&dyn Executor<I>)) {
|
||||
f(&self.0);
|
||||
self.1.for_each(f)
|
||||
}
|
||||
@ -114,7 +140,7 @@ where
|
||||
fn for_each_mut(&mut self, f: fn(&mut dyn Executor<I>)) {
|
||||
f(&mut self.0);
|
||||
self.1.for_each_mut(f)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -61,7 +61,7 @@ where
|
||||
self.mutator_mut()
|
||||
.mutate(rand, corpus, &mut input_mut, i as i32)?;
|
||||
|
||||
let fitness = state.evaluate_input(&input_mut, engine.executor_mut())?;
|
||||
let fitness = state.evaluate_input(&input_mut, engine.executor_mut(), corpus, manager)?;
|
||||
|
||||
self.mutator_mut()
|
||||
.post_exec(fitness, &input_mut, i as i32)?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user