diff --git a/libafl/benches/rand_speeds.rs b/libafl/benches/rand_speeds.rs index ad97bd747b..486343d0cc 100644 --- a/libafl/benches/rand_speeds.rs +++ b/libafl/benches/rand_speeds.rs @@ -1,9 +1,9 @@ //! Compare the speed of rand implementations +use criterion::{black_box, criterion_group, criterion_main, Criterion}; use libafl::utils::{ Lehmer64Rand, Rand, RomuDuoJrRand, RomuTrioRand, XorShift64Rand, Xoshiro256StarRand, }; -use criterion::{black_box, criterion_group, criterion_main, Criterion}; fn criterion_benchmark(c: &mut Criterion) { let mut xorshift = XorShift64Rand::new(1); diff --git a/libafl/build.rs b/libafl/build.rs index f77872e9a6..1c6e87c8ce 100644 --- a/libafl/build.rs +++ b/libafl/build.rs @@ -1,11 +1,9 @@ fn main() { - - #[cfg(target_os = "windows")] - windows::build!( - windows::win32::system_services::HANDLE, - windows::win32::windows_programming::CloseHandle, - // API needed for the shared memory - windows::win32::system_services::{CreateFileMappingA, OpenFileMappingA, MapViewOfFile, UnmapViewOfFile}, - ); - + #[cfg(target_os = "windows")] + windows::build!( + windows::win32::system_services::HANDLE, + windows::win32::windows_programming::CloseHandle, + // API needed for the shared memory + windows::win32::system_services::{CreateFileMappingA, OpenFileMappingA, MapViewOfFile, UnmapViewOfFile}, + ); } diff --git a/libafl/src/bolts/mod.rs b/libafl/src/bolts/mod.rs index 099a20e799..f73268ce7c 100644 --- a/libafl/src/bolts/mod.rs +++ b/libafl/src/bolts/mod.rs @@ -1,8 +1,8 @@ //! Bolts are no conceptual fuzzing elements, but they keep libafl-based fuzzers together. +pub mod bindings; pub mod llmp; pub mod ownedref; pub mod serdeany; pub mod shmem; pub mod tuples; -pub mod bindings; diff --git a/libafl/src/bolts/serdeany.rs b/libafl/src/bolts/serdeany.rs index d7cf5dc7e9..8fcd3ae208 100644 --- a/libafl/src/bolts/serdeany.rs +++ b/libafl/src/bolts/serdeany.rs @@ -512,7 +512,7 @@ macro_rules! impl_serdeany { self } } - + #[allow(non_snake_case)] #[cfg(feature = "std")] #[ctor] diff --git a/libafl/src/bolts/shmem.rs b/libafl/src/bolts/shmem.rs index 324f6d512a..cc4d4f962f 100644 --- a/libafl/src/bolts/shmem.rs +++ b/libafl/src/bolts/shmem.rs @@ -330,8 +330,8 @@ pub mod shmem { use core::{mem::size_of, slice}; use std::ffi::CStr; - use crate::Error; use super::ShMem; + use crate::Error; /// The default Sharedmap impl for windows using shmctl & shmget #[derive(Clone, Debug)] @@ -343,7 +343,6 @@ pub mod shmem { } // TODO complete - } #[cfg(test)] diff --git a/libafl/src/bolts/tuples.rs b/libafl/src/bolts/tuples.rs index 2cd2d51d9e..ba20a0f29a 100644 --- a/libafl/src/bolts/tuples.rs +++ b/libafl/src/bolts/tuples.rs @@ -190,9 +190,9 @@ macro_rules! tuple_for_each { } impl ForEach for () { - fn for_each(&self) { } + fn for_each(&self) {} } - + impl ForEach for (Head, Tail) where Head: $trait_name, @@ -206,7 +206,7 @@ macro_rules! tuple_for_each { } { use $fn_name::*; - + $tuple_name.for_each(); }; }; @@ -221,9 +221,9 @@ macro_rules! tuple_for_each_mut { } impl ForEachMut for () { - fn for_each_mut(&mut self) { } + fn for_each_mut(&mut self) {} } - + impl ForEachMut for (Head, Tail) where Head: $trait_name, @@ -237,7 +237,7 @@ macro_rules! tuple_for_each_mut { } { use $fn_name::*; - + $tuple_name.for_each_mut(); }; }; @@ -245,13 +245,13 @@ macro_rules! tuple_for_each_mut { /* pub fn test_macros() { - + let mut t = tuple_list!(1, "a"); tuple_for_each!(f1, std::fmt::Display, t, |x| { println!("{}", x); }); - + tuple_for_each_mut!(f2, std::fmt::Display, t, |x| { println!("{}", x); }); diff --git a/libafl/src/corpus/mod.rs b/libafl/src/corpus/mod.rs index 02493aa84b..32069c5f46 100644 --- a/libafl/src/corpus/mod.rs +++ b/libafl/src/corpus/mod.rs @@ -7,12 +7,7 @@ use alloc::vec::Vec; use core::cell::RefCell; use serde::{Deserialize, Serialize}; -use crate::{ - inputs::Input, - state::{HasCorpus, HasRand}, - utils::Rand, - Error, -}; +use crate::{inputs::Input, Error}; /// Corpus with all current testcases pub trait Corpus: serde::Serialize + serde::de::DeserializeOwned @@ -33,65 +28,41 @@ where /// Get by id fn get(&self, idx: usize) -> Result<&RefCell>, Error>; + + /// Current testcase scheduled + fn current(&self) -> &Option; + + /// Current testcase scheduled (mut) + fn current_mut(&mut self) -> &mut Option; } -pub trait CorpusScheduler { +pub trait CorpusScheduler +where + I: Input, +{ /// Add an entry to the corpus and return its index - fn on_add( - &self, - state: &mut S, - idx: usize, - testcase: &Testcase, - ) -> Result<(), Error> - where - S: HasCorpus + HasRand, - C: Corpus, - I: Input, - R: Rand, - { + fn on_add(&self, state: &mut S, idx: usize, testcase: &Testcase) -> Result<(), Error> { Ok(()) } /// Replaces the testcase at the given idx - fn on_replace( - &self, - state: &mut S, - idx: usize, - testcase: &Testcase, - ) -> Result<(), Error> - where - S: HasCorpus + HasRand, - C: Corpus, - I: Input, - R: Rand, - { + fn on_replace(&self, state: &mut S, idx: usize, testcase: &Testcase) -> Result<(), Error> { Ok(()) } /// Removes an entry from the corpus, returning it if it was present. - fn on_remove( + fn on_remove( &self, state: &mut S, idx: usize, testcase: &Option>, - ) -> Result<(), Error> - where - S: HasCorpus + HasRand, - C: Corpus, - I: Input, - R: Rand, - { + ) -> Result<(), Error> { Ok(()) } // TODO: IntoIter /// Gets the next entry - fn next(&self, state: &mut S) -> Result - where - S: HasCorpus + HasRand, - C: Corpus, - I: Input, - R: Rand; + fn next(&self, state: &mut S) -> Result; } /* @@ -124,6 +95,7 @@ where I: Input, { entries: Vec>>, + current: Option, } impl Corpus for InMemoryCorpus @@ -168,4 +140,14 @@ where fn get(&self, idx: usize) -> Result<&RefCell>, Error> { Ok(&self.entries[idx]) } + + /// Current testcase scheduled + fn current(&self) -> &Option { + &self.current + } + + /// Current testcase scheduled (mut) + fn current_mut(&mut self) -> &mut Option { + &mut self.current + } } diff --git a/libafl/src/events/llmp.rs b/libafl/src/events/llmp.rs index 27f6078ab3..2d7e82aaa8 100644 --- a/libafl/src/events/llmp.rs +++ b/libafl/src/events/llmp.rs @@ -39,23 +39,25 @@ const _LLMP_TAG_RESTART: llmp::Tag = 0x8357A87; const _LLMP_TAG_NO_RESTART: llmp::Tag = 0x57A7EE71; #[derive(Clone, Debug)] -pub struct LlmpEventManager +pub struct LlmpEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, //CE: CustomEvent, { stats: Option, llmp: llmp::LlmpConnection, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } #[cfg(feature = "std")] #[cfg(unix)] -impl LlmpEventManager +impl LlmpEventManager where I: Input, + S: IfInteresting, ST: Stats, { /// Create llmp on a port @@ -78,9 +80,10 @@ where } } -impl Drop for LlmpEventManager +impl Drop for LlmpEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, { @@ -90,9 +93,10 @@ where } } -impl LlmpEventManager +impl LlmpEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, { @@ -248,7 +252,7 @@ where } // Handle arriving events in the client - fn handle_in_client( + fn handle_in_client( &mut self, state: &mut S, sender_id: u32, @@ -258,7 +262,6 @@ where where E: Executor + HasObservers, OT: ObserversTuple, - S: IfInteresting, { match event { Event::NewTestcase { @@ -293,9 +296,10 @@ where } } -impl EventManager for LlmpEventManager +impl EventManager for LlmpEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, //CE: CustomEvent, { @@ -311,11 +315,10 @@ where } } - fn process(&mut self, state: &mut S, executor: &mut E) -> Result + fn process(&mut self, state: &mut S, executor: &mut E) -> Result where E: Executor + HasObservers, OT: ObserversTuple, - S: IfInteresting, { // TODO: Get around local event copy by moving handle_in_client let mut events = vec![]; @@ -344,7 +347,7 @@ where Ok(count) } - fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, _state: &mut S, event: Event) -> Result<(), Error> { let serialized = postcard::to_allocvec(&event)?; self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?; Ok(()) @@ -356,11 +359,11 @@ where /// This method is needed when the fuzzer run crashes and has to restart. pub fn serialize_state_mgr( state: &S, - mgr: &LlmpEventManager, + mgr: &LlmpEventManager, ) -> Result, Error> where I: Input, - S: Serialize, + S: Serialize + IfInteresting, SH: ShMem, ST: Stats, { @@ -370,10 +373,10 @@ where /// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` pub fn deserialize_state_mgr( state_corpus_serialized: &[u8], -) -> Result<(S, LlmpEventManager), Error> +) -> Result<(S, LlmpEventManager), Error> where I: Input, - S: DeserializeOwned, + S: DeserializeOwned + IfInteresting, SH: ShMem, ST: Stats, { @@ -386,22 +389,24 @@ where /// A manager that can restart on the fly, storing states in-between (in `on_resatrt`) #[derive(Clone, Debug)] -pub struct LlmpRestartingEventManager +pub struct LlmpRestartingEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, //CE: CustomEvent, { /// The embedded llmp event manager - llmp_mgr: LlmpEventManager, + llmp_mgr: LlmpEventManager, /// The sender to serialize the state for the next runner sender: LlmpSender, } -impl EventManager for LlmpRestartingEventManager +impl EventManager for LlmpRestartingEventManager where I: Input, + S: IfInteresting + Serialize, SH: ShMem, ST: Stats, //CE: CustomEvent, { @@ -413,10 +418,7 @@ where } /// Reset the single page (we reuse it over and over from pos 0), then send the current state to the next runner. - fn on_restart(&mut self, state: &mut S) -> Result<(), Error> - where - S: Serialize, - { + fn on_restart(&mut self, state: &mut S) -> Result<(), Error> { // First, reset the page to 0 so the next iteration can read read from the beginning of this page unsafe { self.sender.reset() }; let state_corpus_serialized = serialize_state_mgr(state, &self.llmp_mgr)?; @@ -424,16 +426,15 @@ where .send_buf(_LLMP_TAG_RESTART, &state_corpus_serialized) } - fn process(&mut self, state: &mut S, executor: &mut E) -> Result + fn process(&mut self, state: &mut S, executor: &mut E) -> Result where E: Executor + HasObservers, OT: ObserversTuple, - S: IfInteresting, { self.llmp_mgr.process(state, executor) } - fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error> { + fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error> { // Check if we are going to crash in the event, in which case we store our current state for the next runner self.llmp_mgr.fire(state, event) } @@ -445,14 +446,15 @@ const _ENV_FUZZER_RECEIVER: &str = &"_AFL_ENV_FUZZER_RECEIVER"; /// The llmp (2 way) connection from a fuzzer to the broker (broadcasting all other fuzzer messages) const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = &"_AFL_ENV_FUZZER_BROKER_CLIENT"; -impl LlmpRestartingEventManager +impl LlmpRestartingEventManager where I: Input, + S: IfInteresting, SH: ShMem, ST: Stats, //CE: CustomEvent, { /// Create a new runner, the executed child doing the actual fuzzing. - pub fn new(llmp_mgr: LlmpEventManager, sender: LlmpSender) -> Self { + pub fn new(llmp_mgr: LlmpEventManager, sender: LlmpSender) -> Self { Self { llmp_mgr, sender } } @@ -471,13 +473,13 @@ where /// The restarter will start a new process each time the child crashes or timeouts. #[cfg(feature = "std")] pub fn setup_restarting_mgr( - //mgr: &mut LlmpEventManager, + //mgr: &mut LlmpEventManager, stats: ST, broker_port: u16, -) -> Result<(Option, LlmpRestartingEventManager), Error> +) -> Result<(Option, LlmpRestartingEventManager), Error> where I: Input, - S: DeserializeOwned, + S: DeserializeOwned + IfInteresting, SH: ShMem, ST: Stats, { @@ -485,7 +487,7 @@ where // We start ourself as child process to actually fuzz if std::env::var(_ENV_FUZZER_SENDER).is_err() { - mgr = LlmpEventManager::::new_on_port(stats, broker_port)?; + mgr = LlmpEventManager::::new_on_port(stats, broker_port)?; if mgr.is_broker() { // Yep, broker. Just loop here. println!("Doing broker things. Run this tool again to start fuzzing in a client."); @@ -528,7 +530,7 @@ where None => { println!("First run. Let's set it all up"); // Mgr to send and receive msgs from/to all other fuzzer instances - let client_mgr = LlmpEventManager::::existing_client_from_env( + let client_mgr = LlmpEventManager::::existing_client_from_env( _ENV_FUZZER_BROKER_CLIENT_INITIAL, )?; @@ -537,7 +539,7 @@ where // Restoring from a previous run, deserialize state and corpus. Some((_sender, _tag, msg)) => { println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len()); - let (state, mgr): (S, LlmpEventManager) = deserialize_state_mgr(&msg)?; + let (state, mgr): (S, LlmpEventManager) = deserialize_state_mgr(&msg)?; (Some(state), LlmpRestartingEventManager::new(mgr, sender)) } diff --git a/libafl/src/events/logger.rs b/libafl/src/events/logger.rs index 0a37f9b8f2..4262d847a3 100644 --- a/libafl/src/events/logger.rs +++ b/libafl/src/events/logger.rs @@ -5,14 +5,16 @@ use core::marker::PhantomData; #[cfg(unix)] use crate::{ events::{BrokerEventResult, Event, EventManager}, + executors::{Executor, HasObservers}, inputs::Input, + observers::ObserversTuple, stats::Stats, Error, }; /// A simple, single-threaded event manager that just logs #[derive(Clone, Debug)] -pub struct LoggerEventManager +pub struct LoggerEventManager where I: Input, ST: Stats, //CE: CustomEvent, @@ -21,15 +23,19 @@ where stats: ST, /// The events that happened since the last handle_in_broker events: Vec>, - phantom: PhantomData<(E, S)>, + phantom: PhantomData, } -impl EventManager for LoggerEventManager +impl EventManager for LoggerEventManager where I: Input, ST: Stats, //CE: CustomEvent, { - fn process(&mut self, state: &mut S, _executor: &mut E) -> Result { + fn process(&mut self, state: &mut S, executor: &mut E) -> Result + where + E: Executor + HasObservers, + OT: ObserversTuple, + { let count = self.events.len(); while self.events.len() > 0 { let event = self.events.pop().unwrap(); @@ -47,7 +53,7 @@ where } } -impl LoggerEventManager +impl LoggerEventManager where I: Input, ST: Stats, //TODO CE: CustomEvent, diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index a1c03ff11f..40e0fe05c6 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -9,7 +9,10 @@ use core::{fmt, marker::PhantomData, time::Duration}; use serde::{Deserialize, Serialize}; use crate::{ - executors::Executor, inputs::Input, observers::ObserversTuple, state::IfInteresting, Error, + executors::{Executor, HasObservers}, + inputs::Input, + observers::ObserversTuple, + Error, }; /// The log event severity @@ -146,7 +149,7 @@ where /// EventManager is the main communications hub. /// For the "normal" multi-processed mode, you may want to look into `RestartingEventManager` -pub trait EventManager +pub trait EventManager where I: Input, { @@ -155,7 +158,10 @@ where /// Lookup for incoming events and process them. /// Return the number of processes events or an error - fn process(&mut self, state: &mut S, executor: &mut E) -> Result; + fn process(&mut self, state: &mut S, executor: &mut E) -> Result + where + E: Executor + HasObservers, + OT: ObserversTuple; /// Serialize all observers for this type and manager fn serialize_observers(&mut self, observers: &OT) -> Result, Error> @@ -189,16 +195,17 @@ where /// An eventmgr for tests, and as placeholder if you really don't need an event manager. #[derive(Copy, Clone, Debug)] -pub struct NopEventManager { - phantom: PhantomData<(E, I, S)>, +pub struct NopEventManager { + phantom: PhantomData<(I, S)>, } -impl EventManager for NopEventManager +impl EventManager for NopEventManager where I: Input, { - fn process(&mut self, _state: &mut S, _executor: &mut E) -> Result + fn process(&mut self, state: &mut S, executor: &mut E) -> Result where - E: Executor, + E: Executor + HasObservers, + OT: ObserversTuple, { Ok(0) } diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index 76a1d72a9b..36972050c5 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -56,7 +56,7 @@ where #[inline] fn pre_exec(&mut self, state: &mut S, event_mgr: &mut EM, input: &I) -> Result<(), Error> where - EM: EventManager, + EM: EventManager, { #[cfg(unix)] #[cfg(feature = "std")] @@ -69,7 +69,7 @@ where #[inline] fn post_exec(&mut self, _state: &S, _event_mgr: &mut EM, _input: &I) -> Result<(), Error> where - EM: EventManager, + EM: EventManager, { #[cfg(unix)] #[cfg(feature = "std")] @@ -132,7 +132,7 @@ where _event_mgr: &mut EM, ) -> Self where - EM: EventManager, + EM: EventManager, OC: Corpus, OFT: FeedbacksTuple, S: HasObjectives + HasSolutions, @@ -200,7 +200,7 @@ pub mod unix_signals { info: siginfo_t, _void: c_void, ) where - EM: EventManager, + EM: EventManager, OT: ObserversTuple, OC: Corpus, OFT: FeedbacksTuple, @@ -273,7 +273,7 @@ pub mod unix_signals { info: siginfo_t, _void: c_void, ) where - EM: EventManager, + EM: EventManager, OT: ObserversTuple, OC: Corpus, OFT: FeedbacksTuple, @@ -346,7 +346,7 @@ pub mod unix_signals { pub unsafe fn setup_crash_handlers() where - EM: EventManager, + EM: EventManager, OT: ObserversTuple, OC: Corpus, OFT: FeedbacksTuple, diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 7a4a794e0d..dfe2740203 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -87,21 +87,16 @@ where _input: &I, ) -> Result<(), Error> where - EM: EventManager, + EM: EventManager, { Ok(()) } #[inline] /// Called right after execution finished. - fn post_exec( - &mut self, - _state: &S, - _event_mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> + fn post_exec(&mut self, _state: &S, _event_mgr: &mut EM, _input: &I) -> Result<(), Error> where - EM: EventManager, + EM: EventManager, { Ok(()) } diff --git a/libafl/src/fuzzer.rs b/libafl/src/fuzzer.rs index 88f5960c94..37c986a26c 100644 --- a/libafl/src/fuzzer.rs +++ b/libafl/src/fuzzer.rs @@ -1,20 +1,20 @@ use crate::{ - corpus::{Corpus, CorpusScheduler}, + corpus::CorpusScheduler, events::{Event, EventManager}, - executors::Executor, + executors::{Executor, HasObservers}, inputs::Input, + observers::ObserversTuple, stages::StagesTuple, - state::{HasCorpus, HasExecutions, HasRand}, - utils::{current_milliseconds, current_time, Rand}, + state::HasExecutions, + utils::{current_milliseconds, current_time}, Error, }; use core::marker::PhantomData; /// Holds a set of stages -pub trait HasStages +pub trait HasStages: Sized where - ST: StagesTuple, - I: Input, + ST: StagesTuple, { fn stages(&self) -> &ST; @@ -22,9 +22,10 @@ where } /// Holds a scheduler -pub trait HasCorpusScheduler +pub trait HasCorpusScheduler where - CS: CorpusScheduler, + CS: CorpusScheduler, + I: Input, { fn scheduler(&self) -> &CS; @@ -32,50 +33,29 @@ where } /// The main fuzzer trait. -pub trait Fuzzer: HasCorpusScheduler + HasStages -where - CS: CorpusScheduler, - ST: StagesTuple, - I: Input, -{ - fn fuzz_one( - &self, - state: &mut S, - executor: &mut E, - manager: &mut EM, - ) -> Result - where - EM: EventManager, - E: Executor; +pub trait Fuzzer { + fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result; - fn fuzz_loop( - &self, - state: &mut S, - executor: &mut E, - manager: &mut EM, - ) -> Result - where - EM: EventManager, - E: Executor; + fn fuzz_loop(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result; } /// Your default fuzzer instance, for everyday use. #[derive(Clone, Debug)] -pub struct StdFuzzer +pub struct StdFuzzer where - CS: CorpusScheduler, - ST: StagesTuple, + CS: CorpusScheduler, + ST: StagesTuple, I: Input, { scheduler: CS, stages: ST, - phantom: PhantomData, + phantom: PhantomData<(E, EM, I, OT, S)>, } -impl HasStages for StdFuzzer +impl HasStages for StdFuzzer where - CS: CorpusScheduler, - ST: StagesTuple, + CS: CorpusScheduler, + ST: StagesTuple, I: Input, { fn stages(&self) -> &ST { @@ -87,10 +67,10 @@ where } } -impl HasCorpusScheduler for StdFuzzer +impl HasCorpusScheduler for StdFuzzer where - CS: CorpusScheduler, - ST: StagesTuple, + CS: CorpusScheduler, + ST: StagesTuple, I: Input, { fn scheduler(&self) -> &CS { @@ -102,25 +82,17 @@ where } } -impl Fuzzer for StdFuzzer +impl Fuzzer for StdFuzzer where - CS: CorpusScheduler, - ST: StagesTuple, + CS: CorpusScheduler, + S: HasExecutions, + ST: StagesTuple, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, I: Input, { - fn fuzz_one( - &self, - state: &mut S, - executor: &mut E, - manager: &mut EM, - ) -> Result - where - EM: EventManager, - E: Executor, - S: HasCorpus + HasRand, - C: Corpus, - R: Rand, - { + fn fuzz_one(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result { let idx = self.scheduler().next(state)?; self.stages() @@ -130,19 +102,7 @@ where Ok(idx) } - fn fuzz_loop( - &self, - state: &mut S, - executor: &mut E, - manager: &mut EM, - ) -> Result - where - EM: EventManager, - E: Executor, - S: HasCorpus + HasRand + HasExecutions, - C: Corpus, - R: Rand, - { + fn fuzz_loop(&self, state: &mut S, executor: &mut E, manager: &mut EM) -> Result { let mut last = current_milliseconds(); loop { self.fuzz_one(state, executor, manager)?; @@ -162,10 +122,10 @@ where } } -impl StdFuzzer +impl StdFuzzer where - CS: CorpusScheduler, - ST: StagesTuple, + CS: CorpusScheduler, + ST: StagesTuple, I: Input, { pub fn new(scheduler: CS, stages: ST) -> Self { diff --git a/libafl/src/inputs/bytes.rs b/libafl/src/inputs/bytes.rs index b622a002f7..1cca7ee368 100644 --- a/libafl/src/inputs/bytes.rs +++ b/libafl/src/inputs/bytes.rs @@ -5,7 +5,7 @@ use alloc::{borrow::ToOwned, rc::Rc, vec::Vec}; use core::{cell::RefCell, convert::From}; use serde::{Deserialize, Serialize}; -use crate::inputs::{HasBytesVec, HasTargetBytes, HasLen, Input, TargetBytes}; +use crate::inputs::{HasBytesVec, HasLen, HasTargetBytes, Input, TargetBytes}; /// A bytes input is the basic input #[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq)] diff --git a/libafl/src/inputs/mod.rs b/libafl/src/inputs/mod.rs index 09a62f698a..18b9b6a518 100644 --- a/libafl/src/inputs/mod.rs +++ b/libafl/src/inputs/mod.rs @@ -106,4 +106,3 @@ pub trait HasLen { /// The lenght fn len(&self) -> usize; } - diff --git a/libafl/src/lib.rs b/libafl/src/lib.rs index 0101e09da1..c8f30e87d3 100644 --- a/libafl/src/lib.rs +++ b/libafl/src/lib.rs @@ -29,7 +29,7 @@ pub mod fuzzer; pub use fuzzer::*; use alloc::string::String; -use core::{fmt}; +use core::fmt; #[cfg(feature = "std")] use std::{env::VarError, io, num::ParseIntError, string::FromUtf8Error}; @@ -199,4 +199,4 @@ mod tests { assert_eq!(state.corpus().count(), corpus_deserialized.count()); } } -*/ \ No newline at end of file +*/ diff --git a/libafl/src/mutators/mod.rs b/libafl/src/mutators/mod.rs index 3bbd89d98b..73c5203663 100644 --- a/libafl/src/mutators/mod.rs +++ b/libafl/src/mutators/mod.rs @@ -7,32 +7,24 @@ pub use mutations::*; pub mod token_mutations; pub use token_mutations::*; -use crate::{ - inputs::Input, - Error, -}; +use crate::{inputs::Input, Error}; // TODO mutator stats method that produces something that can be sent with the NewTestcase event // We can use it to report which mutations generated the testcase in the broker logs /// A mutator takes input, and mutates it. /// Simple as that. -pub trait Mutator +pub trait Mutator where I: Input, { /// Mutate a given input - fn mutate( - &mut self, - fuzzer: &F, - state: &mut S, - input: &mut I, - stage_idx: i32, - ) -> Result<(), Error>; + fn mutate(&self, fuzzer: &F, state: &mut S, input: &mut I, stage_idx: i32) + -> Result<(), Error>; /// Post-process given the outcome of the execution - fn post_exec( - &mut self, + fn post_exec( + &self, _fuzzer: &F, _state: &mut S, _is_interesting: u32, diff --git a/libafl/src/mutators/mutations.rs b/libafl/src/mutators/mutations.rs index 2813a1ebc8..c2af06a1c2 100644 --- a/libafl/src/mutators/mutations.rs +++ b/libafl/src/mutators/mutations.rs @@ -27,8 +27,7 @@ pub enum MutationResult { // TODO maybe the mutator arg is not needed /// The generic function type that identifies mutations -pub type MutationFunction = - fn(&mut M, &F, &mut S, &mut I) -> Result; +pub type MutationFunction = fn(&M, &F, &mut S, &mut I) -> Result; pub trait ComposedByMutations where @@ -125,7 +124,7 @@ const INTERESTING_32: [i32; 27] = [ /// Bitflip mutation for inputs with a bytes vector pub fn mutation_bitflip( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -148,7 +147,7 @@ where } pub fn mutation_byteflip( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -171,7 +170,7 @@ where } pub fn mutation_byteinc( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -195,7 +194,7 @@ where } pub fn mutation_bytedec( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -219,7 +218,7 @@ where } pub fn mutation_byteneg( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -242,7 +241,7 @@ where } pub fn mutation_byterand( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -265,7 +264,7 @@ where } pub fn mutation_byteadd( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -293,7 +292,7 @@ where } pub fn mutation_wordadd( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -323,7 +322,7 @@ where } pub fn mutation_dwordadd( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -353,7 +352,7 @@ where } pub fn mutation_qwordadd( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -383,7 +382,7 @@ where } pub fn mutation_byteinteresting( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -407,7 +406,7 @@ where } pub fn mutation_wordinteresting( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -437,7 +436,7 @@ where } pub fn mutation_dwordinteresting( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -467,7 +466,7 @@ where } pub fn mutation_bytesdelete( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -490,7 +489,7 @@ where } pub fn mutation_bytesexpand( - mutator: &mut M, + mutator: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -520,7 +519,7 @@ where } pub fn mutation_bytesinsert( - mutator: &mut M, + mutator: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -553,7 +552,7 @@ where } pub fn mutation_bytesrandinsert( - mutator: &mut M, + mutator: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -586,7 +585,7 @@ where } pub fn mutation_bytesset( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -611,7 +610,7 @@ where } pub fn mutation_bytesrandset( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -636,7 +635,7 @@ where } pub fn mutation_bytescopy( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -661,7 +660,7 @@ where } pub fn mutation_bytesswap( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -689,7 +688,7 @@ where /// Crossover insert mutation pub fn mutation_crossover_insert( - mutator: &mut M, + mutator: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -704,10 +703,13 @@ where let size = input.bytes().len(); // We don't want to use the testcase we're already using for splicing - let (other_testcase, idx) = state.random_corpus_entry()?; - if idx == state.corpus().current_testcase().1 { - return Ok(MutationResult::Skipped); + let idx = state.rand_mut().below(state.corpus().count() as u64) as usize; + if let Some(cur) = state.corpus().current() { + if idx == *cur { + return Ok(MutationResult::Skipped); + } } + let other_testcase = state.corpus().get(idx)?; let mut other_ref = other_testcase.borrow_mut(); let other = other_ref.load_input()?; @@ -738,7 +740,7 @@ where /// Crossover replace mutation pub fn mutation_crossover_replace( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -752,10 +754,13 @@ where let size = input.bytes().len(); // We don't want to use the testcase we're already using for splicing - let (other_testcase, idx) = state.random_corpus_entry()?; - if idx == state.corpus().current_testcase().1 { - return Ok(MutationResult::Skipped); + let idx = state.rand_mut().below(state.corpus().count() as u64) as usize; + if let Some(cur) = state.corpus().current() { + if idx == *cur { + return Ok(MutationResult::Skipped); + } } + let other_testcase = state.corpus().get(idx)?; let mut other_ref = other_testcase.borrow_mut(); let other = other_ref.load_input()?; @@ -792,7 +797,7 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) { /// Splicing mutation from AFL pub fn mutation_splice( - _: &mut M, + _: &M, fuzzer: &F, state: &mut S, input: &mut I, @@ -804,10 +809,13 @@ where S: HasRand + HasCorpus, { // We don't want to use the testcase we're already using for splicing - let (other_testcase, idx) = state.random_corpus_entry()?; - if idx == state.corpus().current_testcase().1 { - return Ok(MutationResult::Skipped); + let idx = state.rand_mut().below(state.corpus().count() as u64) as usize; + if let Some(cur) = state.corpus().current() { + if idx == *cur { + return Ok(MutationResult::Skipped); + } } + let other_testcase = state.corpus().get(idx)?; let mut other_ref = other_testcase.borrow_mut(); let other = other_ref.load_input()?; diff --git a/libafl/src/mutators/scheduled.rs b/libafl/src/mutators/scheduled.rs index a40e84329e..e8b880e3d9 100644 --- a/libafl/src/mutators/scheduled.rs +++ b/libafl/src/mutators/scheduled.rs @@ -15,27 +15,20 @@ use crate::{ pub use crate::mutators::mutations::*; pub use crate::mutators::token_mutations::*; -pub trait ScheduledMutator: Mutator + ComposedByMutations +pub trait ScheduledMutator: Mutator + ComposedByMutations where I: Input, { /// Compute the number of iterations used to apply stacked mutations - fn iterations(&mut self, state: &mut S, input: &I) -> u64; - //{ - // 1 << (1 + state.rand_mut().below(6)) - //} + fn iterations(&self, state: &mut S, input: &I) -> u64; /// Get the next mutation to apply - fn schedule(&mut self, mutations_count: usize, state: &mut S, input: &I) -> usize; - //{ - // debug_assert!(mutations_count > 0); - // rand.below(mutations_count as u64) as usize - //} + fn schedule(&self, mutations_count: usize, state: &mut S, input: &I) -> usize; /// New default implementation for mutate /// Implementations must forward mutate() to this method fn scheduled_mutate( - &mut self, + &self, fuzzer: &F, state: &mut S, input: &mut I, @@ -50,18 +43,22 @@ where } } -#[derive(Clone)] -pub struct StdScheduledMutator +pub struct StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { mutations: Vec>, max_size: usize, + phantom: PhantomData, } -impl Debug for StdScheduledMutator +impl Debug for StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -74,12 +71,14 @@ where } } -impl Mutator for StdScheduledMutator +impl Mutator for StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { fn mutate( - &mut self, + &self, fuzzer: &F, state: &mut S, input: &mut I, @@ -89,9 +88,11 @@ where } } -impl ComposedByMutations for StdScheduledMutator +impl ComposedByMutations for StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { #[inline] fn mutation_by_idx(&self, index: usize) -> MutationFunction { @@ -109,16 +110,29 @@ where } } -impl ScheduledMutator for StdScheduledMutator +impl ScheduledMutator for StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { - // Just use the default methods + /// Compute the number of iterations used to apply stacked mutations + fn iterations(&self, state: &mut S, input: &I) -> u64 { + 1 << (1 + state.rand_mut().below(6)) + } + + /// Get the next mutation to apply + fn schedule(&self, mutations_count: usize, state: &mut S, input: &I) -> usize { + debug_assert!(mutations_count > 0); + state.rand_mut().below(mutations_count as u64) as usize + } } -impl HasMaxSize for StdScheduledMutator +impl HasMaxSize for StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { #[inline] fn max_size(&self) -> usize { @@ -131,15 +145,18 @@ where } } -impl StdScheduledMutator +impl StdScheduledMutator where I: Input, + S: HasRand, + R: Rand, { /// Create a new StdScheduledMutator instance without mutations and corpus pub fn new() -> Self { Self { mutations: vec![], max_size: DEFAULT_MAX_SIZE, + phantom: PhantomData, } } @@ -148,6 +165,7 @@ where StdScheduledMutator { mutations: mutations, max_size: DEFAULT_MAX_SIZE, + phantom: PhantomData, } } } @@ -166,7 +184,7 @@ where phantom: PhantomData<(C, F, I, R, S)>, } -impl Mutator for HavocBytesMutator +impl Mutator for HavocBytesMutator where SM: ScheduledMutator + HasMaxSize, I: Input + HasBytesVec, @@ -176,8 +194,8 @@ where { /// Mutate bytes fn mutate( - &mut self, - fuzzer: &mut F, + &self, + fuzzer: &F, state: &mut S, input: &mut I, stage_idx: i32, @@ -246,7 +264,7 @@ where } } -impl Default for HavocBytesMutator> +impl Default for HavocBytesMutator> where I: Input + HasBytesVec, S: HasRand + HasCorpus + HasMetadata, @@ -255,7 +273,7 @@ where { /// Create a new HavocBytesMutator instance wrapping StdScheduledMutator fn default() -> Self { - let mut scheduled = StdScheduledMutator::::new(); + let mut scheduled = StdScheduledMutator::::new(); scheduled.add_mutation(mutation_bitflip); scheduled.add_mutation(mutation_byteflip); scheduled.add_mutation(mutation_byteinc); @@ -283,8 +301,8 @@ where scheduled.add_mutation(mutation_bytescopy); scheduled.add_mutation(mutation_bytesswap); - scheduled.add_mutation(mutation_tokeninsert); - scheduled.add_mutation(mutation_tokenreplace); + //scheduled.add_mutation(mutation_tokeninsert); + //scheduled.add_mutation(mutation_tokenreplace); scheduled.add_mutation(mutation_crossover_insert); scheduled.add_mutation(mutation_crossover_replace); diff --git a/libafl/src/mutators/token_mutations.rs b/libafl/src/mutators/token_mutations.rs index 71635a33bd..b86937b45f 100644 --- a/libafl/src/mutators/token_mutations.rs +++ b/libafl/src/mutators/token_mutations.rs @@ -3,8 +3,8 @@ use crate::{ inputs::{HasBytesVec, Input}, - state::{HasRand, HasMetadata}, mutators::*, + state::{HasMetadata, HasRand}, utils::Rand, Error, }; diff --git a/libafl/src/stages/mod.rs b/libafl/src/stages/mod.rs index 35db374be4..45c4db9b8d 100644 --- a/libafl/src/stages/mod.rs +++ b/libafl/src/stages/mod.rs @@ -1,10 +1,7 @@ pub mod mutational; pub use mutational::StdMutationalStage; -use crate::{ - bolts::tuples::TupleList, corpus::Corpus, events::EventManager, executors::Executor, - inputs::Input, Error, -}; +use crate::{bolts::tuples::TupleList, corpus::Corpus, Error}; /// A stage is one step in the fuzzing process. /// Multiple stages will be scheduled one by one for each input. diff --git a/libafl/src/stages/mutational.rs b/libafl/src/stages/mutational.rs index 89e08e8a9d..add170ba89 100644 --- a/libafl/src/stages/mutational.rs +++ b/libafl/src/stages/mutational.rs @@ -1,14 +1,14 @@ use core::marker::PhantomData; use crate::{ + corpus::Corpus, events::EventManager, - executors::Executor, + executors::{Executor, HasObservers}, inputs::Input, mutators::Mutator, - stages::Corpus, + observers::ObserversTuple, stages::Stage, - state::HasRand, - state::{Evaluator, HasCorpus}, + state::{Evaluator, HasCorpus, HasRand}, utils::Rand, Error, }; @@ -18,10 +18,15 @@ use crate::{ /// A Mutational stage is the stage in a fuzzing run that mutates inputs. /// Mutational stages will usually have a range of mutations that are /// being applied to the input one by one, between executions. -pub trait MutationalStage: Stage +pub trait MutationalStage: Stage where - M: Mutator, + M: Mutator, I: Input, + S: HasCorpus + Evaluator, + C: Corpus, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, { /// The mutator registered for this stage fn mutator(&self) -> &M; @@ -30,23 +35,17 @@ where fn mutator_mut(&mut self) -> &mut M; /// Gets the number of iterations this mutator should run for. - fn iterations(&mut self, state: &mut S) -> usize; + fn iterations(&mut self, state: &mut S) -> usize; /// Runs this (mutational) stage for the given testcase - fn perform_mutational( + fn perform_mutational( &self, fuzzer: &F, state: &mut S, executor: &mut E, manager: &mut EM, corpus_idx: usize, - ) -> Result<(), Error> - where - EM: EventManager, - E: Executor, - S: HasCorpus + Evaluator, - C: Corpus, - { + ) -> Result<(), Error> { let num = self.iterations(state); for i in 0..num { let mut input_mut = state @@ -71,19 +70,32 @@ pub static DEFAULT_MUTATIONAL_MAX_ITERATIONS: u64 = 128; /// The default mutational stage #[derive(Clone, Debug)] -pub struct StdMutationalStage +pub struct StdMutationalStage where - M: Mutator, + M: Mutator, I: Input, + S: HasCorpus + Evaluator + HasRand, + C: Corpus, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + R: Rand, { mutator: M, - phantom: PhantomData, + phantom: PhantomData<(C, E, EM, F, I, OT, R, S)>, } -impl MutationalStage for StdMutationalStage +impl MutationalStage + for StdMutationalStage where - M: Mutator, + M: Mutator, I: Input, + S: HasCorpus + Evaluator + HasRand, + C: Corpus, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + R: Rand, { /// The mutator, added to this stage #[inline] @@ -98,43 +110,46 @@ where } /// Gets the number of iterations as a random number - fn iterations(&mut self, state: &mut S) -> usize - where - S: HasRand, - R: Rand, - { + fn iterations(&mut self, state: &mut S) -> usize { 1 + state.rand_mut().below(DEFAULT_MUTATIONAL_MAX_ITERATIONS) as usize } } -impl Stage for StdMutationalStage +impl Stage + for StdMutationalStage where - M: Mutator, + M: Mutator, I: Input, + S: HasCorpus + Evaluator + HasRand, + C: Corpus, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + R: Rand, { #[inline] - fn perform( + fn perform( &self, fuzzer: &F, state: &mut S, executor: &mut E, manager: &mut EM, corpus_idx: usize, - ) -> Result<(), Error> - where - EM: EventManager, - E: Executor, - S: HasCorpus + Evaluator, - C: Corpus, - { + ) -> Result<(), Error> { self.perform_mutational(fuzzer, state, executor, manager, corpus_idx) } } -impl StdMutationalStage +impl StdMutationalStage where - M: Mutator, + M: Mutator, I: Input, + S: HasCorpus + Evaluator + HasRand, + C: Corpus, + EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, + R: Rand, { /// Creates a new default mutational stage pub fn new(mutator: M) -> Self { diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 0b11d67ade..eddab4e503 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -159,20 +159,21 @@ where } /// Evaluate an input modyfing the state of the fuzzer and returning a fitness -pub trait Evaluator +pub trait Evaluator: Sized where I: Input, { /// Runs the input and triggers observers and feedback - fn evaluate_input( + fn evaluate_input( &mut self, input: I, executor: &mut E, event_mgr: &mut EM, ) -> Result where - E: Executor, - EM: EventManager; + E: Executor + HasObservers, + OT: ObserversTuple, + EM: EventManager; } /// The state a fuzz run. @@ -442,7 +443,7 @@ where E: Executor + HasObservers, OT: ObserversTuple, C: Corpus, - EM: EventManager, + EM: EventManager, { let (fitness, is_solution) = self.execute_input(&input, executor, manager)?; let observers = executor.observers(); @@ -490,7 +491,7 @@ where C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, - EM: EventManager, + EM: EventManager, { for entry in fs::read_dir(in_dir)? { let entry = entry?; @@ -532,7 +533,7 @@ where C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, - EM: EventManager, + EM: EventManager, { for in_dir in in_dirs { self.load_from_directory(executor, manager, in_dir)?; @@ -570,7 +571,7 @@ where E: Executor + HasObservers, OT: ObserversTuple, C: Corpus, - EM: EventManager, + EM: EventManager, { executor.pre_exec_observers()?; @@ -606,7 +607,7 @@ where C: Corpus, E: Executor + HasObservers, OT: ObserversTuple, - EM: EventManager, + EM: EventManager, { let mut added = 0; for _ in 0..num { diff --git a/libafl/src/utils.rs b/libafl/src/utils.rs index b0eff77df9..e0dd6dd201 100644 --- a/libafl/src/utils.rs +++ b/libafl/src/utils.rs @@ -1,7 +1,7 @@ //! Utility functions for AFL use core::{cell::RefCell, debug_assert, fmt::Debug, time}; -use serde::{Deserialize, Serialize, de::DeserializeOwned}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; use xxhash_rust::xxh3::xxh3_64_with_seed; #[cfg(feature = "std")]