State is now a struct
This commit is contained in:
parent
ff983ecf23
commit
de4fb23f31
@ -19,167 +19,12 @@ 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>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
/// Get executions
|
||||
fn executions(&self) -> usize;
|
||||
|
||||
/// Set executions
|
||||
fn set_executions(&mut self, executions: usize);
|
||||
|
||||
fn start_time(&self) -> u64;
|
||||
fn set_start_time(&mut self, ms: u64);
|
||||
|
||||
fn executions_over_seconds(&self) -> u64 {
|
||||
let elapsed = current_milliseconds() - self.start_time();
|
||||
if elapsed == 0 {
|
||||
return 0;
|
||||
}
|
||||
let elapsed = elapsed / 1000;
|
||||
if elapsed == 0 {
|
||||
0
|
||||
} else {
|
||||
(self.executions() as u64) / elapsed
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all the metadatas into an HashMap
|
||||
fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>;
|
||||
|
||||
/// Get all the metadatas into an HashMap (mutable)
|
||||
fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>>;
|
||||
|
||||
/// Add a metadata
|
||||
fn add_metadata(&mut self, meta: Box<dyn StateMetadata>) {
|
||||
self.metadatas_mut().insert(meta.name(), meta);
|
||||
}
|
||||
|
||||
/// Returns vector of feebacks
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>];
|
||||
|
||||
/// Returns vector of feebacks (mutable)
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>;
|
||||
|
||||
/// Adds a feedback
|
||||
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;
|
||||
|
||||
/// Runs the input and triggers observers and feedback
|
||||
fn evaluate_input(&mut self, input: &I) -> Result<u32, AflError> {
|
||||
self.executor_mut().reset_observers()?;
|
||||
self.executor_mut().run_target(&input)?;
|
||||
self.set_executions(self.executions() + 1);
|
||||
self.executor_mut().post_exec_observers()?;
|
||||
|
||||
let mut fitness = 0;
|
||||
let observers = self.executor().observers();
|
||||
for feedback in self.feedbacks_mut() {
|
||||
fitness += feedback.is_interesting(&input, observers)?;
|
||||
}
|
||||
Ok(fitness)
|
||||
}
|
||||
|
||||
/// Resets all current feedbacks
|
||||
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)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates a new testcase, appending the metadata from each feedback
|
||||
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() {
|
||||
feedback.append_metadata(&mut testcase)?;
|
||||
}
|
||||
|
||||
Ok(testcase)
|
||||
}
|
||||
|
||||
/// Create a testcase from this input, if it's intersting
|
||||
fn testcase_if_interesting(
|
||||
&mut self,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<Testcase<I>>, AflError> {
|
||||
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
|
||||
fn add_if_interesting(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<usize>, AflError> {
|
||||
if fitness > 0 {
|
||||
let testcase = self.input_to_testcase(input, fitness)?;
|
||||
Ok(Some(corpus.add(testcase)))
|
||||
} else {
|
||||
self.discard_input(&input)?;
|
||||
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>
|
||||
pub struct State<C, E, I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
@ -196,60 +41,167 @@ where
|
||||
phantom: PhantomData<(C, R)>,
|
||||
}
|
||||
|
||||
impl<C, E, I, R> State<C, E, I, R> for StdState<C, E, I, R>
|
||||
impl<C, E, I, R> State<C, E, I, R>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
E: Executor<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
{
|
||||
fn executions(&self) -> usize {
|
||||
/// Get executions
|
||||
pub fn executions(&self) -> usize {
|
||||
self.executions
|
||||
}
|
||||
|
||||
fn set_executions(&mut self, executions: usize) {
|
||||
/// Set executions
|
||||
pub fn set_executions(&mut self, executions: usize){
|
||||
self.executions = executions
|
||||
}
|
||||
|
||||
fn start_time(&self) -> u64 {
|
||||
pub fn start_time(&self) -> u64{
|
||||
self.start_time
|
||||
}
|
||||
fn set_start_time(&mut self, ms: u64) {
|
||||
pub fn set_start_time(&mut self, ms: u64) {
|
||||
self.start_time = ms
|
||||
}
|
||||
|
||||
fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>> {
|
||||
pub fn executions_over_seconds(&self) -> u64 {
|
||||
let elapsed = current_milliseconds() - self.start_time();
|
||||
if elapsed == 0 {
|
||||
return 0;
|
||||
}
|
||||
let elapsed = elapsed / 1000;
|
||||
if elapsed == 0 {
|
||||
0
|
||||
} else {
|
||||
(self.executions() as u64) / elapsed
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all the metadatas into an HashMap
|
||||
pub fn metadatas(&self) -> &HashMap<&'static str, Box<dyn StateMetadata>>{
|
||||
&self.metadatas
|
||||
}
|
||||
|
||||
fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>> {
|
||||
/// Get all the metadatas into an HashMap (mutable)
|
||||
pub fn metadatas_mut(&mut self) -> &mut HashMap<&'static str, Box<dyn StateMetadata>>{
|
||||
&mut self.metadatas
|
||||
}
|
||||
|
||||
fn feedbacks(&self) -> &[Box<dyn Feedback<I>>] {
|
||||
/// Add a metadata
|
||||
pub fn add_metadata(&mut self, meta: Box<dyn StateMetadata>) {
|
||||
self.metadatas_mut().insert(meta.name(), meta);
|
||||
}
|
||||
|
||||
/// Returns vector of feebacks
|
||||
pub fn feedbacks(&self) -> &[Box<dyn Feedback<I>>]{
|
||||
&self.feedbacks
|
||||
}
|
||||
|
||||
fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>> {
|
||||
/// Returns vector of feebacks (mutable)
|
||||
pub fn feedbacks_mut(&mut self) -> &mut Vec<Box<dyn Feedback<I>>>{
|
||||
&mut self.feedbacks
|
||||
}
|
||||
|
||||
fn executor(&self) -> &E {
|
||||
&self.executor
|
||||
/// Adds a feedback
|
||||
pub fn add_feedback(&mut self, feedback: Box<dyn Feedback<I>>) {
|
||||
self.feedbacks_mut().push(feedback);
|
||||
}
|
||||
|
||||
fn executor_mut(&mut self) -> &mut E {
|
||||
&mut self.executor
|
||||
}
|
||||
}
|
||||
/// Runs the input and triggers observers and feedback
|
||||
pub fn evaluate_input<FE, EM>(&mut self, input: &I, engine: &FE) -> Result<u32, AflError>
|
||||
where
|
||||
FE: FuzzingEngine<EM, E, C, I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
{
|
||||
engine.executor_mut().reset_observers()?;
|
||||
engine.executor_mut().run_target(&input)?;
|
||||
self.set_executions(self.executions() + 1);
|
||||
engine.executor_mut().post_exec_observers()?;
|
||||
|
||||
let mut fitness = 0;
|
||||
let observers = self.executor().observers();
|
||||
for feedback in self.feedbacks_mut() {
|
||||
fitness += feedback.is_interesting(&input, observers)?;
|
||||
}
|
||||
Ok(fitness)
|
||||
}
|
||||
|
||||
/// Resets all current feedbacks
|
||||
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)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Creates a new testcase, appending the metadata from each feedback
|
||||
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() {
|
||||
feedback.append_metadata(&mut testcase)?;
|
||||
}
|
||||
|
||||
Ok(testcase)
|
||||
}
|
||||
|
||||
/// Create a testcase from this input, if it's intersting
|
||||
pub fn testcase_if_interesting(
|
||||
&mut self,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<Testcase<I>>, AflError> {
|
||||
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
|
||||
pub fn add_if_interesting(
|
||||
&mut self,
|
||||
corpus: &mut C,
|
||||
input: I,
|
||||
fitness: u32,
|
||||
) -> Result<Option<usize>, AflError> {
|
||||
if fitness > 0 {
|
||||
let testcase = self.input_to_testcase(input, fitness)?;
|
||||
Ok(Some(corpus.add(testcase)))
|
||||
} else {
|
||||
self.discard_input(&input)?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_initial_inputs<G, EM>(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
corpus: &mut C,
|
||||
generator: &mut G,
|
||||
events: &mut EM,
|
||||
num: usize,
|
||||
) -> Result<(), AflError>
|
||||
where
|
||||
G: Generator<I, R>,
|
||||
EM: EventManager<C, E, I, R>,
|
||||
{
|
||||
for _ in 0..num {
|
||||
let input = generator.generate(rand)?;
|
||||
let fitness = self.evaluate_input(&input)?;
|
||||
self.add_if_interesting(corpus, input, fitness)?;
|
||||
events.fire(Event::LoadInitial {
|
||||
sender_id: 0,
|
||||
phantom: PhantomData,
|
||||
})?;
|
||||
}
|
||||
events.process(self, corpus)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 {
|
||||
Self {
|
||||
executions: 0,
|
||||
@ -263,27 +215,38 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Engine<S, EM, E, C, I, R>
|
||||
pub trait FuzzingEngine<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>>];
|
||||
|
||||
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>>>;
|
||||
|
||||
fn add_stage(&mut self, stage: Box<dyn Stage<S, 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 events_manager(&self) -> &EM;
|
||||
|
||||
fn events_manager_mut(&mut self) -> &mut EM;
|
||||
|
||||
/// Return the executor
|
||||
fn executor(&self) -> &E;
|
||||
|
||||
/// Return the executor (mutable)
|
||||
fn executor_mut(&mut self) -> &mut E;
|
||||
|
||||
// TODO additional executors, Vec<Box<dyn Executor<I>>>
|
||||
|
||||
fn fuzz_one(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<C, E, I, R>,
|
||||
corpus: &mut C,
|
||||
events: &mut EM,
|
||||
) -> Result<usize, AflError> {
|
||||
@ -309,7 +272,7 @@ where
|
||||
fn fuzz_loop(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<C, E, I, R>,
|
||||
corpus: &mut C,
|
||||
events: &mut EM,
|
||||
) -> Result<(), AflError> {
|
||||
@ -329,41 +292,38 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StdEngine<S, EM, E, C, I, R>
|
||||
pub struct StdFuzzingEngine<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>>>,
|
||||
stages: Vec<Box<dyn Stage<EM, E, C, I, R>>>,
|
||||
phantom: PhantomData<EM>,
|
||||
}
|
||||
|
||||
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> FuzzingEngine<EM, E, C, I, R> for StdFuzzingEngine<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> StdFuzzingEngine<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,
|
||||
|
@ -9,10 +9,9 @@ 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,7 +21,7 @@ where
|
||||
fn perform(
|
||||
&mut self,
|
||||
rand: &mut R,
|
||||
state: &mut S,
|
||||
state: &mut State<C, E, I, R>,
|
||||
corpus: &C,
|
||||
events: &mut EM,
|
||||
input: &I,
|
||||
|
Loading…
x
Reference in New Issue
Block a user