commit
3267c93c8d
@ -19,30 +19,47 @@ use crate::stages::Stage;
|
||||
use crate::utils::{current_milliseconds, Rand};
|
||||
use crate::AflError;
|
||||
|
||||
// TODO FeedbackMetadata to store histroy_map
|
||||
|
||||
pub trait StateMetadata: Debug {
|
||||
/// The name of this metadata - used to find it in the list of avaliable metadatas
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
pub trait State<C, E, I, R>
|
||||
pub struct State<I, R>
|
||||
where
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
executions: usize,
|
||||
start_time: u64,
|
||||
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
|
||||
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
|
||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||
phantom: PhantomData<R>,
|
||||
}
|
||||
|
||||
impl<I, R> State<I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
/// Get executions
|
||||
fn executions(&self) -> usize;
|
||||
pub fn executions(&self) -> usize {
|
||||
self.executions
|
||||
}
|
||||
|
||||
/// Set executions
|
||||
fn set_executions(&mut self, executions: usize);
|
||||
pub fn set_executions(&mut self, executions: usize){
|
||||
self.executions = executions
|
||||
}
|
||||
|
||||
fn start_time(&self) -> u64;
|
||||
fn set_start_time(&mut self, ms: u64);
|
||||
pub fn start_time(&self) -> u64{
|
||||
self.start_time
|
||||
}
|
||||
pub fn set_start_time(&mut self, ms: u64) {
|
||||
self.start_time = ms
|
||||
}
|
||||
|
||||
fn executions_over_seconds(&self) -> u64 {
|
||||
pub fn executions_over_seconds(&self) -> u64 {
|
||||
let elapsed = current_milliseconds() - self.start_time();
|
||||
if elapsed == 0 {
|
||||
return 0;
|
||||
@ -56,76 +73,59 @@ where
|
||||
}
|
||||
|
||||
/// Get all the metadatas into an HashMap
|
||||
fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>;
|
||||
pub fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>{
|
||||
&self.metadatas
|
||||
}
|
||||
|
||||
/// Get all the metadatas into an HashMap (mutable)
|
||||
fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>>;
|
||||
pub fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>>{
|
||||
&mut self.metadatas
|
||||
}
|
||||
|
||||
/// Add a metadata
|
||||
fn add_metadata(&mut self, meta: Box<dyn StateMetadata>) {
|
||||
pub fn add_metadata(&mut self, meta: Box<dyn StateMetadata>) {
|
||||
self.metadatas_mut().insert(meta.name(), meta);
|
||||
}
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &[Rc<RefCell<dyn Observer>>];
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers_mut(&mut self) -> &mut Vec<Rc<RefCell<dyn Observer>>>;
|
||||
|
||||
/// Add a linked observer
|
||||
fn add_observer(&mut self, observer: Rc<RefCell<dyn Observer>>) {
|
||||
self.observers_mut().push(observer);
|
||||
}
|
||||
|
||||
/// Reset the state of all the observes linked to this executor
|
||||
fn reset_observers(&mut self) -> Result<(), AflError> {
|
||||
for observer in self.observers() {
|
||||
observer.borrow_mut().reset()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the post exec hook for all the observes linked to this executor
|
||||
fn post_exec_observers(&mut self) -> Result<(), AflError> {
|
||||
self.observers()
|
||||
.iter()
|
||||
.map(|x| x.borrow_mut().post_exec())
|
||||
.fold(Ok(()), |acc, x| if x.is_err() { x } else { acc })
|
||||
}
|
||||
|
||||
/// Returns vector of feebacks
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>];
|
||||
pub fn feedbacks(&self) -> &[Box<dyn Feedback<I>>]{
|
||||
&self.feedbacks
|
||||
}
|
||||
|
||||
/// Returns vector of feebacks (mutable)
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
|
||||
pub fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>{
|
||||
&mut self.feedbacks
|
||||
}
|
||||
|
||||
/// Adds a feedback
|
||||
fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
|
||||
pub fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
|
||||
self.feedbacks_mut().push(feedback);
|
||||
}
|
||||
|
||||
/// Return the executor
|
||||
fn executor(&self) -> &E;
|
||||
|
||||
/// Return the executor (mutable)
|
||||
fn executor_mut(&mut self) -> &mut E;
|
||||
// TODO move some of these, like evaluate_input, to FuzzingEngine
|
||||
|
||||
/// Runs the input and triggers observers and feedback
|
||||
fn evaluate_input(&mut self, input: &I) -> Result<u32, AflError> {
|
||||
self.reset_observers()?;
|
||||
self.executor_mut().run_target(&input)?;
|
||||
pub fn evaluate_input<C, E, EM>(&mut self, input: &I, engine: &mut Engine<EM, E, C, I, R>) -> Result<u32, AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
{
|
||||
engine.executor_mut().reset_observers()?;
|
||||
engine.executor_mut().run_target(&input)?;
|
||||
self.set_executions(self.executions() + 1);
|
||||
self.post_exec_observers()?;
|
||||
engine.executor_mut().post_exec_observers()?;
|
||||
|
||||
let mut fitness = 0;
|
||||
let observers = engine.executor().observers();
|
||||
for feedback in self.feedbacks_mut() {
|
||||
fitness += feedback.is_interesting(&input)?;
|
||||
fitness += feedback.is_interesting(&input, observers)?;
|
||||
}
|
||||
Ok(fitness)
|
||||
}
|
||||
|
||||
/// Resets all current feedbacks
|
||||
fn discard_input(&mut self, input: &I) -> Result<(), AflError> {
|
||||
pub fn discard_input(&mut self, input: &I) -> Result<(), AflError> {
|
||||
// TODO: This could probably be automatic in the feedback somehow?
|
||||
for feedback in self.feedbacks_mut() {
|
||||
feedback.discard_metadata(input)?;
|
||||
@ -134,7 +134,7 @@ where
|
||||
}
|
||||
|
||||
/// Creates a new testcase, appending the metadata from each feedback
|
||||
fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result<Testcase<I>, AflError> {
|
||||
pub fn input_to_testcase(&mut self, input: I, fitness: u32) -> Result<Testcase<I>, AflError> {
|
||||
let mut testcase = Testcase::new(input);
|
||||
testcase.set_fitness(fitness);
|
||||
for feedback in self.feedbacks_mut() {
|
||||
@ -145,7 +145,7 @@ where
|
||||
}
|
||||
|
||||
/// Create a testcase from this input, if it's intersting
|
||||
fn testcase_if_interesting(
|
||||
pub fn testcase_if_interesting(
|
||||
&mut self,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
@ -159,12 +159,15 @@ where
|
||||
}
|
||||
|
||||
/// Adds this input to the corpus, if it's intersting
|
||||
fn add_if_interesting(
|
||||
pub fn add_if_interesting<C>(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<usize>, AflError> {
|
||||
) -> Result<Option<usize>, AflError>
|
||||
where
|
||||
C: Corpus<I, R>
|
||||
{
|
||||
if fitness > 0 {
|
||||
let testcase = self.input_to_testcase(input, fitness)?;
|
||||
Ok(Some(corpus.add(testcase)))
|
||||
@ -173,153 +176,117 @@ where
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_initial_inputs<S, G, C, E, I, R, EM>(
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
events: &mut EM,
|
||||
num: usize,
|
||||
) -> Result<(), AflError>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
G: Generator<I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
{
|
||||
for _ in 0..num {
|
||||
let input = generator.generate(rand)?;
|
||||
let fitness = state.evaluate_input(&input)?;
|
||||
state.add_if_interesting(corpus, input, fitness)?;
|
||||
events.fire(Event::LoadInitial {
|
||||
sender_id: 0,
|
||||
phantom: PhantomData,
|
||||
})?;
|
||||
}
|
||||
events.process(state, corpus)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct StdState<C, E, I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
executions: usize,
|
||||
start_time: u64,
|
||||
metadatas: HashMap<&'static str, Box<dyn StateMetadata>>,
|
||||
// additional_corpuses: HashMap<&'static str, Box<dyn Corpus>>,
|
||||
observers: Vec<Rc<RefCell<dyn Observer>>>,
|
||||
feedbacks: Vec<Box<dyn Feedback<I>>>,
|
||||
executor: E,
|
||||
phantom: PhantomData<(C, R)>,
|
||||
}
|
||||
|
||||
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn executions(&self) -> usize {
|
||||
self.executions
|
||||
pub fn generate_initial_inputs<G, C, E, FE, EM>(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
num: usize,
|
||||
) -> Result<(), AflError>
|
||||
where
|
||||
G: Generator<I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
{
|
||||
for _ in 0..num {
|
||||
let input = generator.generate(rand)?;
|
||||
let fitness = self.evaluate_input(&input, engine)?;
|
||||
self.add_if_interesting(corpus, input, fitness)?;
|
||||
engine.events_manager_mut().fire(Event::LoadInitial {
|
||||
sender_id: 0,
|
||||
phantom: PhantomData,
|
||||
})?;
|
||||
}
|
||||
engine.events_manager_mut().process(self, corpus)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_executions(&mut self, executions: usize) {
|
||||
self.executions = executions
|
||||
}
|
||||
|
||||
fn start_time(&self) -> u64 {
|
||||
self.start_time
|
||||
}
|
||||
fn set_start_time(&mut self, ms: u64) {
|
||||
self.start_time = ms
|
||||
}
|
||||
|
||||
fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>> {
|
||||
&self.metadatas
|
||||
}
|
||||
|
||||
fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>> {
|
||||
&mut self.metadatas
|
||||
}
|
||||
|
||||
fn observers(&self) -> &[Rc<RefCell<dyn Observer>>] {
|
||||
&self.observers
|
||||
}
|
||||
|
||||
fn observers_mut(&mut self) -> &mut Vec<Rc<RefCell<dyn Observer>>> {
|
||||
&mut self.observers
|
||||
}
|
||||
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] {
|
||||
&self.feedbacks
|
||||
}
|
||||
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>> {
|
||||
&mut self.feedbacks
|
||||
}
|
||||
|
||||
fn executor(&self) -> &E {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
fn executor_mut(&mut self) -> &mut E {
|
||||
&mut self.executor
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, E, I, R> StdState<C, E, I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
pub fn new(executor: E) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
executions: 0,
|
||||
start_time: current_milliseconds(),
|
||||
metadatas: HashMap::default(),
|
||||
observers: vec![],
|
||||
feedbacks: vec![],
|
||||
executor: executor,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Engine<S, EM, E, C, I, R>
|
||||
pub struct Engine<EM, E, C, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &[Box<dyn Stage<S, EM, E, C, I, R>>];
|
||||
manager: EM,
|
||||
executor: E,
|
||||
phantom: PhantomData<(C, I, R)>
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, EM, E, C, I, R>>>;
|
||||
impl<EM, E, C, I, R> Engine<EM, E, C, I, R>
|
||||
where
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
pub fn events_manager(&self) -> &EM {
|
||||
&self.manager
|
||||
}
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<S, EM, E, C, I, R>>) {
|
||||
pub fn events_manager_mut(&mut self) -> &mut EM {
|
||||
&mut self.manager
|
||||
}
|
||||
|
||||
/// Return the executor
|
||||
pub fn executor(&self) -> &E {
|
||||
&self.executor
|
||||
}
|
||||
|
||||
/// Return the executor (mutable)
|
||||
pub fn executor_mut(&mut self) -> &mut E {
|
||||
&mut self.executor
|
||||
}
|
||||
|
||||
// TODO additional executors, Vec<Box<dyn Executor<I>>>
|
||||
|
||||
pub fn new(executor: E, events_manager: EM) -> Self {
|
||||
Self {
|
||||
executor: executor,
|
||||
manager: events_manager,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Fuzzer<EM, E, C, I, R>
|
||||
where
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &[Box<dyn Stage<EM, E, C, I, R>>];
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, C, I, R>>>;
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<EM, E, C, I, R>>) {
|
||||
self.stages_mut().push(stage);
|
||||
}
|
||||
|
||||
fn fuzz_one(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<I, R>,
|
||||
corpus: &mut C,
|
||||
events: &mut EM,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
) -> Result<usize, AflError> {
|
||||
let (testcase, idx) = corpus.next(rand)?;
|
||||
match testcase.input() {
|
||||
@ -333,27 +300,27 @@ where
|
||||
let input = corpus.get(idx).input().as_ref().unwrap();
|
||||
|
||||
for stage in self.stages_mut() {
|
||||
stage.perform(rand, state, corpus, events, &input)?;
|
||||
stage.perform(rand, state, corpus, engine, &input)?;
|
||||
}
|
||||
|
||||
events.process(state, corpus)?;
|
||||
engine.events_manager_mut().process(state, corpus)?;
|
||||
Ok(idx)
|
||||
}
|
||||
|
||||
fn fuzz_loop(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<I, R>,
|
||||
corpus: &mut C,
|
||||
events: &mut EM,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
) -> Result<(), AflError> {
|
||||
let mut last = current_milliseconds();
|
||||
loop {
|
||||
self.fuzz_one(rand, state, corpus, events)?;
|
||||
self.fuzz_one(rand, state, corpus, engine)?;
|
||||
let cur = current_milliseconds();
|
||||
if cur - last > 60 * 100 {
|
||||
last = cur;
|
||||
events.fire(Event::UpdateStats {
|
||||
engine.events_manager_mut().fire(Event::UpdateStats {
|
||||
sender_id: 0,
|
||||
new_execs: 1,
|
||||
phantom: PhantomData,
|
||||
@ -361,43 +328,40 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub struct StdEngine<S, EM, E, C, I, R>
|
||||
pub struct StdFuzzer<EM, E, C, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
stages: Vec<Box<dyn Stage<S, EM, E, C, I, R>>>,
|
||||
phantom: PhantomData<EM>,
|
||||
stages: Vec<Box<dyn Stage<EM, E, C, I, R>>>,
|
||||
}
|
||||
|
||||
impl<S, EM, E, C, I, R> Engine<S, EM, E, C, I, R> for StdEngine<S, EM, E, C, I, R>
|
||||
impl<EM, E, C, I, R> Fuzzer<EM, E, C, I, R> for StdFuzzer<EM, E, C, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn stages(&self) -> &[Box<dyn Stage<S, EM, E, C, I, R>>] {
|
||||
fn stages(&self) -> &[Box<dyn Stage<EM, E, C, I, R>>] {
|
||||
&self.stages
|
||||
}
|
||||
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<S, EM, E, C, I, R>>> {
|
||||
fn stages_mut(&mut self) -> &mut Vec<Box<dyn Stage<EM, E, C, I, R>>> {
|
||||
&mut self.stages
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, EM, E, C, I, R> StdEngine<S, EM, E, C, I, R>
|
||||
impl<EM, E, C, I, R> StdFuzzer<EM, E, C, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
@ -405,12 +369,12 @@ where
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
stages: vec![],
|
||||
phantom: PhantomData,
|
||||
stages: vec![]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: no_std test
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(test)]
|
||||
@ -422,7 +386,7 @@ mod tests {
|
||||
use std::io::stderr;
|
||||
|
||||
use crate::corpus::{Corpus, InMemoryCorpus, Testcase};
|
||||
use crate::engines::{Engine, StdEngine, StdState};
|
||||
use crate::engines::{Engine, Fuzzer, StdFuzzer, State};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::events::LoggerEventManager;
|
||||
use crate::executors::inmemory::InMemoryExecutor;
|
||||
@ -445,21 +409,22 @@ mod tests {
|
||||
corpus.add(testcase);
|
||||
|
||||
let executor = InMemoryExecutor::<BytesInput>::new(harness);
|
||||
let mut state = StdState::new(executor);
|
||||
let mut state = State::new();
|
||||
|
||||
let mut events_manager = LoggerEventManager::new(stderr());
|
||||
|
||||
let mut engine = StdEngine::new();
|
||||
let mut engine = Engine::new(executor, events_manager);
|
||||
let mut mutator = StdScheduledMutator::new();
|
||||
mutator.add_mutation(mutation_bitflip);
|
||||
let stage = StdMutationalStage::new(mutator);
|
||||
engine.add_stage(Box::new(stage));
|
||||
let mut fuzzer = StdFuzzer::new();
|
||||
fuzzer.add_stage(Box::new(stage));
|
||||
|
||||
//
|
||||
|
||||
for i in 0..1000 {
|
||||
engine
|
||||
.fuzz_one(&mut rand, &mut state, &mut corpus, &mut events_manager)
|
||||
fuzzer
|
||||
.fuzz_one(&mut rand, &mut state, &mut corpus, &mut engine)
|
||||
.expect(&format!("Error in iter {}", i));
|
||||
}
|
||||
}
|
||||
|
@ -60,35 +60,33 @@ pub unsafe fn llmp_tcp_server_clientloop(client: *mut LlmpClient, _data: *mut c_
|
||||
|
||||
/// Eventmanager for multi-processed application
|
||||
#[cfg(feature = "std")]
|
||||
pub struct LLMPEventManager<S, C, E, I, R>
|
||||
pub struct LLMPEventManager<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
R: Rand,
|
||||
//CE: CustomEvent<S, C, E, I, R>,
|
||||
//CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
// TODO...
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
is_broker: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<S, C, E, I, R> EventManager<S, C, E, I, R> for LLMPEventManager<S, C, E, I, R>
|
||||
impl<C, E, I, R> EventManager<C, E, I, R> for LLMPEventManager<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
//CE: CustomEvent<S, C, E, I, R>,
|
||||
//CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
fn enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn fire(&mut self, _event: Event<S, C, E, I, R>) -> Result<(), AflError> {
|
||||
fn fire(&mut self, _event: Event<C, E, I, R>) -> Result<(), AflError> {
|
||||
//self.events.push(event);
|
||||
|
||||
// TODO: Serde serialize, llmp send
|
||||
@ -96,7 +94,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process(&mut self, _state: &mut S, _corpus: &mut C) -> Result<usize, AflError> {
|
||||
fn process(&mut self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<usize, AflError> {
|
||||
// TODO: iterators
|
||||
/*
|
||||
let mut handled = vec![];
|
||||
@ -127,9 +125,8 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<S, C, E, I, R> LLMPEventManager<S, C, E, I, R>
|
||||
impl<C, E, I, R> LLMPEventManager<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
|
@ -34,9 +34,9 @@ enum BrokerEventResult {
|
||||
/*
|
||||
|
||||
/// A custom event, in case a user wants to extend the features (at compile time)
|
||||
pub trait CustomEvent<S, C, E, I, R>
|
||||
pub trait CustomEvent<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
S: State<I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
@ -45,81 +45,79 @@ where
|
||||
/// Returns the name of this event
|
||||
fn name(&self) -> &str;
|
||||
/// This method will be called in the broker
|
||||
fn handle_in_broker(&self, broker: &dyn EventManager<S, C, E, I, R, Self>, state: &mut S, corpus: &mut C) -> Result<BrokerEventResult, AflError>;
|
||||
fn handle_in_broker(&self, broker: &dyn EventManager<C, E, I, R, Self>, state: &mut State<I, R>, corpus: &mut C) -> Result<BrokerEventResult, AflError>;
|
||||
/// This method will be called in the clients after handle_in_broker (unless BrokerEventResult::Handled) was returned in handle_in_broker
|
||||
fn handle_in_client(&self, client: &dyn EventManager<S, C, E, I, R, Self>, state: &mut S, corpus: &mut C) -> Result<(), AflError>;
|
||||
fn handle_in_client(&self, client: &dyn EventManager<C, E, I, R, Self>, state: &mut State<I, R>, corpus: &mut C) -> Result<(), AflError>;
|
||||
}
|
||||
|
||||
struct UnusedCustomEvent {}
|
||||
impl<S, C, E, I, R> CustomEvent<S, C, E, I, R> for UnusedCustomEvent<S, C, E, I, R>
|
||||
impl<C, E, I, R> CustomEvent<C, E, I, R> for UnusedCustomEvent<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
S: State<I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn name(&self) -> &str {"No custom events"}
|
||||
fn handle_in_broker(&self, broker: &dyn EventManager<S, C, E, I, R, Self>, state: &mut S, corpus: &mut C) {Ok(BrokerEventResult::Handled)}
|
||||
fn handle_in_client(&self, client: &dyn EventManager<S, C, E, I, R, Self>, state: &mut S, corpus: &mut C) {Ok(())}
|
||||
fn handle_in_broker(&self, broker: &dyn EventManager<C, E, I, R, Self>, state: &mut State<I, R>, corpus: &mut C) {Ok(BrokerEventResult::Handled)}
|
||||
fn handle_in_client(&self, client: &dyn EventManager<C, E, I, R, Self>, state: &mut State<I, R>, corpus: &mut C) {Ok(())}
|
||||
}
|
||||
*/
|
||||
|
||||
/// Events sent around in the library
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub enum Event<S, C, E, I, R>
|
||||
pub enum Event<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
// CE: CustomEvent<S, C, E, I, R>,
|
||||
// CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
LoadInitial {
|
||||
sender_id: u64,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
NewTestcase {
|
||||
sender_id: u64,
|
||||
testcase: Testcase<I>,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
UpdateStats {
|
||||
sender_id: u64,
|
||||
new_execs: usize,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
Crash {
|
||||
sender_id: u64,
|
||||
input: I,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
Timeout {
|
||||
sender_id: u64,
|
||||
input: I,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
Log {
|
||||
sender_id: u64,
|
||||
severity_level: u8,
|
||||
message: String,
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
None {
|
||||
phantom: PhantomData<(S, C, E, I, R)>,
|
||||
phantom: PhantomData<(C, E, I, R)>,
|
||||
},
|
||||
//Custom {sender_id: u64, custom_event: CE},
|
||||
}
|
||||
|
||||
impl<S, C, E, I, R> Event<S, C, E, I, R>
|
||||
impl<C, E, I, R> Event<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
//CE: CustomEvent<S, C, E, I, R>,
|
||||
//CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
pub fn name(&self) -> &str {
|
||||
match self {
|
||||
@ -160,7 +158,7 @@ where
|
||||
|
||||
fn handle_in_broker(
|
||||
&self,
|
||||
/*broker: &dyn EventManager<S, C, E, I, R>,*/ _state: &mut S,
|
||||
/*broker: &dyn EventManager<C, E, I, R>,*/ _state: &mut State<I, R>,
|
||||
_corpus: &mut C,
|
||||
) -> Result<BrokerEventResult, AflError> {
|
||||
match self {
|
||||
@ -215,7 +213,7 @@ where
|
||||
|
||||
fn handle_in_client(
|
||||
self,
|
||||
/*client: &dyn EventManager<S, C, E, I, R>,*/ _state: &mut S,
|
||||
/*client: &dyn EventManager<C, E, I, R>,*/ _state: &mut State<I, R>,
|
||||
corpus: &mut C,
|
||||
) -> Result<(), AflError> {
|
||||
match self {
|
||||
@ -236,9 +234,8 @@ where
|
||||
// TODO serialize and deserialize, defaults to serde
|
||||
}
|
||||
|
||||
pub trait EventManager<S, C, E, I, R>
|
||||
pub trait EventManager<C, E, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
@ -249,13 +246,13 @@ where
|
||||
fn enabled(&self) -> bool;
|
||||
|
||||
/// Fire an Event
|
||||
fn fire(&mut self, event: Event<S, C, E, I, R>) -> Result<(), AflError>;
|
||||
fn fire(&mut self, event: Event<C, E, I, R>) -> Result<(), AflError>;
|
||||
|
||||
/// Lookup for incoming events and process them.
|
||||
/// Return the number of processes events or an error
|
||||
fn process(&mut self, state: &mut S, corpus: &mut C) -> Result<usize, AflError>;
|
||||
fn process(&mut self, state: &mut State<I, R>, corpus: &mut C) -> Result<usize, AflError>;
|
||||
|
||||
fn on_recv(&self, _state: &mut S, _corpus: &mut C) -> Result<(), AflError> {
|
||||
fn on_recv(&self, _state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> {
|
||||
// TODO: Better way to move out of testcase, or get ref
|
||||
//Ok(corpus.add(self.testcase.take().unwrap()))
|
||||
Ok(())
|
||||
@ -263,7 +260,7 @@ where
|
||||
}
|
||||
|
||||
/*TODO
|
||||
fn on_recv(&self, state: &mut S, _corpus: &mut C) -> Result<(), AflError> {
|
||||
fn on_recv(&self, state: &mut State<I, R>, _corpus: &mut C) -> Result<(), AflError> {
|
||||
println!(
|
||||
"#{}\t exec/s: {}",
|
||||
state.executions(),
|
||||
@ -275,41 +272,39 @@ where
|
||||
*/
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub struct LoggerEventManager<S, C, E, I, R, W>
|
||||
pub struct LoggerEventManager<C, E, I, R, W>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
R: Rand,
|
||||
W: Write,
|
||||
//CE: CustomEvent<S, C, E, I, R>,
|
||||
//CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
events: Vec<Event<S, C, E, I, R>>,
|
||||
events: Vec<Event<C, E, I, R>>,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<S, C, E, I, R, W> EventManager<S, C, E, I, R> for LoggerEventManager<S, C, E, I, R, W>
|
||||
impl<C, E, I, R, W> EventManager<C, E, I, R> for LoggerEventManager<C, E, I, R, W>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
W: Write,
|
||||
//CE: CustomEvent<S, C, E, I, R>,
|
||||
//CE: CustomEvent<C, E, I, R>,
|
||||
{
|
||||
fn enabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn fire(&mut self, event: Event<S, C, E, I, R>) -> Result<(), AflError> {
|
||||
fn fire(&mut self, event: Event<C, E, I, R>) -> Result<(), AflError> {
|
||||
self.events.push(event);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process(&mut self, state: &mut S, corpus: &mut C) -> Result<usize, AflError> {
|
||||
fn process(&mut self, state: &mut State<I, R>, corpus: &mut C) -> Result<usize, AflError> {
|
||||
// TODO: iterators
|
||||
let mut handled = vec![];
|
||||
for x in self.events.iter() {
|
||||
@ -330,9 +325,8 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<S, C, E, I, R, W> LoggerEventManager<S, C, E, I, R, W>
|
||||
impl<C, E, I, R, W> LoggerEventManager<C, E, I, R, W>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
E: Executor<I>,
|
||||
|
@ -1,10 +1,10 @@
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::ffi::c_void;
|
||||
use core::ptr;
|
||||
|
||||
use crate::executors::{Executor, ExitKind};
|
||||
use crate::inputs::Input;
|
||||
use crate::serde_anymap::NamedSerdeAnyMap;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
|
||||
type HarnessFunction<I> = fn(&dyn Executor<I>, &[u8]) -> ExitKind;
|
||||
@ -14,15 +14,7 @@ where
|
||||
I: Input,
|
||||
{
|
||||
harness: HarnessFunction<I>,
|
||||
}
|
||||
|
||||
impl<I> Into<Rc<RefCell<Self>>> for InMemoryExecutor<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn into(self) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
observers: NamedSerdeAnyMap<dyn Observer>,
|
||||
}
|
||||
|
||||
static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null();
|
||||
@ -42,6 +34,14 @@ where
|
||||
}
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn observers(&self) -> &NamedSerdeAnyMap<dyn Observer> {
|
||||
&self.observers
|
||||
}
|
||||
|
||||
fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap<dyn Observer> {
|
||||
&mut self.observers
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> InMemoryExecutor<I>
|
||||
@ -55,6 +55,7 @@ where
|
||||
}
|
||||
Self {
|
||||
harness: harness_fn,
|
||||
observers: NamedSerdeAnyMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
pub mod inmemory;
|
||||
|
||||
use crate::inputs::Input;
|
||||
use crate::serde_anymap::NamedSerdeAnyMap;
|
||||
use crate::observers::Observer;
|
||||
use crate::AflError;
|
||||
|
||||
pub enum ExitKind {
|
||||
@ -10,12 +12,34 @@ pub enum ExitKind {
|
||||
Timeout,
|
||||
}
|
||||
|
||||
// TODO unbox input
|
||||
|
||||
pub trait Executor<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
/// Instruct the target about the input and run
|
||||
fn run_target(&mut self, input: &I) -> Result<ExitKind, AflError>;
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers(&self) -> &NamedSerdeAnyMap<dyn Observer>;
|
||||
|
||||
/// Get the linked observers
|
||||
fn observers_mut(&mut self) -> &mut NamedSerdeAnyMap<dyn Observer>;
|
||||
|
||||
/// Add a linked observer
|
||||
fn add_observer(&mut self, observer: Box<dyn Observer>) {
|
||||
let name = observer.name();
|
||||
self.observers_mut().insert(observer, name);
|
||||
}
|
||||
|
||||
/// Reset the state of all the observes linked to this executor
|
||||
fn reset_observers(&mut self) -> Result<(), AflError> {
|
||||
self.observers_mut().for_each_mut(|_, x| Ok(x.reset()?))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Run the post exec hook for all the observes linked to this executor
|
||||
fn post_exec_observers(&mut self) -> Result<(), AflError> {
|
||||
self.observers_mut().for_each_mut(|_, x| Ok(x.post_exec()?))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,11 @@
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use core::any::Any;
|
||||
use core::cell::RefCell;
|
||||
use core::marker::PhantomData;
|
||||
use num::Integer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::corpus::{Testcase, TestcaseMetadata};
|
||||
use crate::inputs::Input;
|
||||
use crate::observers::MapObserver;
|
||||
use crate::serde_anymap::SerdeAny;
|
||||
use crate::observers::{Observer, MapObserver};
|
||||
use crate::serde_anymap::NamedSerdeAnyMap;
|
||||
use crate::AflError;
|
||||
|
||||
pub trait Feedback<I>
|
||||
@ -17,7 +13,7 @@ where
|
||||
I: Input,
|
||||
{
|
||||
/// is_interesting should return the "Interestingness" from 0 to 255 (percent times 2.55)
|
||||
fn is_interesting(&mut self, input: &I) -> Result<u32, AflError>;
|
||||
fn is_interesting(&mut self, input: &I, observers: &NamedSerdeAnyMap<dyn Observer>) -> Result<u32, AflError>;
|
||||
|
||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||
fn append_metadata(&mut self, _testcase: &mut Testcase<I>) -> Result<(), AflError> {
|
||||
@ -28,6 +24,8 @@ where
|
||||
fn discard_metadata(&mut self, _input: &I) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// A Reducer function is used to aggregate values for the novelty search
|
||||
@ -78,16 +76,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a usable history map of the given size
|
||||
pub fn create_history_map<T>(map_size: usize) -> Rc<RefCell<Vec<T>>>
|
||||
where
|
||||
T: Default + Clone,
|
||||
{
|
||||
{
|
||||
Rc::new(RefCell::new(vec![T::default(); map_size]))
|
||||
}
|
||||
}
|
||||
|
||||
/// The most common AFL-like feedback type
|
||||
pub struct MapFeedback<T, R, O>
|
||||
where
|
||||
@ -96,39 +84,41 @@ where
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
/// The observer this feedback struct observes
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Vec<T>,
|
||||
/// Name identifier of this instance
|
||||
name: &'static str,
|
||||
/// Phantom Data of Reducer
|
||||
phantom: PhantomData<R>,
|
||||
phantom: PhantomData<(R, O)>,
|
||||
}
|
||||
|
||||
impl<T, R, O, I> Feedback<I> for MapFeedback<T, R, O>
|
||||
where
|
||||
T: Integer + Copy + 'static,
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<T>,
|
||||
O: MapObserver<T> + 'static,
|
||||
I: Input,
|
||||
{
|
||||
fn is_interesting(&mut self, _input: &I) -> Result<u32, AflError> {
|
||||
fn is_interesting(&mut self, _input: &I, observers: &NamedSerdeAnyMap<dyn Observer>) -> Result<u32, AflError> {
|
||||
let mut interesting = 0;
|
||||
|
||||
// TODO optimize
|
||||
let size = self.map_observer.borrow().map().len();
|
||||
let mut history_map = self.history_map.borrow_mut();
|
||||
let observer = self.map_observer.borrow();
|
||||
let observer = observers.get::<O>(self.name).unwrap();
|
||||
let size = observer.map().len();
|
||||
for i in 0..size {
|
||||
let history = history_map[i];
|
||||
let history = self.history_map[i];
|
||||
let item = observer.map()[i];
|
||||
let reduced = R::reduce(history, item);
|
||||
if history != reduced {
|
||||
history_map[i] = reduced;
|
||||
self.history_map[i] = reduced;
|
||||
interesting += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(interesting)
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, O> MapFeedback<T, R, O>
|
||||
@ -137,11 +127,11 @@ where
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Create new MapFeedback using a map observer
|
||||
pub fn new(map_observer: Rc<RefCell<O>>, map_size: usize) -> Self {
|
||||
/// Create new MapFeedback
|
||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
||||
Self {
|
||||
map_observer: map_observer,
|
||||
history_map: create_history_map::<T>(map_size),
|
||||
history_map: vec![T::default(); map_size],
|
||||
name: name,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -155,18 +145,16 @@ where
|
||||
{
|
||||
/// Create new MapFeedback using a map observer, and a map.
|
||||
/// The map can be shared.
|
||||
pub fn with_history_map(
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
) -> Self {
|
||||
pub fn with_history_map(name: &'static str, history_map: Vec<T>) -> Self {
|
||||
Self {
|
||||
map_observer: map_observer,
|
||||
history_map: history_map,
|
||||
name: name,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct MapNoveltiesMetadata {
|
||||
novelties: Vec<usize>,
|
||||
@ -206,11 +194,11 @@ where
|
||||
O: MapObserver<T>,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
history_map: Rc<RefCell<Vec<T>>>,
|
||||
/// The observer this feedback struct observes
|
||||
map_observer: Rc<RefCell<O>>,
|
||||
history_map: Vec<T>,
|
||||
/// Name identifier of this instance
|
||||
name: &'static str,
|
||||
/// Phantom Data of Reducer
|
||||
phantom: PhantomData<R>,
|
||||
phantom: PhantomData<(R, O)>,
|
||||
/// Track novel entries indexes
|
||||
novelties: Vec<usize>,
|
||||
}
|
||||
@ -254,6 +242,10 @@ where
|
||||
self.novelties.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, R, O> MapTrackerFeedback<T, R, O>
|
||||
@ -293,9 +285,10 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
pub type MaxMapFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
||||
pub type MinMapFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
||||
|
||||
pub type MaxMapTrackerFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
||||
pub type MinMapTrackerFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
||||
//pub type MaxMapTrackerFeedback<T, O> = MapFeedback<T, MaxReducer<T>, O>;
|
||||
//pub type MinMapTrackerFeedback<T, O> = MapFeedback<T, MinReducer<T>, O>;
|
||||
|
@ -2,7 +2,7 @@ use alloc::boxed::Box;
|
||||
use alloc::vec::Vec;
|
||||
use core::any::{Any, TypeId};
|
||||
use core::slice::{Iter, IterMut};
|
||||
use hashbrown::hash_map::{Values, ValuesMut};
|
||||
use hashbrown::hash_map::{Keys, Values, ValuesMut};
|
||||
use hashbrown::HashMap;
|
||||
|
||||
pub struct MetaMap {
|
||||
@ -241,11 +241,22 @@ impl MetaInstanceMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NamedAnyMap {
|
||||
map: HashMap<TypeId, HashMap<&'static str, Box<dyn Any>>>,
|
||||
pub trait AsAny {
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
}
|
||||
|
||||
impl NamedAnyMap {
|
||||
pub struct NamedAnyMap<B>
|
||||
where
|
||||
B: ?Sized + Any + AsAny,
|
||||
{
|
||||
map: HashMap<TypeId, HashMap<&'static str, Box<B>>>,
|
||||
}
|
||||
|
||||
impl<B> NamedAnyMap<B>
|
||||
where
|
||||
B: ?Sized + Any + AsAny,
|
||||
{
|
||||
pub fn get<T>(&self, name: &'static str) -> Option<&T>
|
||||
where
|
||||
T: Any,
|
||||
@ -254,7 +265,14 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get(&name)
|
||||
.map(|x| x.as_ref().downcast_ref::<T>().unwrap()),
|
||||
.map(|x| x.as_any().downcast_ref::<T>().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn by_typeid(&self, name: &'static str, typeid: &TypeId) -> Option<&B> {
|
||||
match self.map.get(typeid) {
|
||||
None => None,
|
||||
Some(h) => h.get(&name).map(|x| x.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -266,27 +284,42 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get_mut(&name)
|
||||
.map(|x| x.as_mut().downcast_mut::<T>().unwrap()),
|
||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> {
|
||||
match self.map.get_mut(typeid) {
|
||||
None => None,
|
||||
Some(h) => h.get_mut(&name).map(|x| x.as_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all<T>(
|
||||
&self,
|
||||
) -> Option<core::iter::Map<Values<'_, &'static str, Box<dyn Any>>, fn(&Box<dyn Any>) -> &T>>
|
||||
) -> Option<core::iter::Map<Values<'_, &'static str, Box<B>>, fn(&Box<B>) -> &T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get(&TypeId::of::<T>()) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values().map(|x| x.as_ref().downcast_ref::<T>().unwrap())),
|
||||
Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_by_typeid(
|
||||
&self,
|
||||
typeid: &TypeId,
|
||||
) -> Option<core::iter::Map<Values<'_, &'static str, Box<B>>, fn(&Box<B>) -> &B>> {
|
||||
match self.map.get(typeid) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values().map(|x| x.as_ref())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_mut<T>(
|
||||
&mut self,
|
||||
) -> Option<
|
||||
core::iter::Map<ValuesMut<'_, &'static str, Box<dyn Any>>, fn(&mut Box<dyn Any>) -> &mut T>,
|
||||
>
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, &'static str, Box<B>>, fn(&mut Box<B>) -> &mut T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
@ -294,23 +327,32 @@ impl NamedAnyMap {
|
||||
None => None,
|
||||
Some(h) => Some(
|
||||
h.values_mut()
|
||||
.map(|x| x.as_mut().downcast_mut::<T>().unwrap()),
|
||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert<T>(&mut self, t: T, name: &'static str)
|
||||
where
|
||||
T: Any,
|
||||
pub fn all_by_typeid_mut(
|
||||
&mut self,
|
||||
typeid: &TypeId,
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, &'static str, Box<B>>, fn(&mut Box<B>) -> &mut B>>
|
||||
{
|
||||
let typeid = TypeId::of::<T>();
|
||||
match self.map.get_mut(typeid) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values_mut().map(|x| x.as_mut())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_typeids(&self) -> Keys<'_, TypeId, HashMap<&'static str, Box<B>>> {
|
||||
self.map.keys()
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, val: Box<B>, name: &'static str) {
|
||||
let typeid = val.type_id();
|
||||
if !self.map.contains_key(&typeid) {
|
||||
self.map.insert(typeid, HashMap::default());
|
||||
}
|
||||
self.map
|
||||
.get_mut(&typeid)
|
||||
.unwrap()
|
||||
.insert(name, Box::new(t));
|
||||
self.map.get_mut(&typeid).unwrap().insert(name, val);
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
|
@ -1,15 +1,16 @@
|
||||
extern crate num;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use core::cell::RefCell;
|
||||
use core::any::Any;
|
||||
use core::slice::from_raw_parts_mut;
|
||||
use num::Integer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::serde_anymap::{SerdeAny, SliceMut};
|
||||
use crate::AflError;
|
||||
|
||||
/// Observers observe different information about the target.
|
||||
/// They can then be used by various sorts of feedback.
|
||||
pub trait Observer {
|
||||
pub trait Observer: SerdeAny + 'static {
|
||||
fn flush(&mut self) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
@ -19,6 +20,8 @@ pub trait Observer {
|
||||
fn post_exec(&mut self) -> Result<(), AflError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
/// A MapObserver observes the static map, as oftentimes used for afl-like coverage information
|
||||
@ -33,7 +36,7 @@ where
|
||||
fn map_mut(&mut self) -> &mut [T];
|
||||
|
||||
/// Get the initial value for reset()
|
||||
fn initial(&self) -> &T;
|
||||
fn initial(&self) -> T;
|
||||
|
||||
/// Get the initial value for reset()
|
||||
fn initial_mut(&mut self) -> &mut T;
|
||||
@ -44,44 +47,69 @@ where
|
||||
/// Reset the map
|
||||
fn reset_map(&mut self) -> Result<(), AflError> {
|
||||
// Normal memset, see https://rust.godbolt.org/z/Trs5hv
|
||||
let initial = self.initial();
|
||||
for i in self.map_mut().iter_mut() {
|
||||
*i = T::zero();
|
||||
*i = initial;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StdMapObserver<'a, T>
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
T: Integer + Copy + 'static,
|
||||
{
|
||||
map: &'a mut [T],
|
||||
map: SliceMut<'static, T>,
|
||||
initial: T,
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
impl<'a, T> Observer for StdMapObserver<'a, T>
|
||||
impl<T> Observer for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
T: Integer + Copy + 'static + serde::Serialize,
|
||||
{
|
||||
fn reset(&mut self) -> Result<(), AflError> {
|
||||
self.reset_map()
|
||||
}
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> MapObserver<T> for StdMapObserver<'a, T>
|
||||
impl<T> SerdeAny for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy + 'static + serde::Serialize,
|
||||
{
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MapObserver<T> for StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
fn map(&self) -> &[T] {
|
||||
&self.map
|
||||
match &self.map {
|
||||
SliceMut::Ref(r) => r,
|
||||
SliceMut::Owned(v) => v.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
fn map_mut(&mut self) -> &mut [T] {
|
||||
&mut self.map
|
||||
match &mut self.map {
|
||||
SliceMut::Ref(r) => r,
|
||||
SliceMut::Owned(v) => v.as_mut_slice()
|
||||
}
|
||||
}
|
||||
|
||||
fn initial(&self) -> &T {
|
||||
&self.initial
|
||||
fn initial(&self) -> T {
|
||||
self.initial
|
||||
}
|
||||
|
||||
fn initial_mut(&mut self) -> &mut T {
|
||||
@ -93,36 +121,29 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> StdMapObserver<'a, T>
|
||||
impl<T> StdMapObserver<T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
/// Creates a new MapObserver
|
||||
pub fn new(map: &'a mut [T]) -> Self {
|
||||
pub fn new(name: &'static str, map: &'static mut [T]) -> Self {
|
||||
let initial = if map.len() > 0 { map[0] } else { T::zero() };
|
||||
Self {
|
||||
map: map,
|
||||
map: SliceMut::Ref(map),
|
||||
initial: initial,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new MapObserver from a raw pointer
|
||||
pub fn new_from_ptr(map_ptr: *mut T, len: usize) -> Self {
|
||||
pub fn new_from_ptr(name: &'static str, map_ptr: *mut T, len: usize) -> Self {
|
||||
unsafe {
|
||||
let initial = if len > 0 { *map_ptr } else { T::zero() };
|
||||
StdMapObserver {
|
||||
map: from_raw_parts_mut(map_ptr, len),
|
||||
map: SliceMut::Ref(from_raw_parts_mut(map_ptr, len)),
|
||||
initial: initial,
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Into<Rc<RefCell<Self>>> for StdMapObserver<'a, T>
|
||||
where
|
||||
T: Integer + Copy,
|
||||
{
|
||||
fn into(self) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,10 @@ use alloc::boxed::Box;
|
||||
use core::any::{Any, TypeId};
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::slice::{Iter, IterMut};
|
||||
use hashbrown::hash_map::{Keys, Values, ValuesMut};
|
||||
|
||||
use crate::AflError;
|
||||
|
||||
pub fn pack_type_id(id: u64) -> TypeId {
|
||||
unsafe { *(&id as *const u64 as *const TypeId) }
|
||||
@ -199,3 +203,241 @@ impl SerdeAnyMap {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NamedSerdeAnyMap<B>
|
||||
where
|
||||
B: ?Sized + SerdeAny,
|
||||
{
|
||||
map: HashMap<u64, HashMap<u64, Box<B>>>,
|
||||
}
|
||||
|
||||
impl<B> NamedSerdeAnyMap<B>
|
||||
where
|
||||
B: ?Sized + SerdeAny,
|
||||
{
|
||||
pub fn get<T>(&self, name: &'static str) -> Option<&T>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
||||
.map(|x| x.as_any().downcast_ref::<T>().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn by_typeid(&self, name: &'static str, typeid: &TypeId) -> Option<&B> {
|
||||
match self.map.get(&unpack_type_id(*typeid)) {
|
||||
None => None,
|
||||
Some(h) => h.get(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())).map(|x| x.as_ref()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_mut<T>(&mut self, name: &'static str) -> Option<&mut T>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
||||
None => None,
|
||||
Some(h) => h
|
||||
.get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes()))
|
||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn by_typeid_mut(&mut self, name: &'static str, typeid: &TypeId) -> Option<&mut B> {
|
||||
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
||||
None => None,
|
||||
Some(h) => h.get_mut(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())).map(|x| x.as_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all<T>(
|
||||
&self,
|
||||
) -> Option<core::iter::Map<Values<'_, u64, Box<B>>, fn(&Box<B>) -> &T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_by_typeid(
|
||||
&self,
|
||||
typeid: &TypeId,
|
||||
) -> Option<core::iter::Map<Values<'_, u64, Box<B>>, fn(&Box<B>) -> &B>> {
|
||||
match self.map.get(&unpack_type_id(*typeid)) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values().map(|x| x.as_ref())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_all_mut<T>(
|
||||
&mut self,
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, u64, Box<B>>, fn(&mut Box<B>) -> &mut T>>
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get_mut(&unpack_type_id(TypeId::of::<T>())) {
|
||||
None => None,
|
||||
Some(h) => Some(
|
||||
h.values_mut()
|
||||
.map(|x| x.as_any_mut().downcast_mut::<T>().unwrap()),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_by_typeid_mut(
|
||||
&mut self,
|
||||
typeid: &TypeId,
|
||||
) -> Option<core::iter::Map<ValuesMut<'_, u64, Box<B>>, fn(&mut Box<B>) -> &mut B>>
|
||||
{
|
||||
match self.map.get_mut(&unpack_type_id(*typeid)) {
|
||||
None => None,
|
||||
Some(h) => Some(h.values_mut().map(|x| x.as_mut())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_typeids(&self) -> core::iter::Map<Keys<'_, u64, HashMap<u64, Box<B>>>, fn(&u64) -> TypeId> {
|
||||
self.map.keys().map(|x| pack_type_id(*x))
|
||||
}
|
||||
|
||||
pub fn for_each(&self, func: fn(&TypeId, &Box<B>) -> Result<(), AflError>) -> Result<(), AflError> {
|
||||
for (id, h) in self.map.iter() {
|
||||
for x in h.values() {
|
||||
func(&pack_type_id(*id), x)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn for_each_mut(&mut self, func: fn(&TypeId, &mut Box<B>) -> Result<(), AflError>) -> Result<(), AflError> {
|
||||
for (id, h) in self.map.iter_mut() {
|
||||
for x in h.values_mut() {
|
||||
func(&pack_type_id(*id), x)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, val: Box<B>, name: &'static str) {
|
||||
let id = unpack_type_id(val.type_id());
|
||||
if !self.map.contains_key(&id) {
|
||||
self.map.insert(id, HashMap::default());
|
||||
}
|
||||
self.map.get_mut(&id).unwrap().insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), val);
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
pub fn contains_type<T>(&self) -> bool
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
self.map.contains_key(&unpack_type_id(TypeId::of::<T>()))
|
||||
}
|
||||
|
||||
pub fn contains<T>(&self, name: &'static str) -> bool
|
||||
where
|
||||
T: Any,
|
||||
{
|
||||
match self.map.get(&unpack_type_id(TypeId::of::<T>())) {
|
||||
None => false,
|
||||
Some(h) => h.contains_key(&xxhash_rust::xxh3::xxh3_64(name.as_bytes())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
map: HashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> Default for NamedSerdeAnyMap<B>
|
||||
where
|
||||
B: ?Sized + SerdeAny,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum Ptr<'a, T: 'a + ?Sized> {
|
||||
Ref(&'a T),
|
||||
Owned(Box<T>),
|
||||
}
|
||||
|
||||
impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for Ptr<'a, T>
|
||||
where
|
||||
Box<T>: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(Ptr::Owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum PtrMut<'a, T: 'a + ?Sized> {
|
||||
Ref(&'a mut T),
|
||||
Owned(Box<T>),
|
||||
}
|
||||
|
||||
impl<'de, 'a, T: 'a + ?Sized> Deserialize<'de> for PtrMut<'a, T>
|
||||
where
|
||||
Box<T>: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(PtrMut::Owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum Slice<'a, T: 'a + Sized> {
|
||||
Ref(&'a [T]),
|
||||
Owned(Vec<T>),
|
||||
}
|
||||
|
||||
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for Slice<'a, T>
|
||||
where
|
||||
Vec<T>: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(Slice::Owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub enum SliceMut<'a, T: 'a + Sized> {
|
||||
Ref(&'a mut [T]),
|
||||
Owned(Vec<T>),
|
||||
}
|
||||
|
||||
impl<'de, 'a, T: 'a + Sized> Deserialize<'de> for SliceMut<'a, T>
|
||||
where
|
||||
Vec<T>: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Deserialize::deserialize(deserializer).map(SliceMut::Owned)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,17 +2,16 @@ pub mod mutational;
|
||||
pub use mutational::StdMutationalStage;
|
||||
|
||||
use crate::corpus::Corpus;
|
||||
use crate::engines::State;
|
||||
use crate::engines::{Engine, State};
|
||||
use crate::events::EventManager;
|
||||
use crate::executors::Executor;
|
||||
use crate::inputs::Input;
|
||||
use crate::utils::Rand;
|
||||
use crate::AflError;
|
||||
|
||||
pub trait Stage<S, EM, E, C, I, R>
|
||||
pub trait Stage<EM, E, C, I, R>
|
||||
where
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
@ -22,9 +21,9 @@ where
|
||||
fn perform(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<I, R>,
|
||||
corpus: &C,
|
||||
events: &mut EM,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
input: &I,
|
||||
) -> Result<(), AflError>;
|
||||
}
|
||||
|
@ -5,18 +5,17 @@ use crate::executors::Executor;
|
||||
use crate::inputs::Input;
|
||||
use crate::mutators::Mutator;
|
||||
use crate::stages::Corpus;
|
||||
use crate::stages::Stage;
|
||||
use crate::stages::{Engine, Stage};
|
||||
use crate::utils::Rand;
|
||||
use crate::AflError;
|
||||
use crate::{engines::State, events::Event};
|
||||
|
||||
// TODO multi mutators stage
|
||||
|
||||
pub trait MutationalStage<M, S, EM, E, C, I, R>: Stage<S, EM, E, C, I, R>
|
||||
pub trait MutationalStage<M, EM, E, C, I, R>: Stage<EM, E, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
@ -38,9 +37,9 @@ where
|
||||
fn perform_mutational(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<I, R>,
|
||||
corpus: &C,
|
||||
events: &mut EM,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
input: &I,
|
||||
) -> Result<(), AflError> {
|
||||
let num = self.iterations(rand);
|
||||
@ -49,7 +48,7 @@ where
|
||||
self.mutator_mut()
|
||||
.mutate(rand, corpus, &mut input_mut, i as i32)?;
|
||||
|
||||
let fitness = state.evaluate_input(&input_mut)?;
|
||||
let fitness = state.evaluate_input(&input_mut, engine)?;
|
||||
|
||||
self.mutator_mut()
|
||||
.post_exec(fitness, &input_mut, i as i32)?;
|
||||
@ -57,7 +56,7 @@ where
|
||||
let testcase_maybe = state.testcase_if_interesting(input_mut, fitness)?;
|
||||
if let Some(testcase) = testcase_maybe {
|
||||
//corpus.entries()[idx]
|
||||
events.fire(Event::NewTestcase {
|
||||
engine.events_manager_mut().fire(Event::NewTestcase {
|
||||
sender_id: 0,
|
||||
testcase: testcase,
|
||||
phantom: PhantomData,
|
||||
@ -69,26 +68,24 @@ where
|
||||
}
|
||||
|
||||
/// The default mutational stage
|
||||
pub struct StdMutationalStage<M, S, EM, E, C, I, R>
|
||||
pub struct StdMutationalStage<M, EM, E, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
mutator: M,
|
||||
phantom: PhantomData<(S, EM, E, C, I, R)>,
|
||||
phantom: PhantomData<(EM, E, C, I, R)>,
|
||||
}
|
||||
|
||||
impl<M, S, EM, E, C, I, R> MutationalStage<M, S, EM, E, C, I, R>
|
||||
for StdMutationalStage<M, S, EM, E, C, I, R>
|
||||
impl<M, EM, E, C, I, R> MutationalStage<M, EM, E, C, I, R>
|
||||
for StdMutationalStage<M, EM, E, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
@ -105,11 +102,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, S, EM, E, C, I, R> Stage<S, EM, E, C, I, R> for StdMutationalStage<M, S, EM, E, C, I, R>
|
||||
impl<M, EM, E, C, I, R> Stage<EM, E, C, I, R> for StdMutationalStage<M, EM, E, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
@ -118,20 +114,19 @@ where
|
||||
fn perform(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<I, R>,
|
||||
corpus: &C,
|
||||
events: &mut EM,
|
||||
engine: &mut Engine<EM, E, C, I, R>,
|
||||
input: &I,
|
||||
) -> Result<(), AflError> {
|
||||
self.perform_mutational(rand, state, corpus, events, input)
|
||||
self.perform_mutational(rand, state, corpus, engine, input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<M, S, EM, E, C, I, R> StdMutationalStage<M, S, EM, E, C, I, R>
|
||||
impl<M, EM, E, C, I, R> StdMutationalStage<M, EM, E, C, I, R>
|
||||
where
|
||||
M: Mutator<C, I, R>,
|
||||
S: State<C, E, I, R>,
|
||||
EM: EventManager<S, C, E, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
E: Executor<I>,
|
||||
C: Corpus<I, R>,
|
||||
I: Input,
|
||||
|
Loading…
x
Reference in New Issue
Block a user