make nopstate public so that it can be used as reproducer (#1888)

This commit is contained in:
Addison Crump 2024-02-27 16:48:08 +01:00 committed by GitHub
parent 1dcfe8ef56
commit 7a4fb06d02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 169 additions and 144 deletions

View File

@ -693,7 +693,7 @@ mod tests {
fuzzer::test::NopFuzzer, fuzzer::test::NopFuzzer,
inputs::BytesInput, inputs::BytesInput,
monitors::SimpleMonitor, monitors::SimpleMonitor,
state::test::NopState, state::NopState,
}; };
#[test] #[test]

View File

@ -560,7 +560,7 @@ mod tests {
inprocess_fork::GenericInProcessForkExecutor, Executor, inprocess_fork::GenericInProcessForkExecutor, Executor,
}, },
fuzzer::test::NopFuzzer, fuzzer::test::NopFuzzer,
state::test::NopState, state::NopState,
}; };
let provider = StdShMemProvider::new().unwrap(); let provider = StdShMemProvider::new().unwrap();

View File

@ -174,7 +174,7 @@ pub mod test {
executors::{Executor, ExitKind}, executors::{Executor, ExitKind},
fuzzer::test::NopFuzzer, fuzzer::test::NopFuzzer,
inputs::{BytesInput, HasTargetBytes}, inputs::{BytesInput, HasTargetBytes},
state::{test::NopState, HasExecutions, State, UsesState}, state::{HasExecutions, NopState, State, UsesState},
}; };
/// A simple executor that does nothing. /// A simple executor that does nothing.

View File

@ -163,7 +163,7 @@ mod tests {
feedbacks::{differential::DiffResult, DiffFeedback, Feedback}, feedbacks::{differential::DiffResult, DiffFeedback, Feedback},
inputs::{BytesInput, UsesInput}, inputs::{BytesInput, UsesInput},
observers::Observer, observers::Observer,
state::{test::NopState, State, UsesState}, state::{NopState, State, UsesState},
}; };
#[derive(Debug)] #[derive(Debug)]

View File

