diff --git a/afl/src/engines/mod.rs b/afl/src/engines/mod.rs index 7b940815ec..e0a8406874 100644 --- a/afl/src/engines/mod.rs +++ b/afl/src/engines/mod.rs @@ -509,7 +509,7 @@ mod tests { use crate::inputs::bytes::BytesInput; use crate::mutators::{mutation_bitflip, ComposedByMutations, StdScheduledMutator}; use crate::stages::mutational::StdMutationalStage; - use crate::tuples::{tuple_list, tuple_list_type}; + use crate::tuples::tuple_list; use crate::utils::StdRand; fn harness(_executor: &dyn Executor, _buf: &[u8]) -> ExitKind { @@ -534,7 +534,7 @@ mod tests { "main", harness, tuple_list!(), - Box::new(|_, _| ()), + Box::new(|_, _, _, _, _| ()), &state, &corpus, &mut event_manager, @@ -559,7 +559,7 @@ mod tests { } let state_serialized = postcard::to_allocvec(&state).unwrap(); - let state_deserialized: State = + let state_deserialized: State = postcard::from_bytes(state_serialized.as_slice()).unwrap(); assert_eq!(state.executions, state_deserialized.executions); diff --git a/afl/src/events/mod.rs b/afl/src/events/mod.rs index 95a4b7c4a4..37ffe0d66e 100644 --- a/afl/src/events/mod.rs +++ b/afl/src/events/mod.rs @@ -292,6 +292,30 @@ where // TODO Custom event fire (dyn CustomEvent or similar) } +/// 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, +} +impl EventManager for NopEventManager +where + I: Input, +{ + fn process( + &mut self, + _state: &mut State, + _corpus: &mut C, + ) -> Result + where + C: Corpus, + FT: FeedbacksTuple, + R: Rand, + { + Ok(0) + } +} + +/// Events that may happen #[derive(Clone, Debug)] pub enum LoggerEvent where diff --git a/afl/src/executors/inmemory.rs b/afl/src/executors/inmemory.rs index 958b9a0378..1e19e75e79 100644 --- a/afl/src/executors/inmemory.rs +++ b/afl/src/executors/inmemory.rs @@ -1,4 +1,4 @@ -use alloc::{boxed::Box, vec::Vec}; +use alloc::boxed::Box; use core::{ffi::c_void, ptr}; use crate::{ @@ -15,17 +15,17 @@ use crate::{ }; #[cfg(feature = "std")] -use self::unix_signals::setup_crash_handlers; +#[cfg(unix)] +use unix_signals as os_signals; + +#[cfg(feature = "std")] +use self::os_signals::setup_crash_handlers; /// The (unsafe) pointer to the current inmem input, for the current run. /// This is neede for certain non-rust side effects, as well as unix signal handling. static mut CURRENT_INPUT_PTR: *const c_void = ptr::null(); static mut CURRENT_ON_CRASH_FN: *mut c_void = ptr::null_mut(); -static mut CORPUS_PTR: *const c_void = ptr::null_mut(); -static mut STATE_PTR: *const c_void = ptr::null_mut(); -static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut(); - /// The inmem executor harness type HarnessFunction = fn(&dyn Executor, &[u8]) -> ExitKind; type OnCrashFunction = dyn FnMut(ExitKind, &I, &State, &C, &mut EM); @@ -149,40 +149,6 @@ where } } -/// Serialize the current state and corpus during an executiont to bytes. -/// This method is needed when the fuzzer run crashes and has to restart. -pub fn serialize_state_corpus( - state: &State, - corpus: &C, -) -> Result, AflError> -where - C: Corpus, - FT: FeedbacksTuple, - I: Input, - R: Rand, -{ - let state_bytes = postcard::to_allocvec(&state)?; - let corpus_bytes = postcard::to_allocvec(&corpus)?; - Ok(postcard::to_allocvec(&(state_bytes, corpus_bytes))?) -} - -/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` -pub fn deserialize_state_corpus( - state_corpus_serialized: &[u8], -) -> Result<(State, C), AflError> -where - C: Corpus, - FT: FeedbacksTuple, - I: Input, - R: Rand, -{ - let tuple: (Vec, Vec) = postcard::from_bytes(&state_corpus_serialized)?; - Ok(( - postcard::from_bytes(&tuple.0)?, - postcard::from_bytes(&tuple.1)?, - )) -} - #[cfg(feature = "std")] #[cfg(unix)] pub mod unix_signals { @@ -206,16 +172,19 @@ pub mod unix_signals { corpus::Corpus, engines::State, events::EventManager, - executors::inmemory::{ - ExitKind, OnCrashFunction, CORPUS_PTR, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN, - EVENT_MANAGER_PTR, STATE_PTR, - }, + executors::inmemory::{ExitKind, OnCrashFunction, CURRENT_INPUT_PTR, CURRENT_ON_CRASH_FN}, feedbacks::FeedbacksTuple, inputs::Input, observers::ObserversTuple, utils::Rand, }; + /// Pointers to values only needed on crash. As the program will not continue after a crash, + /// we should (tm) be okay with raw pointers here, + static mut CORPUS_PTR: *const c_void = ptr::null_mut(); + static mut STATE_PTR: *const c_void = ptr::null_mut(); + static mut EVENT_MANAGER_PTR: *mut c_void = ptr::null_mut(); + pub unsafe extern "C" fn libaflrs_executor_inmem_handle_crash( _sig: c_int, info: siginfo_t, @@ -230,9 +199,10 @@ pub mod unix_signals { { if CURRENT_INPUT_PTR == ptr::null() { println!( - "We died accessing addr {}, but are not in client...", + "We died accessing addr {}, but are not in client... Exiting.", info.si_addr() as usize ); + return; } #[cfg(feature = "std")] @@ -274,7 +244,7 @@ pub mod unix_signals { { dbg!("TIMEOUT/SIGUSR2 received"); if CURRENT_INPUT_PTR.is_null() { - dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing."); + dbg!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); return; } @@ -342,33 +312,16 @@ pub mod unix_signals { } } -//#[cfg(feature = "std")] -//#[cfg(unix)] -//use unix_signals as os_signals; -//#[cfg(feature = "std")] -//#[cfg(not(unix))] -//compile_error!("InMemoryExecutor not yet supported on this OS"); - #[cfg(test)] mod tests { use alloc::boxed::Box; - use crate::executors::inmemory::InMemoryExecutor; - use crate::executors::{Executor, ExitKind}; - use crate::inputs::{HasTargetBytes, Input, TargetBytes}; - use crate::tuples::tuple_list; - - use serde::{Deserialize, Serialize}; - - #[derive(Clone, Serialize, Deserialize, Debug)] - struct NopInput {} - impl Input for NopInput {} - impl HasTargetBytes for NopInput { - fn target_bytes(&self) -> TargetBytes { - TargetBytes::Owned(vec![0]) - } - } + use crate::{ + executors::{inmemory::InMemoryExecutor, Executor, ExitKind}, + inputs::NopInput, + tuples::tuple_list, + }; #[cfg(feature = "std")] fn test_harness_fn_nop(_executor: &dyn Executor, buf: &[u8]) -> ExitKind { @@ -383,12 +336,22 @@ mod tests { #[test] fn test_inmem_exec() { - let mut in_mem_executor = InMemoryExecutor { + use crate::{ + corpus::InMemoryCorpus, events::NopEventManager, inputs::NopInput, utils::StdRand, + }; + + let mut in_mem_executor = InMemoryExecutor::< + NopInput, + (), + InMemoryCorpus<_, _>, + NopEventManager<_>, + (), + StdRand, + > { harness_fn: test_harness_fn_nop, - on_crash_fn: Box::new(|_, _| ()), + on_crash_fn: Box::new(|_, _, _, _, _| ()), observers: tuple_list!(), name: "main", - phantom: PhantomData, }; let mut input = NopInput {}; assert!(in_mem_executor.run_target(&mut input).is_ok()); diff --git a/afl/src/inputs/mod.rs b/afl/src/inputs/mod.rs index 2c487d4aff..d422f299a5 100644 --- a/afl/src/inputs/mod.rs +++ b/afl/src/inputs/mod.rs @@ -3,7 +3,6 @@ pub use bytes::BytesInput; use alloc::vec::Vec; use core::{clone::Clone, fmt::Debug}; - #[cfg(feature = "std")] use std::{ fs::File, @@ -11,6 +10,8 @@ use std::{ path::Path, }; +use serde::{Deserialize, Serialize}; + use crate::AflError; /// An input for the target @@ -54,6 +55,16 @@ where { } } +/// An input for tests, mainly. There is no real use much else. +#[derive(Copy, Clone, Serialize, Deserialize, Debug)] +pub struct NopInput {} +impl Input for NopInput {} +impl HasTargetBytes for NopInput { + fn target_bytes(&self) -> TargetBytes { + TargetBytes::Owned(vec![0]) + } +} + pub enum TargetBytes<'a> { Ref(&'a [u8]), Owned(Vec), diff --git a/afl/src/utils.rs b/afl/src/utils.rs index 10700f0177..514adb159b 100644 --- a/afl/src/utils.rs +++ b/afl/src/utils.rs @@ -1,14 +1,51 @@ //! Utility functions for AFL -use alloc::rc::Rc; +use alloc::vec::Vec; use core::{cell::RefCell, debug_assert, fmt::Debug, time}; +use postcard; use xxhash_rust::xxh3::xxh3_64_with_seed; #[cfg(feature = "std")] use std::time::{SystemTime, UNIX_EPOCH}; +use crate::{corpus::Corpus, engines::State, feedbacks::FeedbacksTuple, inputs::Input, AflError}; + pub type StdRand = RomuTrioRand; +/// Serialize the current state and corpus during an executiont to bytes. +/// This method is needed when the fuzzer run crashes and has to restart. +pub fn serialize_state_corpus( + state: &State, + corpus: &C, +) -> Result, AflError> +where + C: Corpus, + FT: FeedbacksTuple, + I: Input, + R: Rand, +{ + let state_bytes = postcard::to_allocvec(&state)?; + let corpus_bytes = postcard::to_allocvec(&corpus)?; + Ok(postcard::to_allocvec(&(state_bytes, corpus_bytes))?) +} + +/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)` +pub fn deserialize_state_corpus( + state_corpus_serialized: &[u8], +) -> Result<(State, C), AflError> +where + C: Corpus, + FT: FeedbacksTuple, + I: Input, + R: Rand, +{ + let tuple: (Vec, Vec) = postcard::from_bytes(&state_corpus_serialized)?; + Ok(( + postcard::from_bytes(&tuple.0)?, + postcard::from_bytes(&tuple.1)?, + )) +} + /// Ways to get random around here pub trait Rand: Debug { // Sets the seed of this Rand @@ -137,12 +174,6 @@ impl Rand for Xoshiro256StarRand { } } -impl Into>> for Xoshiro256StarRand { - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) - } -} - impl Xoshiro256StarRand { /// Creates a new Xoshiro rand with the given seed pub fn new(seed: u64) -> Self { @@ -184,12 +215,6 @@ impl Rand for XorShift64Rand { } } -impl Into>> for XorShift64Rand { - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) - } -} - impl XorShift64Rand { /// Creates a new Xoshiro rand with the given seed pub fn new(seed: u64) -> Self { @@ -227,12 +252,6 @@ impl Rand for Lehmer64Rand { } } -impl Into>> for Lehmer64Rand { - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) - } -} - impl Lehmer64Rand { /// Creates a new Lehmer rand with the given seed pub fn new(seed: u64) -> Self { @@ -360,13 +379,6 @@ impl Rand for XKCDRand { } } -#[cfg(test)] -impl Into>> for XKCDRand { - fn into(self) -> Rc> { - Rc::new(RefCell::new(self)) - } -} - #[cfg(test)] impl XKCDRand { pub fn new() -> Self { diff --git a/fuzzers/libfuzzer_libpng/src/mod.rs b/fuzzers/libfuzzer_libpng/src/mod.rs index 1c0873644c..6eae65c509 100644 --- a/fuzzers/libfuzzer_libpng/src/mod.rs +++ b/fuzzers/libfuzzer_libpng/src/mod.rs @@ -13,10 +13,7 @@ use afl::{ shmem::{AflShmem, ShMem}, EventManager, LlmpEventManager, SimpleStats, }, - executors::{ - inmemory::{deserialize_state_corpus, serialize_state_corpus, InMemoryExecutor}, - Executor, ExitKind, - }, + executors::{inmemory::InMemoryExecutor, Executor, ExitKind}, feedbacks::MaxMapFeedback, generators::RandPrintablesGenerator, inputs::BytesInput, @@ -24,7 +21,7 @@ use afl::{ observers::StdMapObserver, stages::mutational::StdMutationalStage, tuples::tuple_list, - utils::StdRand, + utils::{deserialize_state_corpus, serialize_state_corpus, StdRand}, AflError, };