diff --git a/src/corpus/mod.rs b/src/corpus/mod.rs index 93e5da42f6..a5491a7559 100644 --- a/src/corpus/mod.rs +++ b/src/corpus/mod.rs @@ -1,3 +1,4 @@ +extern crate alloc; pub mod testcase; pub use testcase::{Testcase, TestcaseMetadata}; @@ -5,10 +6,10 @@ use crate::inputs::Input; use crate::utils::{HasRand, Rand}; use crate::AflError; +use alloc::rc::Rc; use core::cell::RefCell; -use std::marker::PhantomData; +use core::marker::PhantomData; use std::path::PathBuf; -use std::rc::Rc; pub trait HasEntriesVec where diff --git a/src/corpus/testcase.rs b/src/corpus/testcase.rs index e80831ee67..3694c87e2c 100644 --- a/src/corpus/testcase.rs +++ b/src/corpus/testcase.rs @@ -1,10 +1,11 @@ +extern crate alloc; use crate::inputs::Input; use crate::AflError; -use hashbrown::HashMap; +use alloc::rc::Rc; use core::cell::RefCell; +use hashbrown::HashMap; use std::path::PathBuf; -use std::rc::Rc; // TODO: Give example /// Metadata for a testcase diff --git a/src/engines/mod.rs b/src/engines/mod.rs index d8ab27940f..313c3deaca 100644 --- a/src/engines/mod.rs +++ b/src/engines/mod.rs @@ -1,19 +1,16 @@ -use crate::corpus::testcase::{Testcase, TestcaseMetadata}; -use crate::corpus::Corpus; -use crate::executors::Executor; +extern crate alloc; +use crate::corpus::testcase::Testcase; use crate::feedbacks::Feedback; use crate::inputs::Input; use crate::stages::Stage; use crate::AflError; +use alloc::rc::Rc; use core::cell::RefCell; -use std::rc::Rc; -pub trait Engine +pub trait Engine where I: Input, - C: Corpus, - E: Executor, { fn feedbacks(&self) -> &Vec>>; @@ -31,17 +28,12 @@ where self.stages_mut().push(stage); } - fn executor(&self) -> &E; - - fn executor_mut(&mut self) -> &mut E; - fn fuzz_one(&mut self, testcase: &Rc>>) -> Result<(), AflError> { for stage in self.stages_mut() { stage.perform(&testcase)?; } Ok(()) } - } pub struct DefaultEngine @@ -52,11 +44,9 @@ where stages: Vec>>, } -impl Engine for DefaultEngine +impl Engine for DefaultEngine where I: Input, - C: Corpus, - E: Executor, { fn feedbacks(&self) -> &Vec>> { &self.feedbacks @@ -73,61 +63,39 @@ where fn stages_mut(&mut self) -> &mut Vec>> { &mut self.stages } - } impl DefaultEngine where I: Input, { - pub fn new(executor: E) -> Self { + pub fn new() -> Self { DefaultEngine { feedbacks: vec![], stages: vec![], } } - pub fn new_rr(executor: E) -> Rc> { - Rc::new(RefCell::new(Self::new(executor))) + pub fn new_rr() -> Rc> { + Rc::new(RefCell::new(Self::new())) } } -pub struct FuzzState -where - I: Input, - C: Corpus, -{ - - corpus: C, - current_input: Option, - -} - -impl FuzzState -where - I: Input, - C: Corpus, -{ - pub fn new(corpus: C) -> Self { - Self{corpus: corpus, current_input: None} - } -} - - #[cfg(test)] mod tests { use crate::corpus::{Corpus, InMemoryCorpus, Testcase}; - use crate::engines::{DefaultEngine, Engine, FuzzState}; + use crate::engines::{DefaultEngine, Engine}; use crate::executors::inmemory::InMemoryExecutor; use crate::executors::{Executor, ExitKind}; use crate::inputs::bytes::BytesInput; - use crate::mutators::DefaultScheduledMutator; - use crate::mutators::scheduled::mutation_bitflip; + use crate::mutators::scheduled::{ + mutation_bitflip, ComposedByMutations, DefaultScheduledMutator, + }; use crate::stages::mutational::DefaultMutationalStage; - use crate::stages::Stage; + use crate::utils::Xoshiro256StarRand; - fn harness(_executor: &dyn Executor, _buf: &[u8]) -> ExitKind { + fn harness(_executor: &dyn Executor, _buf: &[u8]) -> ExitKind { ExitKind::Ok } @@ -135,15 +103,14 @@ mod tests { fn test_engine() { let rand = Xoshiro256StarRand::preseeded_rr(); - let corpus = InMemoryCorpus::::new(&rand); + let mut corpus = InMemoryCorpus::::new(&rand); let testcase = Testcase::new_rr(BytesInput::new(vec![0; 4])); corpus.add(testcase); - let executor = InMemoryExecutor::new(harness); - let state = FuzzState::new(corpus); - let engine = DefaultEngine::new(executor); - let mutator = DefaultScheduledMutator::new(&rand); + let executor = InMemoryExecutor::new_rr(harness); + let mut engine = DefaultEngine::new(); + let mut mutator = DefaultScheduledMutator::new(&rand); mutator.add_mutation(mutation_bitflip); - let stage = DefaultMutationalStage::new(&rand, &engine, mutator); + let stage = DefaultMutationalStage::new(&rand, &executor, mutator); engine.add_stage(Box::new(stage)); engine.fuzz_one(&corpus.next().unwrap()).unwrap(); } diff --git a/src/executors/inmemory.rs b/src/executors/inmemory.rs index 8e4e6cc20c..6b26d06cac 100644 --- a/src/executors/inmemory.rs +++ b/src/executors/inmemory.rs @@ -1,32 +1,34 @@ -use crate::executors::Corpus; +extern crate alloc; +use crate::feedbacks::Feedback; use crate::inputs::Input; use crate::observers::Observer; use crate::AflError; +use alloc::rc::Rc; +use core::cell::RefCell; use crate::executors::{Executor, ExitKind}; use std::os::raw::c_void; use std::ptr; -type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; +type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; -pub struct InMemoryExecutor +pub struct InMemoryExecutor where I: Input, - C: Corpus, { observers: Vec>, - harness: HarnessFunction, + harness: HarnessFunction, + feedbacks: Vec>>, } static mut CURRENT_INMEMORY_EXECUTOR_PTR: *const c_void = ptr::null(); -impl Executor for InMemoryExecutor +impl Executor for InMemoryExecutor where I: Input, - C: Corpus, { - fn run_target(&mut self, input: &mut I) -> Result { + fn run_target(&mut self, input: &I) -> Result { let bytes = input.serialize()?; unsafe { CURRENT_INMEMORY_EXECUTOR_PTR = self as *const InMemoryExecutor as *const c_void; @@ -59,22 +61,38 @@ where fn observers(&self) -> &Vec> { &self.observers } + + fn feedbacks(&self) -> &Vec>> { + &self.feedbacks + } + + fn feedbacks_mut(&mut self) -> &mut Vec>> { + &mut self.feedbacks + } + + fn add_feedback(&mut self, feedback: Box>) { + self.feedbacks_mut().push(feedback); + } } -impl InMemoryExecutor +impl InMemoryExecutor where I: Input, - C: Corpus, { - pub fn new(harness_fn: HarnessFunction) -> Self { + pub fn new(harness_fn: HarnessFunction) -> Self { unsafe { - os_signals::setup_crash_handlers::(); + os_signals::setup_crash_handlers::(); } InMemoryExecutor { observers: vec![], + feedbacks: vec![], harness: harness_fn, } } + + pub fn new_rr(harness_fn: HarnessFunction) -> Rc> { + Rc::new(RefCell::new(Self::new(harness_fn))) + } } #[cfg(unix)] @@ -167,8 +185,7 @@ compile_error!("InMemoryExecutor not yet supported on this OS"); #[cfg(test)] mod tests { - use crate::executors::Corpus; -use crate::executors::inmemory::InMemoryExecutor; + use crate::executors::inmemory::InMemoryExecutor; use crate::executors::{Executor, ExitKind}; use crate::inputs::Input; use crate::observers::Observer; @@ -196,16 +213,16 @@ use crate::executors::inmemory::InMemoryExecutor; } } - /*fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { + fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { println! {"Fake exec with buf of len {}", buf.len()}; ExitKind::Ok - }*/ + } #[test] fn test_inmem_post_exec() { - //let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop); + let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop); let nopserver = Nopserver {}; - //in_mem_executor.add_observer(Box::new(nopserver)); + in_mem_executor.add_observer(Box::new(nopserver)); assert_eq!(in_mem_executor.post_exec_observers().is_err(), true); } @@ -213,6 +230,6 @@ use crate::executors::inmemory::InMemoryExecutor; fn test_inmem_exec() { let mut in_mem_executor = InMemoryExecutor::new(test_harness_fn_nop); let mut input = NopInput {}; - //assert!(in_mem_executor.run_target(&mut input).is_ok()); + assert!(in_mem_executor.run_target(&mut input).is_ok()); } } diff --git a/src/executors/mod.rs b/src/executors/mod.rs index 764254add7..25aaf8e3f1 100644 --- a/src/executors/mod.rs +++ b/src/executors/mod.rs @@ -1,14 +1,14 @@ +extern crate alloc; pub mod inmemory; use crate::corpus::Testcase; -use core::cell::RefCell; -use std::rc::Rc; -use crate::corpus::Corpus; use crate::corpus::TestcaseMetadata; use crate::feedbacks::Feedback; use crate::inputs::Input; use crate::observers::Observer; use crate::AflError; +use alloc::rc::Rc; +use core::cell::RefCell; pub enum ExitKind { Ok, @@ -19,13 +19,12 @@ pub enum ExitKind { // TODO unbox input -pub trait Executor +pub trait Executor where I: Input, - C: Corpus, { /// Instruct the target about the input and run - fn run_target(&mut self, input: &mut I) -> Result; + fn run_target(&mut self, input: &I) -> Result; /// Reset the state of all the observes linked to this executor fn reset_observers(&mut self) -> Result<(), AflError>; @@ -45,21 +44,20 @@ where /// Returns vector of feebacks fn feedbacks(&self) -> &Vec>>; + /// Returns vector of feebacks (mutable) + fn feedbacks_mut(&mut self) -> &mut Vec>>; + // TODO: Move to another struct, like evaluator? // In any case, the dependency on Corpus should probably go /// Runs the input and triggers observers and feedback - fn evaluate_input( - &mut self, - corpus: &mut C, - input: &mut I, - ) -> Result { + fn evaluate_input(&mut self, input: &I) -> Result { self.reset_observers()?; self.run_target(input)?; self.post_exec_observers()?; let mut metadatas: Vec> = vec![]; let mut rate_acc = 0; - for feedback in self.feedbacks() { + for feedback in self.feedbacks_mut() { let (rate, meta) = feedback.is_interesting(input); rate_acc += rate; if let Some(m) = meta { @@ -72,12 +70,11 @@ where for meta in metadatas { new_entry.borrow_mut().add_metadata(meta); } - corpus.add(new_entry); + //TODO corpus.add(new_entry); Ok(true) } else { Ok(false) } } - } diff --git a/src/feedbacks/mod.rs b/src/feedbacks/mod.rs index 0f28525f33..2ecf56eac5 100644 --- a/src/feedbacks/mod.rs +++ b/src/feedbacks/mod.rs @@ -1,12 +1,13 @@ +extern crate alloc; extern crate num; use crate::corpus::TestcaseMetadata; use crate::inputs::Input; use crate::observers::MapObserver; -use num::Integer; use core::cell::RefCell; -use std::marker::PhantomData; +use core::marker::PhantomData; +use num::Integer; pub trait Feedback where diff --git a/src/inputs/bytes.rs b/src/inputs/bytes.rs index b096dab1bb..b221b119f1 100644 --- a/src/inputs/bytes.rs +++ b/src/inputs/bytes.rs @@ -1,3 +1,4 @@ +extern crate alloc; use crate::inputs::{HasBytesVec, HasTargetBytes, Input}; use crate::AflError; diff --git a/src/inputs/mod.rs b/src/inputs/mod.rs index ecedbe9e3d..f9024b7c49 100644 --- a/src/inputs/mod.rs +++ b/src/inputs/mod.rs @@ -1,3 +1,4 @@ +extern crate alloc; pub mod bytes; pub use bytes::BytesInput; diff --git a/src/lib.rs b/src/lib.rs index 12cf09cda8..31723f3cb9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +extern crate alloc; use std::io; use thiserror::Error; diff --git a/src/mutators/mod.rs b/src/mutators/mod.rs index d25faf5510..878e73ace9 100644 --- a/src/mutators/mod.rs +++ b/src/mutators/mod.rs @@ -1,9 +1,10 @@ +extern crate alloc; pub mod scheduled; +pub use scheduled::ComposedByMutations; pub use scheduled::DefaultScheduledMutator; pub use scheduled::HavocBytesMutator; pub use scheduled::ScheduledMutator; -use crate::corpus::Corpus; use crate::inputs::Input; use crate::utils::HasRand; use crate::AflError; diff --git a/src/mutators/scheduled.rs b/src/mutators/scheduled.rs index a87d720d81..11350a05a4 100644 --- a/src/mutators/scheduled.rs +++ b/src/mutators/scheduled.rs @@ -1,12 +1,12 @@ -use crate::corpus::Corpus; +extern crate alloc; use crate::inputs::{HasBytesVec, Input}; use crate::mutators::Mutator; use crate::utils::{HasRand, Rand}; use crate::AflError; +use alloc::rc::Rc; use core::cell::RefCell; -use std::marker::PhantomData; -use std::rc::Rc; +use core::marker::PhantomData; /// The generic function type that identifies mutations type MutationFunction = fn(&mut M, &mut I) -> Result<(), AflError>; @@ -58,21 +58,19 @@ where } } -pub struct DefaultScheduledMutator<'a, I, C, R> +pub struct DefaultScheduledMutator<'a, I, R> where I: Input, - C: Corpus, R: Rand, { rand: Rc>, mutations: Vec>, } -impl<'a, I, C, R> HasRand for DefaultScheduledMutator<'_, I, C, R> +impl<'a, I, R> HasRand for DefaultScheduledMutator<'_, I, R> where I: Input, R: Rand, - C: Corpus, { type R = R; @@ -81,23 +79,20 @@ where } } - -impl<'a, I, C, R> Mutator for DefaultScheduledMutator<'_, I, C, R> +impl<'a, I, R> Mutator for DefaultScheduledMutator<'_, I, R> where I: Input, R: Rand, - C: Corpus, { fn mutate(&mut self, input: &mut I, _stage_idx: i32) -> Result<(), AflError> { self.scheduled_mutate(input, _stage_idx) } } -impl<'a, I, C, R> ComposedByMutations for DefaultScheduledMutator<'_, I, C, R> +impl<'a, I, R> ComposedByMutations for DefaultScheduledMutator<'_, I, R> where I: Input, R: Rand, - C: Corpus, { fn mutation_by_idx(&self, index: usize) -> Result, AflError> { if index >= self.mutations.len() { @@ -115,19 +110,17 @@ where } } -impl<'a, I, C, R> ScheduledMutator for DefaultScheduledMutator<'_, I, C, R> +impl<'a, I, R> ScheduledMutator for DefaultScheduledMutator<'_, I, R> where I: Input, R: Rand, - C: Corpus, { // Just use the default methods } -impl<'a, I, C, R> DefaultScheduledMutator<'a, I, C, R> +impl<'a, I, R> DefaultScheduledMutator<'a, I, R> where I: Input, - C: Corpus, R: Rand, { /// Create a new DefaultScheduledMutator instance without mutations and corpus @@ -139,16 +132,12 @@ where } /// Create a new DefaultScheduledMutator instance specifying mutations and corpus too - pub fn new_all( - rand: &Rc>, - mutations: Vec>, - ) -> Self { + pub fn new_all(rand: &Rc>, mutations: Vec>) -> Self { DefaultScheduledMutator { rand: Rc::clone(rand), mutations: mutations, } } - } /// Bitflip mutation for inputs with a bytes vector @@ -209,15 +198,14 @@ where } } -impl<'a, I, C, R> HavocBytesMutator> +impl<'a, I, R> HavocBytesMutator> where I: Input + HasBytesVec, R: Rand, - C: Corpus, { /// Create a new HavocBytesMutator instance wrapping DefaultScheduledMutator pub fn new_default(rand: &Rc>) -> Self { - let mut scheduled = DefaultScheduledMutator::<'a, I, C, R>::new(rand); + let mut scheduled = DefaultScheduledMutator::<'a, I, R>::new(rand); scheduled.add_mutation(mutation_bitflip); HavocBytesMutator { scheduled: scheduled, diff --git a/src/observers/mod.rs b/src/observers/mod.rs index bcd9da6e72..2b50f0b22b 100644 --- a/src/observers/mod.rs +++ b/src/observers/mod.rs @@ -1,3 +1,4 @@ +extern crate alloc; extern crate num; use num::Integer; diff --git a/src/stages/mod.rs b/src/stages/mod.rs index 08c8392c79..d951ff2dc3 100644 --- a/src/stages/mod.rs +++ b/src/stages/mod.rs @@ -1,3 +1,4 @@ +extern crate alloc; pub mod mutational; pub use mutational::DefaultMutationalStage; @@ -5,8 +6,8 @@ use crate::corpus::Testcase; use crate::inputs::Input; use crate::AflError; +use alloc::rc::Rc; use core::cell::RefCell; -use std::rc::Rc; pub trait Stage where diff --git a/src/stages/mutational.rs b/src/stages/mutational.rs index 358cf68075..8d58ee954a 100644 --- a/src/stages/mutational.rs +++ b/src/stages/mutational.rs @@ -1,26 +1,23 @@ -use crate::corpus::Corpus; -use crate::corpus::TestcaseMetadata; -use crate::executors::Executor; +extern crate alloc; use crate::corpus::testcase::Testcase; -use crate::engines::Evaluator; +use crate::executors::Executor; use crate::inputs::Input; use crate::mutators::Mutator; use crate::stages::Stage; use crate::utils::{HasRand, Rand}; use crate::AflError; -use std::cell::RefCell; -use std::marker::PhantomData; -use std::rc::Rc; +use alloc::rc::Rc; +use core::cell::RefCell; +use core::marker::PhantomData; // TODO create HasMutatorsVec trait -pub trait MutationalStage: Stage + HasRand +pub trait MutationalStage: Stage + HasRand where I: Input, M: Mutator, - C: Corpus, - E: Executor, + E: Executor, { /// The mutator registered for this stage fn mutator(&self) -> &M; @@ -37,9 +34,9 @@ where 1 + self.rand_below(128) as usize } + // TODO: We need a way to get testcases for splicing /// Runs this (mutational) stage for the given testcase - fn perform_mutational(&mut self, corpus: &mut C, testcase: &Rc>>) -> Result<(), AflError> { - let testcase = corpus.next()?; + fn perform_mutational(&mut self, testcase: &Rc>>) -> Result<(), AflError> { let num = self.iterations(); let input = testcase.borrow_mut().load_input()?.clone(); @@ -47,7 +44,7 @@ where let mut input_tmp = input.clone(); self.mutator_mut().mutate(&mut input_tmp, i as i32)?; - let interesting = self.executor().borrow_mut().evaluate_input(&corpus)?; + let interesting = self.executor().borrow_mut().evaluate_input(&input_tmp)?; self.mutator_mut().post_exec(interesting, i as i32)?; } @@ -56,28 +53,25 @@ where } /// The default mutational stage -pub struct DefaultMutationalStage +pub struct DefaultMutationalStage where I: Input, - C: Corpus, R: Rand, M: Mutator, - E: Executor, + E: Executor, { rand: Rc>, executor: Rc>, mutator: M, _phantom_input: PhantomData, - _phantom_corpus: PhantomData, } -impl HasRand for DefaultMutationalStage +impl HasRand for DefaultMutationalStage where I: Input, - C: Corpus, R: Rand, M: Mutator, - E: Executor, + E: Executor, { type R = R; @@ -86,14 +80,12 @@ where } } - -impl MutationalStage for DefaultMutationalStage +impl MutationalStage for DefaultMutationalStage where I: Input, - C: Corpus, R: Rand, M: Mutator, - E: Executor, + E: Executor, { /// The mutator, added to this stage fn mutator(&self) -> &M { @@ -104,28 +96,30 @@ where fn mutator_mut(&mut self) -> &mut M { &mut self.mutator } -} -impl Stage for DefaultMutationalStage -where - I: Input, - C: Corpus, - R: Rand, - M: Mutator, - E: Executor, -{ - fn perform(&mut self, corpus: &mut C) -> Result<(), AflError> { - self.perform_mutational(corpus) + fn executor(&self) -> &Rc> { + &self.executor } } -impl DefaultMutationalStage +impl Stage for DefaultMutationalStage where I: Input, R: Rand, - C: Corpus, M: Mutator, - E: Executor, + E: Executor, +{ + fn perform(&mut self, testcase: &Rc>>) -> Result<(), AflError> { + self.perform_mutational(testcase) + } +} + +impl DefaultMutationalStage +where + I: Input, + R: Rand, + M: Mutator, + E: Executor, { /// Creates a new default mutational stage pub fn new(rand: &Rc>, executor: &Rc>, mutator: M) -> Self { @@ -134,7 +128,6 @@ where executor: Rc::clone(executor), mutator: mutator, _phantom_input: PhantomData, - _phantom_corpus: PhantomData, } } } diff --git a/src/utils.rs b/src/utils.rs index 7589775028..dd686fdaca 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,9 +1,10 @@ //! Utility functions for AFL +extern crate alloc; +use alloc::rc::Rc; use core::cell::RefCell; use std::debug_assert; use std::fmt::Debug; -use std::rc::Rc; use std::time::{SystemTime, UNIX_EPOCH}; use xxhash_rust::xxh3::xxh3_64_with_seed; @@ -160,8 +161,8 @@ mod tests { assert!(rand.between(11, 20) > 10); } + use alloc::rc::Rc; use core::cell::RefCell; - use std::rc::Rc; struct HasRandTest where R: Rand,