diff --git a/libafl/src/executors/command.rs b/libafl/src/executors/command.rs index a37344ccfc..9754b0fe6e 100644 --- a/libafl/src/executors/command.rs +++ b/libafl/src/executors/command.rs @@ -693,7 +693,7 @@ mod tests { fuzzer::test::NopFuzzer, inputs::BytesInput, monitors::SimpleMonitor, - state::test::NopState, + state::NopState, }; #[test] diff --git a/libafl/src/executors/inprocess_fork.rs b/libafl/src/executors/inprocess_fork.rs index 50225439c8..a5aef5bcfc 100644 --- a/libafl/src/executors/inprocess_fork.rs +++ b/libafl/src/executors/inprocess_fork.rs @@ -560,7 +560,7 @@ mod tests { inprocess_fork::GenericInProcessForkExecutor, Executor, }, fuzzer::test::NopFuzzer, - state::test::NopState, + state::NopState, }; let provider = StdShMemProvider::new().unwrap(); diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index abb87814ac..66ddb54a39 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -174,7 +174,7 @@ pub mod test { executors::{Executor, ExitKind}, fuzzer::test::NopFuzzer, inputs::{BytesInput, HasTargetBytes}, - state::{test::NopState, HasExecutions, State, UsesState}, + state::{HasExecutions, NopState, State, UsesState}, }; /// A simple executor that does nothing. diff --git a/libafl/src/feedbacks/differential.rs b/libafl/src/feedbacks/differential.rs index b944df2438..7e11638b3f 100644 --- a/libafl/src/feedbacks/differential.rs +++ b/libafl/src/feedbacks/differential.rs @@ -163,7 +163,7 @@ mod tests { feedbacks::{differential::DiffResult, DiffFeedback, Feedback}, inputs::{BytesInput, UsesInput}, observers::Observer, - state::{test::NopState, State, UsesState}, + state::{NopState, State, UsesState}, }; #[derive(Debug)] diff --git a/libafl/src/mutators/tuneable.rs b/libafl/src/mutators/tuneable.rs index 2ce0686c1c..f417c9a314 100644 --- a/libafl/src/mutators/tuneable.rs +++ b/libafl/src/mutators/tuneable.rs @@ -376,7 +376,7 @@ mod test { use crate::{ inputs::BytesInput, mutators::{ByteRandMutator, ScheduledMutator}, - state::test::NopState, + state::NopState, }; #[test] diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 9bd2af6992..b01488fb50 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -14,7 +14,7 @@ use std::{ }; use libafl_bolts::{ - rands::Rand, + rands::{Rand, StdRand}, serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap}, }; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -998,149 +998,139 @@ impl HasScalabilityMonitor for StdState { } } +/// A very simple state without any bells or whistles, for testing. +#[derive(Debug, Serialize, Deserialize, Default)] +pub struct NopState { + metadata: SerdeAnyMap, + execution: usize, + rand: StdRand, + phantom: PhantomData, +} + +impl NopState { + /// Create a new State that does nothing (for tests) + #[must_use] + pub fn new() -> Self { + NopState { + metadata: SerdeAnyMap::new(), + execution: 0, + rand: StdRand::default(), + phantom: PhantomData, + } + } +} + +impl UsesInput for NopState +where + I: Input, +{ + type Input = I; +} + +impl HasExecutions for NopState { + fn executions(&self) -> &usize { + &self.execution + } + + fn executions_mut(&mut self) -> &mut usize { + &mut self.execution + } +} + +impl HasLastReportTime for NopState { + fn last_report_time(&self) -> &Option { + unimplemented!(); + } + + fn last_report_time_mut(&mut self) -> &mut Option { + unimplemented!(); + } +} + +impl HasMetadata for NopState { + fn metadata_map(&self) -> &SerdeAnyMap { + &self.metadata + } + + fn metadata_map_mut(&mut self) -> &mut SerdeAnyMap { + &mut self.metadata + } +} + +impl HasRand for NopState { + type Rand = StdRand; + + fn rand(&self) -> &Self::Rand { + &self.rand + } + + fn rand_mut(&mut self) -> &mut Self::Rand { + &mut self.rand + } +} + +impl State for NopState where I: Input {} + +impl HasCurrentCorpusIdx for NopState { + fn set_corpus_idx(&mut self, _idx: CorpusId) -> Result<(), Error> { + Ok(()) + } + + fn clear_corpus_idx(&mut self) -> Result<(), Error> { + Ok(()) + } + + fn current_corpus_idx(&self) -> Result, Error> { + Ok(None) + } +} + +impl HasCurrentStage for NopState { + fn set_stage(&mut self, _idx: usize) -> Result<(), Error> { + Ok(()) + } + + fn clear_stage(&mut self) -> Result<(), Error> { + Ok(()) + } + + fn current_stage(&self) -> Result, Error> { + Ok(None) + } +} + +#[cfg(feature = "introspection")] +impl HasClientPerfMonitor for NopState { + fn introspection_monitor(&self) -> &ClientPerfMonitor { + unimplemented!(); + } + + fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor { + unimplemented!(); + } +} + +#[cfg(feature = "scalability_introspection")] +impl HasScalabilityMonitor for NopState { + fn scalability_monitor(&self) -> &ScalabilityMonitor { + unimplemented!(); + } + + fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor { + unimplemented!(); + } +} + #[cfg(test)] pub mod test { - use core::{marker::PhantomData, time::Duration}; - - use libafl_bolts::{rands::StdRand, serdeany::SerdeAnyMap, Error}; - use serde::{Deserialize, Serialize}; + use libafl_bolts::rands::StdRand; + use super::StdState; use crate::{ - corpus::{CorpusId, HasCurrentCorpusIdx, InMemoryCorpus}, - inputs::{Input, NopInput, UsesInput}, + corpus::InMemoryCorpus, + inputs::{Input, NopInput}, stages::test::{test_resume, test_resume_stages}, - state::{ - HasCurrentStage, HasExecutions, HasLastReportTime, HasMetadata, HasRand, State, - StdState, - }, }; - #[cfg(feature = "introspection")] - use crate::{monitors::ClientPerfMonitor, state::HasClientPerfMonitor}; - #[cfg(feature = "scalability_introspection")] - use crate::{monitors::ScalabilityMonitor, state::HasScalabilityMonitor}; - - /// A very simple state without any bells or whistles, for testing. - #[derive(Debug, Serialize, Deserialize, Default)] - pub struct NopState { - metadata: SerdeAnyMap, - execution: usize, - rand: StdRand, - phantom: PhantomData, - } - - impl NopState { - /// Create a new State that does nothing (for tests) - #[must_use] - pub fn new() -> Self { - NopState { - metadata: SerdeAnyMap::new(), - execution: 0, - rand: StdRand::default(), - phantom: PhantomData, - } - } - } - - impl UsesInput for NopState - where - I: Input, - { - type Input = I; - } - - impl HasExecutions for NopState { - fn executions(&self) -> &usize { - &self.execution - } - - fn executions_mut(&mut self) -> &mut usize { - &mut self.execution - } - } - - impl HasLastReportTime for NopState { - fn last_report_time(&self) -> &Option { - unimplemented!(); - } - - fn last_report_time_mut(&mut self) -> &mut Option { - unimplemented!(); - } - } - - impl HasMetadata for NopState { - fn metadata_map(&self) -> &SerdeAnyMap { - &self.metadata - } - - fn metadata_map_mut(&mut self) -> &mut SerdeAnyMap { - &mut self.metadata - } - } - - impl HasRand for NopState { - type Rand = StdRand; - - fn rand(&self) -> &Self::Rand { - &self.rand - } - - fn rand_mut(&mut self) -> &mut Self::Rand { - &mut self.rand - } - } - - impl State for NopState where I: Input {} - - impl HasCurrentCorpusIdx for NopState { - fn set_corpus_idx(&mut self, _idx: CorpusId) -> Result<(), Error> { - Ok(()) - } - - fn clear_corpus_idx(&mut self) -> Result<(), Error> { - Ok(()) - } - - fn current_corpus_idx(&self) -> Result, Error> { - Ok(None) - } - } - - impl HasCurrentStage for NopState { - fn set_stage(&mut self, _idx: usize) -> Result<(), Error> { - Ok(()) - } - - fn clear_stage(&mut self) -> Result<(), Error> { - Ok(()) - } - - fn current_stage(&self) -> Result, Error> { - Ok(None) - } - } - - #[cfg(feature = "introspection")] - impl HasClientPerfMonitor for NopState { - fn introspection_monitor(&self) -> &ClientPerfMonitor { - unimplemented!(); - } - - fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor { - unimplemented!(); - } - } - - #[cfg(feature = "scalability_introspection")] - impl HasScalabilityMonitor for NopState { - fn scalability_monitor(&self) -> &ScalabilityMonitor { - unimplemented!(); - } - - fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor { - unimplemented!(); - } - } #[must_use] pub fn test_std_state() -> StdState, StdRand, InMemoryCorpus> diff --git a/libafl_qemu/src/hooks.rs b/libafl_qemu/src/hooks.rs index a1a6aad8be..2e73153578 100644 --- a/libafl_qemu/src/hooks.rs +++ b/libafl_qemu/src/hooks.rs @@ -10,7 +10,11 @@ use core::{ ptr::{self, addr_of, addr_of_mut}, }; -use libafl::{executors::hooks::inprocess::inprocess_get_state, inputs::UsesInput}; +use libafl::{ + executors::{hooks::inprocess::inprocess_get_state, ExitKind}, + inputs::UsesInput, + state::NopState, +}; pub use crate::emu::SyscallHookResult; use crate::{ @@ -337,6 +341,7 @@ where } static mut HOOKS_IS_INITIALIZED: bool = false; +static mut FIRST_EXEC: bool = true; pub struct QemuHooks where @@ -361,6 +366,36 @@ where } } +impl QemuHooks> +where + QT: QemuHelperTuple>, + NopState: UsesInput, +{ + pub fn reproducer(emulator: Emulator, helpers: QT) -> Box { + Self::new(emulator, helpers) + } + + pub fn repro_run(&mut self, harness: &mut H, input: &I) -> ExitKind + where + H: FnMut(&I) -> ExitKind, + { + unsafe { + if FIRST_EXEC { + self.helpers.first_exec_all(self); + FIRST_EXEC = false; + } + } + self.helpers.pre_exec_all(&self.emulator, input); + + let mut exit_kind = harness(input); + + self.helpers + .post_exec_all(&self.emulator, input, &mut (), &mut exit_kind); + + exit_kind + } +} + impl QemuHooks where QT: QemuHelperTuple,