@ -376,7 +376,7 @@ mod test {
use crate::{ use crate::{
inputs::BytesInput, inputs::BytesInput,
mutators::{ByteRandMutator, ScheduledMutator}, mutators::{ByteRandMutator, ScheduledMutator},
state::test::NopState, state::NopState,
}; };
#[test] #[test]

View File

@ -14,7 +14,7 @@ use std::{
}; };
use libafl_bolts::{ use libafl_bolts::{
rands::Rand, rands::{Rand, StdRand},
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap}, serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
}; };
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
@ -998,149 +998,139 @@ impl<I, C, R, SC> HasScalabilityMonitor for StdState<I, C, R, SC> {
} }
} }
/// A very simple state without any bells or whistles, for testing.
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct NopState<I> {
metadata: SerdeAnyMap,
execution: usize,
rand: StdRand,
phantom: PhantomData<I>,
}
impl<I> NopState<I> {
/// 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<I> UsesInput for NopState<I>
where
I: Input,
{
type Input = I;
}
impl<I> HasExecutions for NopState<I> {
fn executions(&self) -> &usize {
&self.execution
}
fn executions_mut(&mut self) -> &mut usize {
&mut self.execution
}
}
impl<I> HasLastReportTime for NopState<I> {
fn last_report_time(&self) -> &Option<Duration> {
unimplemented!();
}
fn last_report_time_mut(&mut self) -> &mut Option<Duration> {
unimplemented!();
}
}
impl<I> HasMetadata for NopState<I> {
fn metadata_map(&self) -> &SerdeAnyMap {
&self.metadata
}
fn metadata_map_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl<I> HasRand for NopState<I> {
type Rand = StdRand;
fn rand(&self) -> &Self::Rand {
&self.rand
}
fn rand_mut(&mut self) -> &mut Self::Rand {
&mut self.rand
}
}
impl<I> State for NopState<I> where I: Input {}
impl<I> HasCurrentCorpusIdx for NopState<I> {
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<Option<CorpusId>, Error> {
Ok(None)
}
}
impl<I> HasCurrentStage for NopState<I> {
fn set_stage(&mut self, _idx: usize) -> Result<(), Error> {
Ok(())
}
fn clear_stage(&mut self) -> Result<(), Error> {
Ok(())
}
fn current_stage(&self) -> Result<Option<usize>, Error> {
Ok(None)
}
}
#[cfg(feature = "introspection")]
impl<I> HasClientPerfMonitor for NopState<I> {
fn introspection_monitor(&self) -> &ClientPerfMonitor {
unimplemented!();
}
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
unimplemented!();
}
}
#[cfg(feature = "scalability_introspection")]
impl<I> HasScalabilityMonitor for NopState<I> {
fn scalability_monitor(&self) -> &ScalabilityMonitor {
unimplemented!();
}
fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor {
unimplemented!();
}
}
#[cfg(test)] #[cfg(test)]
pub mod test { pub mod test {
use core::{marker::PhantomData, time::Duration}; use libafl_bolts::rands::StdRand;
use libafl_bolts::{rands::StdRand, serdeany::SerdeAnyMap, Error};
use serde::{Deserialize, Serialize};
use super::StdState;
use crate::{ use crate::{
corpus::{CorpusId, HasCurrentCorpusIdx, InMemoryCorpus}, corpus::InMemoryCorpus,
inputs::{Input, NopInput, UsesInput}, inputs::{Input, NopInput},
stages::test::{test_resume, test_resume_stages}, 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<I> {
metadata: SerdeAnyMap,
execution: usize,
rand: StdRand,
phantom: PhantomData<I>,
}
impl<I> NopState<I> {
/// 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<I> UsesInput for NopState<I>
where
I: Input,
{
type Input = I;
}
impl<I> HasExecutions for NopState<I> {
fn executions(&self) -> &usize {
&self.execution
}
fn executions_mut(&mut self) -> &mut usize {
&mut self.execution
}
}
impl<I> HasLastReportTime for NopState<I> {
fn last_report_time(&self) -> &Option<Duration> {
unimplemented!();
}
fn last_report_time_mut(&mut self) -> &mut Option<Duration> {
unimplemented!();
}
}
impl<I> HasMetadata for NopState<I> {
fn metadata_map(&self) -> &SerdeAnyMap {
&self.metadata
}
fn metadata_map_mut(&mut self) -> &mut SerdeAnyMap {
&mut self.metadata
}
}
impl<I> HasRand for NopState<I> {
type Rand = StdRand;
fn rand(&self) -> &Self::Rand {
&self.rand
}
fn rand_mut(&mut self) -> &mut Self::Rand {
&mut self.rand
}
}
impl<I> State for NopState<I> where I: Input {}
impl<I> HasCurrentCorpusIdx for NopState<I> {
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<Option<CorpusId>, Error> {
Ok(None)
}
}
impl<I> HasCurrentStage for NopState<I> {
fn set_stage(&mut self, _idx: usize) -> Result<(), Error> {
Ok(())
}
fn clear_stage(&mut self) -> Result<(), Error> {
Ok(())
}
fn current_stage(&self) -> Result<Option<usize>, Error> {
Ok(None)
}
}
#[cfg(feature = "introspection")]
impl<I> HasClientPerfMonitor for NopState<I> {
fn introspection_monitor(&self) -> &ClientPerfMonitor {
unimplemented!();
}
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
unimplemented!();
}
}
#[cfg(feature = "scalability_introspection")]
impl<I> HasScalabilityMonitor for NopState<I> {
fn scalability_monitor(&self) -> &ScalabilityMonitor {
unimplemented!();
}
fn scalability_monitor_mut(&mut self) -> &mut ScalabilityMonitor {
unimplemented!();
}
}
#[must_use] #[must_use]
pub fn test_std_state<I: Input>() -> StdState<I, InMemoryCorpus<I>, StdRand, InMemoryCorpus<I>> pub fn test_std_state<I: Input>() -> StdState<I, InMemoryCorpus<I>, StdRand, InMemoryCorpus<I>>

View File

@ -10,7 +10,11 @@ use core::{
ptr::{self, addr_of, addr_of_mut}, 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; pub use crate::emu::SyscallHookResult;
use crate::{ use crate::{
@ -337,6 +341,7 @@ where
} }
static mut HOOKS_IS_INITIALIZED: bool = false; static mut HOOKS_IS_INITIALIZED: bool = false;
static mut FIRST_EXEC: bool = true;
pub struct QemuHooks<QT, S> pub struct QemuHooks<QT, S>
where where
@ -361,6 +366,36 @@ where
} }
} }
impl<I, QT> QemuHooks<QT, NopState<I>>
where
QT: QemuHelperTuple<NopState<I>>,
NopState<I>: UsesInput<Input = I>,
{
pub fn reproducer(emulator: Emulator, helpers: QT) -> Box<Self> {
Self::new(emulator, helpers)
}
pub fn repro_run<H>(&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<QT, S> QemuHooks<QT, S> impl<QT, S> QemuHooks<QT, S>
where where
QT: QemuHelperTuple<S>, QT: QemuHelperTuple<S>,