No Uses* for Corpus, Mutators (#2547)

* wip

* this shit is crazy

* from windows

* fmt

* fuck

* fmt

* aa

* reduce generics for generator

* do stuff for mutators, too

* aa

* a

* fmt

* idk

* getting things compiling

* fix merge

* idk

* fuzzers

* nire

* more

* a

* frida win

* cmin

* mm

* qemu?

* del ubuntu dep

---------

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
Dongjia "toka" Zhang 2024-09-26 20:03:03 +02:00 committed by GitHub
parent 79cd1afec0
commit 79b8390214
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
79 changed files with 747 additions and 829 deletions

View File

@ -110,7 +110,6 @@ jobs:
ubuntu-miri: ubuntu-miri:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: ubuntu
steps: steps:
- name: Add nightly clippy - name: Add nightly clippy
run: rustup toolchain install nightly --component miri --allow-downgrade run: rustup toolchain install nightly --component miri --allow-downgrade

View File

@ -94,8 +94,8 @@ pub fn main() -> Result<(), Error> {
.expect("Failed to generate the initial corpus"); .expect("Failed to generate the initial corpus");
// Setup a mutational stage with a basic bytes mutator // Setup a mutational stage with a basic bytes mutator
let mutator = StdScheduledMutator::new(havoc_mutations::<BytesInput>()); let mutator = StdScheduledMutator::new(havoc_mutations());
let minimizer = StdScheduledMutator::new(havoc_mutations::<BytesInput>()); let minimizer = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!( let mut stages = tuple_list!(
StdMutationalStage::new(mutator), StdMutationalStage::new(mutator),
StdTMinMutationalStage::new(minimizer, factory, 128) StdTMinMutationalStage::new(minimizer, factory, 128)
@ -121,7 +121,7 @@ pub fn main() -> Result<(), Error> {
let mut mgr = SimpleEventManager::new(mon); let mut mgr = SimpleEventManager::new(mon);
let minimizer = StdScheduledMutator::new(havoc_mutations::<BytesInput>()); let minimizer = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(StdTMinMutationalStage::new( let mut stages = tuple_list!(StdTMinMutationalStage::new(
minimizer, minimizer,
CrashFeedback::new(), CrashFeedback::new(),

View File

@ -301,14 +301,15 @@ fn fuzz(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -307,14 +307,15 @@ fn fuzz(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -185,14 +185,15 @@ impl<'a, M: Monitor> Instance<'a, M> {
))); )));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -293,14 +293,15 @@ fn fuzz(
println!("Let's fuzz :)"); println!("Let's fuzz :)");
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -293,14 +293,15 @@ fn fuzz(
println!("Let's fuzz :)"); println!("Let's fuzz :)");
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -9,7 +9,7 @@ use std::{
}; };
use libafl::{ use libafl::{
corpus::{Corpus, HasCurrentCorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase}, corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase},
events::EventFirer, events::EventFirer,
executors::HasObservers, executors::HasObservers,
inputs::UsesInput, inputs::UsesInput,
@ -236,11 +236,11 @@ where
+ HasStartTime + HasStartTime
+ HasExecutions + HasExecutions
+ HasNamedMetadata + HasNamedMetadata
+ Stoppable + Stoppable,
+ HasTestcase,
O: MapObserver, O: MapObserver,
C: AsRef<O> + Named, C: AsRef<O> + Named,
<Z as HasScheduler>::Scheduler: HasQueueCycles, <Z as HasScheduler>::Scheduler: HasQueueCycles,
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>,
{ {
fn perform( fn perform(
&mut self, &mut self,

View File

@ -2,7 +2,6 @@ use std::marker::PhantomData;
use libafl::{ use libafl::{
corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
inputs::Input,
schedulers::{HasQueueCycles, RemovableScheduler, Scheduler}, schedulers::{HasQueueCycles, RemovableScheduler, Scheduler},
state::HasCorpus, state::HasCorpus,
Error, HasMetadata, Error, HasMetadata,
@ -14,17 +13,19 @@ pub enum SupportedSchedulers<Q, W> {
Weighted(W, PhantomData<Q>), Weighted(W, PhantomData<Q>),
} }
impl<I, Q, S, W> RemovableScheduler<I, S> for SupportedSchedulers<Q, W> impl<Q, S, W> RemovableScheduler<<S::Corpus as Corpus>::Input, S> for SupportedSchedulers<Q, W>
where where
Q: Scheduler<I, S> + RemovableScheduler<I, S>, Q: Scheduler<<S::Corpus as Corpus>::Input, S>
W: Scheduler<I, S> + RemovableScheduler<I, S>, + RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
W: Scheduler<<S::Corpus as Corpus>::Input, S>
+ RemovableScheduler<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus + HasTestcase, S: HasCorpus + HasTestcase,
{ {
fn on_remove( fn on_remove(
&mut self, &mut self,
state: &mut S, state: &mut S,
id: CorpusId, id: CorpusId,
testcase: &Option<Testcase<I>>, testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
match self { match self {
Self::Queue(queue, _) => queue.on_remove(state, id, testcase), Self::Queue(queue, _) => queue.on_remove(state, id, testcase),
@ -32,7 +33,12 @@ where
} }
} }
fn on_replace(&mut self, state: &mut S, id: CorpusId, prev: &Testcase<I>) -> Result<(), Error> { fn on_replace(
&mut self,
state: &mut S,
id: CorpusId,
prev: &Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
match self { match self {
Self::Queue(queue, _) => queue.on_replace(state, id, prev), Self::Queue(queue, _) => queue.on_replace(state, id, prev),
Self::Weighted(weighted, _) => weighted.on_replace(state, id, prev), Self::Weighted(weighted, _) => weighted.on_replace(state, id, prev),
@ -40,11 +46,10 @@ where
} }
} }
impl<I, Q, S, W> Scheduler<I, S> for SupportedSchedulers<Q, W> impl<Q, S, W> Scheduler<<S::Corpus as Corpus>::Input, S> for SupportedSchedulers<Q, W>
where where
I: Input, Q: Scheduler<<S::Corpus as Corpus>::Input, S>,
Q: Scheduler<I, S>, W: Scheduler<<S::Corpus as Corpus>::Input, S>,
W: Scheduler<I, S>,
S: HasCorpus + HasTestcase, S: HasCorpus + HasTestcase,
{ {
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
@ -77,7 +82,12 @@ where
Self::Weighted(weighted, _) => weighted.next(state), Self::Weighted(weighted, _) => weighted.next(state),
} }
} }
fn on_evaluation<OTB>(&mut self, state: &mut S, input: &I, observers: &OTB) -> Result<(), Error> fn on_evaluation<OTB>(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
observers: &OTB,
) -> Result<(), Error>
where where
OTB: MatchName, OTB: MatchName,
{ {

View File

@ -1,6 +1,7 @@
use std::{borrow::Cow, marker::PhantomData}; use std::{borrow::Cow, marker::PhantomData};
use libafl::{ use libafl::{
corpus::Corpus,
inputs::Input, inputs::Input,
mutators::Mutator, mutators::Mutator,
stages::{mutational::MutatedTransform, MutationalStage, Stage}, stages::{mutational::MutatedTransform, MutationalStage, Stage},
@ -26,6 +27,7 @@ where
SM: MutationalStage<E, EM, I, M, Z, State = S>, SM: MutationalStage<E, EM, I, M, Z, State = S>,
P: MutationalStage<E, EM, I, M, Z, State = S>, P: MutationalStage<E, EM, I, M, Z, State = S>,
S: State<Input = I> + HasRand + HasCorpus + HasNamedMetadata, S: State<Input = I> + HasRand + HasCorpus + HasNamedMetadata,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
#[inline] #[inline]
@ -85,6 +87,7 @@ where
SM: MutationalStage<E, EM, I, M, Z, State = S>, SM: MutationalStage<E, EM, I, M, Z, State = S>,
P: MutationalStage<E, EM, I, M, Z, State = S>, P: MutationalStage<E, EM, I, M, Z, State = S>,
S: State<Input = I> + HasRand + HasCorpus + HasNamedMetadata, S: State<Input = I> + HasRand + HasCorpus + HasNamedMetadata,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]

View File

@ -304,14 +304,15 @@ fn fuzz(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -298,14 +298,15 @@ fn fuzz(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -308,14 +308,15 @@ fn fuzz(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(

View File

@ -365,14 +365,15 @@ fn fuzz_binary(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
// A minimization+queue policy to get testcasess from the corpus // A minimization+queue policy to get testcasess from the corpus
let scheduler = IndexesLenTimeMinimizerScheduler::new( let scheduler = IndexesLenTimeMinimizerScheduler::new(
@ -577,14 +578,15 @@ fn fuzz_text(
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
// Setup a MOPT mutator // Setup a MOPT mutator
let mutator = StdMOptMutator::new( let mutator = StdMOptMutator::new::<BytesInput, _>(
&mut state, &mut state,
havoc_mutations().merge(tokens_mutations()), havoc_mutations().merge(tokens_mutations()),
7, 7,
5, 5,
)?; )?;
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
let grimoire_mutator = StdScheduledMutator::with_max_stack_pow( let grimoire_mutator = StdScheduledMutator::with_max_stack_pow(
tuple_list!( tuple_list!(

View File

@ -143,7 +143,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -6,10 +6,7 @@ use std::ptr;
use std::{env, path::PathBuf}; use std::{env, path::PathBuf};
use libafl::{ use libafl::{
corpus::{ corpus::{minimizer::StdCorpusMinimizer, Corpus, InMemoryCorpus, OnDiskCorpus},
minimizer::{CorpusMinimizer, StdCorpusMinimizer},
Corpus, InMemoryCorpus, OnDiskCorpus,
},
events::{setup_restarting_mgr_std, EventConfig, EventFirer, EventRestarter, LogSeverity}, events::{setup_restarting_mgr_std, EventConfig, EventFirer, EventRestarter, LogSeverity},
executors::{inprocess::InProcessExecutor, ExitKind}, executors::{inprocess::InProcessExecutor, ExitKind},
feedback_or, feedback_or_fast, feedback_or, feedback_or_fast,
@ -143,7 +140,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -141,7 +141,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -110,7 +110,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
StdPowerMutationalStage::new(mutator);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -128,7 +128,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// Setup a lain mutator with a mutational stage // Setup a lain mutator with a mutational stage
let mutator = LainMutator::new(); let mutator = LainMutator::new();
let power = StdPowerMutationalStage::new(mutator); let power: StdPowerMutationalStage<_, _, PacketData, _, _> =
StdPowerMutationalStage::new(mutator);
let mut stages = tuple_list!(calibration, power); let mut stages = tuple_list!(calibration, power);

View File

@ -1,7 +1,7 @@
use std::borrow::Cow; use std::borrow::Cow;
use libafl::{ use libafl::{
corpus::Testcase, corpus::{Corpus, Testcase},
events::EventFirer, events::EventFirer,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, MapIndexesMetadata}, feedbacks::{Feedback, MapIndexesMetadata},
@ -22,11 +22,14 @@ pub struct PacketLenMetadata {
pub struct PacketLenTestcaseScore {} pub struct PacketLenTestcaseScore {}
impl<S> TestcaseScore<PacketData, S> for PacketLenTestcaseScore impl<S> TestcaseScore<S> for PacketLenTestcaseScore
where where
S: HasCorpus<Input = PacketData> + HasMetadata, S: HasMetadata + HasCorpus,
{ {
fn compute(_state: &S, entry: &mut Testcase<PacketData>) -> Result<f64, Error> { fn compute(
_state: &S,
entry: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
Ok(entry Ok(entry
.metadata_map() .metadata_map()
.get::<PacketLenMetadata>() .get::<PacketLenMetadata>()

View File

@ -11,7 +11,7 @@ use crate::{
inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId, inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId,
HasTestcase, Testcase, HasTestcase, Testcase,
}, },
inputs::{Input, UsesInput}, inputs::Input,
Error, Error,
}; };
@ -20,23 +20,12 @@ use crate::{
/// The eviction policy is FIFO. /// The eviction policy is FIFO.
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct CachedOnDiskCorpus<I> {
pub struct CachedOnDiskCorpus<I>
where
I: Input,
{
inner: InMemoryOnDiskCorpus<I>, inner: InMemoryOnDiskCorpus<I>,
cached_indexes: RefCell<VecDeque<CorpusId>>, cached_indexes: RefCell<VecDeque<CorpusId>>,
cache_max_len: usize, cache_max_len: usize,
} }
impl<I> UsesInput for CachedOnDiskCorpus<I>
where
I: Input,
{
type Input = I;
}
impl<I> CachedOnDiskCorpus<I> impl<I> CachedOnDiskCorpus<I>
where where
I: Input, I: Input,
@ -71,6 +60,8 @@ impl<I> Corpus for CachedOnDiskCorpus<I>
where where
I: Input, I: Input,
{ {
type Input = I;
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
@ -193,22 +184,16 @@ impl<I> HasTestcase for CachedOnDiskCorpus<I>
where where
I: Input, I: Input,
{ {
fn testcase(&self, id: CorpusId) -> Result<core::cell::Ref<Testcase<Self::Input>>, Error> { fn testcase(&self, id: CorpusId) -> Result<core::cell::Ref<Testcase<I>>, Error> {
Ok(self.get(id)?.borrow()) Ok(self.get(id)?.borrow())
} }
fn testcase_mut( fn testcase_mut(&self, id: CorpusId) -> Result<core::cell::RefMut<Testcase<I>>, Error> {
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<Self::Input>>, Error> {
Ok(self.get(id)?.borrow_mut()) Ok(self.get(id)?.borrow_mut())
} }
} }
impl<I> CachedOnDiskCorpus<I> impl<I> CachedOnDiskCorpus<I> {
where
I: Input,
{
/// Creates the [`CachedOnDiskCorpus`]. /// Creates the [`CachedOnDiskCorpus`].
/// ///
/// This corpus stores (and reads) all testcases to/from disk /// This corpus stores (and reads) all testcases to/from disk

View File

@ -8,18 +8,13 @@ use serde::{Deserialize, Serialize};
use super::HasTestcase; use super::HasTestcase;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, Testcase},
inputs::{Input, UsesInput},
Error, Error,
}; };
/// Keep track of the stored `Testcase` and the siblings ids (insertion order) /// Keep track of the stored `Testcase` and the siblings ids (insertion order)
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct TestcaseStorageItem<I> {
pub struct TestcaseStorageItem<I>
where
I: Input,
{
/// The stored testcase /// The stored testcase
pub testcase: RefCell<Testcase<I>>, pub testcase: RefCell<Testcase<I>>,
/// Previously inserted id /// Previously inserted id
@ -30,11 +25,7 @@ where
/// The map type in which testcases are stored (disable the feature `corpus_btreemap` to use a `HashMap` instead of `BTreeMap`) /// The map type in which testcases are stored (disable the feature `corpus_btreemap` to use a `HashMap` instead of `BTreeMap`)
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct TestcaseStorageMap<I> {
pub struct TestcaseStorageMap<I>
where
I: Input,
{
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
/// A map of `CorpusId` to `TestcaseStorageItem` /// A map of `CorpusId` to `TestcaseStorageItem`
pub map: hashbrown::HashMap<CorpusId, TestcaseStorageItem<I>>, pub map: hashbrown::HashMap<CorpusId, TestcaseStorageItem<I>>,
@ -51,10 +42,7 @@ where
last_id: Option<CorpusId>, last_id: Option<CorpusId>,
} }
impl<I> TestcaseStorageMap<I> impl<I> TestcaseStorageMap<I> {
where
I: Input,
{
/// Insert a key in the keys set /// Insert a key in the keys set
fn insert_key(&mut self, id: CorpusId) { fn insert_key(&mut self, id: CorpusId) {
if let Err(idx) = self.keys.binary_search(&id) { if let Err(idx) = self.keys.binary_search(&id) {
@ -235,11 +223,7 @@ where
} }
/// Storage map for the testcases (used in `Corpus` implementations) with an incremental index /// Storage map for the testcases (used in `Corpus` implementations) with an incremental index
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct TestcaseStorage<I> {
pub struct TestcaseStorage<I>
where
I: Input,
{
/// The map in which enabled testcases are stored /// The map in which enabled testcases are stored
pub enabled: TestcaseStorageMap<I>, pub enabled: TestcaseStorageMap<I>,
/// The map in which disabled testcases are stored /// The map in which disabled testcases are stored
@ -248,17 +232,7 @@ where
progressive_id: usize, progressive_id: usize,
} }
impl<I> UsesInput for TestcaseStorage<I> impl<I> TestcaseStorage<I> {
where
I: Input,
{
type Input = I;
}
impl<I> TestcaseStorage<I>
where
I: Input,
{
/// Insert a testcase assigning a `CorpusId` to it /// Insert a testcase assigning a `CorpusId` to it
pub fn insert(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId { pub fn insert(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId {
self.insert_inner(testcase, false) self.insert_inner(testcase, false)
@ -335,26 +309,14 @@ where
/// A corpus handling all in memory. /// A corpus handling all in memory.
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct InMemoryCorpus<I> {
pub struct InMemoryCorpus<I>
where
I: Input,
{
storage: TestcaseStorage<I>, storage: TestcaseStorage<I>,
current: Option<CorpusId>, current: Option<CorpusId>,
} }
impl<I> UsesInput for InMemoryCorpus<I> impl<I> Corpus for InMemoryCorpus<I> {
where
I: Input,
{
type Input = I; type Input = I;
}
impl<I> Corpus for InMemoryCorpus<I>
where
I: Input,
{
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
@ -492,29 +454,23 @@ where
} }
} }
impl<I> HasTestcase for InMemoryCorpus<I> impl<I> HasTestcase for InMemoryCorpus<I> {
where
I: Input,
{
fn testcase( fn testcase(
&self, &self,
id: CorpusId, id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> { ) -> Result<core::cell::Ref<Testcase<<Self::Corpus as Corpus>::Input>>, Error> {
Ok(self.get(id)?.borrow()) Ok(self.get(id)?.borrow())
} }
fn testcase_mut( fn testcase_mut(
&self, &self,
id: CorpusId, id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> { ) -> Result<core::cell::RefMut<Testcase<<Self::Corpus as Corpus>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut()) Ok(self.get(id)?.borrow_mut())
} }
} }
impl<I> InMemoryCorpus<I> impl<I> InMemoryCorpus<I> {
where
I: Input,
{
/// Creates a new [`InMemoryCorpus`], keeping all [`Testcase`]`s` in memory. /// Creates a new [`InMemoryCorpus`], keeping all [`Testcase`]`s` in memory.
/// This is the simplest and fastest option, however test progress will be lost on exit or on OOM. /// This is the simplest and fastest option, however test progress will be lost on exit or on OOM.
#[must_use] #[must_use]

View File

@ -24,7 +24,7 @@ use super::{
}; };
use crate::{ use crate::{
corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase}, corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase},
inputs::{Input, UsesInput}, inputs::Input,
Error, HasMetadata, Error, HasMetadata,
}; };
@ -52,11 +52,7 @@ fn try_create_new<P: AsRef<Path>>(path: P) -> Result<Option<File>, io::Error> {
/// Metadata is written to a `.<filename>.metadata` file in the same folder by default. /// Metadata is written to a `.<filename>.metadata` file in the same folder by default.
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct InMemoryOnDiskCorpus<I> {
pub struct InMemoryOnDiskCorpus<I>
where
I: Input,
{
inner: InMemoryCorpus<I>, inner: InMemoryCorpus<I>,
dir_path: PathBuf, dir_path: PathBuf,
meta_format: Option<OnDiskMetadataFormat>, meta_format: Option<OnDiskMetadataFormat>,
@ -64,17 +60,12 @@ where
locking: bool, locking: bool,
} }
impl<I> UsesInput for InMemoryOnDiskCorpus<I>
where
I: Input,
{
type Input = I;
}
impl<I> Corpus for InMemoryOnDiskCorpus<I> impl<I> Corpus for InMemoryOnDiskCorpus<I>
where where
I: Input, I: Input,
{ {
type Input = I;
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
@ -228,22 +219,19 @@ where
fn testcase( fn testcase(
&self, &self,
id: CorpusId, id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> { ) -> Result<core::cell::Ref<Testcase<<Self as Corpus>::Input>>, Error> {
Ok(self.get(id)?.borrow()) Ok(self.get(id)?.borrow())
} }
fn testcase_mut( fn testcase_mut(
&self, &self,
id: CorpusId, id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> { ) -> Result<core::cell::RefMut<Testcase<<Self as Corpus>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut()) Ok(self.get(id)?.borrow_mut())
} }
} }
impl<I> InMemoryOnDiskCorpus<I> impl<I> InMemoryOnDiskCorpus<I> {
where
I: Input,
{
/// Creates an [`InMemoryOnDiskCorpus`]. /// Creates an [`InMemoryOnDiskCorpus`].
/// ///
/// This corpus stores all testcases to disk, and keeps all of them in memory, as well. /// This corpus stores all testcases to disk, and keeps all of them in memory, as well.
@ -388,7 +376,10 @@ where
} }
} }
fn save_testcase(&self, testcase: &mut Testcase<I>, id: CorpusId) -> Result<(), Error> { fn save_testcase(&self, testcase: &mut Testcase<I>, id: CorpusId) -> Result<(), Error>
where
I: Input,
{
let file_name_orig = testcase.filename_mut().take().unwrap_or_else(|| { let file_name_orig = testcase.filename_mut().take().unwrap_or_else(|| {
// TODO walk entry metadata to ask for pieces of filename (e.g. :havoc in AFL) // TODO walk entry metadata to ask for pieces of filename (e.g. :havoc in AFL)
testcase.input().as_ref().unwrap().generate_name(Some(id)) testcase.input().as_ref().unwrap().generate_name(Some(id))

View File

@ -24,28 +24,6 @@ use crate::{
Error, HasMetadata, HasScheduler, Error, HasMetadata, HasScheduler,
}; };
/// `CorpusMinimizers` minimize corpora according to internal logic. See various implementations for
/// details.
pub trait CorpusMinimizer<E>
where
E: UsesState,
E::State: HasCorpus,
{
/// Minimize the corpus of the provided state.
fn minimize<CS, EM, Z>(
&self,
fuzzer: &mut Z,
executor: &mut E,
manager: &mut EM,
state: &mut E::State,
) -> Result<(), Error>
where
E: Executor<EM, Z> + HasObservers,
CS: Scheduler<E::Input, E::State> + RemovableScheduler<E::Input, E::State>, // schedulers that has on_remove/on_replace only!
EM: EventFirer<State = E::State>,
Z: HasScheduler<Scheduler = CS, State = E::State>;
}
/// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`. /// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`.
/// ///
/// Algorithm based on WMOPT: <https://hexhive.epfl.ch/publications/files/21ISSTA2.pdf> /// Algorithm based on WMOPT: <https://hexhive.epfl.ch/publications/files/21ISSTA2.pdf>
@ -62,7 +40,7 @@ impl<C, E, O, T, TS> MapCorpusMinimizer<C, E, O, T, TS>
where where
E: UsesState, E: UsesState,
E::State: HasCorpus + HasMetadata, E::State: HasCorpus + HasMetadata,
TS: TestcaseScore<E::Input, E::State>, TS: TestcaseScore<E::State>,
C: Named, C: Named,
{ {
/// Constructs a new `MapCorpusMinimizer` from a provided observer. This observer will be used /// Constructs a new `MapCorpusMinimizer` from a provided observer. This observer will be used
@ -75,17 +53,19 @@ where
} }
} }
impl<C, E, O, T, TS> CorpusMinimizer<E> for MapCorpusMinimizer<C, E, O, T, TS> impl<C, E, O, T, TS> MapCorpusMinimizer<C, E, O, T, TS>
where where
E: UsesState, E: UsesState,
for<'a> O: MapObserver<Entry = T> + AsIter<'a, Item = T>, for<'a> O: MapObserver<Entry = T> + AsIter<'a, Item = T>,
C: AsRef<O>, C: AsRef<O>,
E::State: HasMetadata + HasCorpus + HasExecutions, E::State: HasMetadata + HasCorpus + HasExecutions,
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>,
T: Copy + Hash + Eq, T: Copy + Hash + Eq,
TS: TestcaseScore<E::Input, E::State>, TS: TestcaseScore<E::State>,
{ {
/// Do the minimization
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
fn minimize<CS, EM, Z>( pub fn minimize<CS, EM, Z>(
&self, &self,
fuzzer: &mut Z, fuzzer: &mut Z,
executor: &mut E, executor: &mut E,

View File

@ -31,7 +31,7 @@ pub use minimizer::*;
pub use nop::NopCorpus; pub use nop::NopCorpus;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{inputs::UsesInput, Error}; use crate::Error;
/// An abstraction for the index that identify a testcase in the corpus /// An abstraction for the index that identify a testcase in the corpus
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
@ -85,7 +85,10 @@ macro_rules! random_corpus_id_with_disabled {
} }
/// Corpus with all current [`Testcase`]s, or solutions /// Corpus with all current [`Testcase`]s, or solutions
pub trait Corpus: UsesInput + Serialize + for<'de> Deserialize<'de> { pub trait Corpus: Sized {
/// The type of input contained in this corpus
type Input;
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
fn count(&self) -> usize; fn count(&self) -> usize;
@ -171,7 +174,10 @@ pub trait Corpus: UsesInput + Serialize + for<'de> Deserialize<'de> {
fn store_input_from(&self, testcase: &Testcase<Self::Input>) -> Result<(), Error>; fn store_input_from(&self, testcase: &Testcase<Self::Input>) -> Result<(), Error>;
/// Loads the `Input` for a given [`CorpusId`] from the [`Corpus`], and returns the clone. /// Loads the `Input` for a given [`CorpusId`] from the [`Corpus`], and returns the clone.
fn cloned_input_for_id(&self, id: CorpusId) -> Result<Self::Input, Error> { fn cloned_input_for_id(&self, id: CorpusId) -> Result<Self::Input, Error>
where
Self::Input: Clone,
{
let mut testcase = self.get(id)?.borrow_mut(); let mut testcase = self.get(id)?.borrow_mut();
Ok(testcase.load_input(self)?.clone()) Ok(testcase.load_input(self)?.clone())
} }

View File

@ -5,29 +5,18 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, Testcase},
inputs::{Input, UsesInput},
Error, Error,
}; };
/// A corpus which does not store any [`Testcase`]s. /// A corpus which does not store any [`Testcase`]s.
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")]
pub struct NopCorpus<I> { pub struct NopCorpus<I> {
empty: Option<CorpusId>, empty: Option<CorpusId>,
phantom: PhantomData<I>, phantom: PhantomData<I>,
} }
impl<I> UsesInput for NopCorpus<I> impl<I> Corpus for NopCorpus<I> {
where
I: Input,
{
type Input = I; type Input = I;
}
impl<I> Corpus for NopCorpus<I>
where
I: Input,
{
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
@ -142,10 +131,7 @@ where
} }
} }
impl<I> NopCorpus<I> impl<I> NopCorpus<I> {
where
I: Input,
{
/// Creates a new [`NopCorpus`]. /// Creates a new [`NopCorpus`].
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {

View File

@ -6,7 +6,10 @@
//! which stores a certain number of [`Testcase`]s in memory and removes additional ones in a FIFO manner. //! which stores a certain number of [`Testcase`]s in memory and removes additional ones in a FIFO manner.
use alloc::string::String; use alloc::string::String;
use core::{cell::RefCell, time::Duration}; use core::{
cell::{Ref, RefCell, RefMut},
time::Duration,
};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use libafl_bolts::serdeany::SerdeAnyMap; use libafl_bolts::serdeany::SerdeAnyMap;
@ -14,7 +17,7 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase}, corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase},
inputs::{Input, UsesInput}, inputs::Input,
Error, Error,
}; };
@ -49,28 +52,18 @@ pub struct OnDiskMetadata<'a> {
/// ///
/// Metadata is written to a `.<filename>.metadata` file in the same folder by default. /// Metadata is written to a `.<filename>.metadata` file in the same folder by default.
#[derive(Default, Serialize, Deserialize, Clone, Debug)] #[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "I: serde::de::DeserializeOwned")] pub struct OnDiskCorpus<I> {
pub struct OnDiskCorpus<I>
where
I: Input,
{
/// The root directory backing this corpus /// The root directory backing this corpus
dir_path: PathBuf, dir_path: PathBuf,
/// We wrapp a cached corpus and set its size to 1. /// We wrapp a cached corpus and set its size to 1.
inner: CachedOnDiskCorpus<I>, inner: CachedOnDiskCorpus<I>,
} }
impl<I> UsesInput for OnDiskCorpus<I>
where
I: Input,
{
type Input = I;
}
impl<I> Corpus for OnDiskCorpus<I> impl<I> Corpus for OnDiskCorpus<I>
where where
I: Input, I: Input,
{ {
type Input = I;
/// Returns the number of all enabled entries /// Returns the number of all enabled entries
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
@ -188,25 +181,16 @@ impl<I> HasTestcase for OnDiskCorpus<I>
where where
I: Input, I: Input,
{ {
fn testcase( fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<I>>, Error> {
&self,
id: CorpusId,
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow()) Ok(self.get(id)?.borrow())
} }
fn testcase_mut( fn testcase_mut(&self, id: CorpusId) -> Result<RefMut<Testcase<I>>, Error> {
&self,
id: CorpusId,
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.get(id)?.borrow_mut()) Ok(self.get(id)?.borrow_mut())
} }
} }
impl<I> OnDiskCorpus<I> impl<I> OnDiskCorpus<I> {
where
I: Input,
{
/// Creates an [`OnDiskCorpus`]. /// Creates an [`OnDiskCorpus`].
/// ///
/// This corpus stores all testcases to disk. /// This corpus stores all testcases to disk.

View File

@ -15,21 +15,24 @@ use libafl_bolts::{serdeany::SerdeAnyMap, HasLen};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::Corpus; use super::Corpus;
use crate::{corpus::CorpusId, inputs::UsesInput, Error, HasMetadata}; use crate::{corpus::CorpusId, state::HasCorpus, Error, HasMetadata};
/// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
pub trait HasTestcase: UsesInput { pub trait HasTestcase: HasCorpus {
/// Shorthand to receive a [`Ref`] to a stored [`Testcase`], by [`CorpusId`]. /// Shorthand to receive a [`Ref`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<<Self as UsesInput>::Input>>, Error>; fn testcase(
&self,
id: CorpusId,
) -> Result<Ref<Testcase<<Self::Corpus as Corpus>::Input>>, Error>;
/// Shorthand to receive a [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// Shorthand to receive a [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
fn testcase_mut( fn testcase_mut(
&self, &self,
id: CorpusId, id: CorpusId,
) -> Result<RefMut<Testcase<<Self as UsesInput>::Input>>, Error>; ) -> Result<RefMut<Testcase<<Self::Corpus as Corpus>::Input>>, Error>;
} }
/// An entry in the [`Testcase`] Corpus /// An entry in the [`Testcase`] Corpus

View File

@ -28,11 +28,12 @@ use crate::executors::hooks::unix::unix_signal_handler;
#[cfg(windows)] #[cfg(windows)]
use crate::state::State; use crate::state::State;
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers},
feedbacks::Feedback, feedbacks::Feedback,
inputs::UsesInput, inputs::UsesInput,
state::{HasCorpus, HasExecutions, HasSolutions}, state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
Error, HasObjective, Error, HasObjective,
}; };
/// The inmem executor's handlers. /// The inmem executor's handlers.
@ -236,6 +237,8 @@ where
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
// # Safety // # Safety
// We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time. // We get a pointer to `GLOBAL_STATE` that will be initialized at this point in time.
@ -276,6 +279,8 @@ where
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: State + HasExecutions + HasSolutions + HasCorpus, E::State: State + HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let ret; let ret;
#[cfg(feature = "std")] #[cfg(feature = "std")]

View File

@ -9,6 +9,7 @@ pub mod unix_signal_handler {
use libc::siginfo_t; use libc::siginfo_t;
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
common_signals, common_signals,
@ -19,7 +20,7 @@ pub mod unix_signal_handler {
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
state::{HasCorpus, HasExecutions, HasSolutions}, state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
}; };
pub(crate) type HandlerFuncPtr = unsafe fn( pub(crate) type HandlerFuncPtr = unsafe fn(
@ -80,6 +81,8 @@ pub mod unix_signal_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| unsafe { panic::set_hook(Box::new(move |panic_info| unsafe {
@ -127,6 +130,8 @@ pub mod unix_signal_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
// this stuff is for batch timeout // this stuff is for batch timeout
if !data.executor_ptr.is_null() if !data.executor_ptr.is_null()
@ -182,6 +187,8 @@ pub mod unix_signal_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
#[cfg(all(target_os = "android", target_arch = "aarch64"))] #[cfg(all(target_os = "android", target_arch = "aarch64"))]
let _context = _context.map(|p| { let _context = _context.map(|p| {

View File

@ -12,6 +12,7 @@ pub mod windows_asan_handler {
}; };
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor, hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor,
@ -20,7 +21,7 @@ pub mod windows_asan_handler {
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::UsesInput, inputs::UsesInput,
state::{HasCorpus, HasExecutions, HasSolutions}, state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
}; };
/// # Safety /// # Safety
@ -32,6 +33,8 @@ pub mod windows_asan_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let data = addr_of_mut!(GLOBAL_STATE); let data = addr_of_mut!(GLOBAL_STATE);
(*data).set_in_handler(true); (*data).set_in_handler(true);
@ -125,6 +128,7 @@ pub mod windows_exception_handler {
}; };
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE}, hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE},
@ -134,7 +138,7 @@ pub mod windows_exception_handler {
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::{Input, UsesInput}, inputs::{Input, UsesInput},
state::{HasCorpus, HasExecutions, HasSolutions, State}, state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
}; };
pub(crate) type HandlerFuncPtr = pub(crate) type HandlerFuncPtr =
@ -180,6 +184,8 @@ pub mod windows_exception_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| unsafe { panic::set_hook(Box::new(move |panic_info| unsafe {
@ -240,6 +246,8 @@ pub mod windows_exception_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: State + HasExecutions + HasSolutions + HasCorpus, E::State: State + HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let data: &mut InProcessExecutorHandlerData = let data: &mut InProcessExecutorHandlerData =
&mut *(global_state as *mut InProcessExecutorHandlerData); &mut *(global_state as *mut InProcessExecutorHandlerData);
@ -310,6 +318,8 @@ pub mod windows_exception_handler {
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
// Have we set a timer_before? // Have we set a timer_before?
if data.ptp_timer.is_some() { if data.ptp_timer.is_some() {

View File

@ -16,6 +16,7 @@ use crate::executors::hooks::inprocess::HasTimeout;
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
use crate::executors::hooks::inprocess::HasTimeout; use crate::executors::hooks::inprocess::HasTimeout;
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::{ hooks::{
@ -178,6 +179,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
Self::with_timeout_generic::<E, EM, OF, Z>( Self::with_timeout_generic::<E, EM, OF, Z>(
user_hooks, user_hooks,
@ -205,6 +208,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let mut me = Self::with_timeout_generic::<E, EM, OF, Z>( let mut me = Self::with_timeout_generic::<E, EM, OF, Z>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
@ -235,6 +240,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let default = InProcessHooks::new::<E, EM, OF, Z>(timeout)?; let default = InProcessHooks::new::<E, EM, OF, Z>(timeout)?;
let mut hooks = tuple_list!(default).merge(user_hooks); let mut hooks = tuple_list!(default).merge(user_hooks);

View File

@ -168,6 +168,8 @@ where
H: FnMut(&S::Input) -> ExitKind + ?Sized, H: FnMut(&S::Input) -> ExitKind + ?Sized,
OT: ObserversTuple<S>, OT: ObserversTuple<S>,
S: HasExecutions + HasSolutions + HasCorpus + State, S: HasExecutions + HasSolutions + HasCorpus + State,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn new<EM, OF, Z>( pub fn new<EM, OF, Z>(
@ -211,6 +213,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
tuple_list!(), tuple_list!(),
@ -250,6 +254,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
tuple_list!(), tuple_list!(),
@ -275,6 +281,8 @@ where
HT: ExecutorHooksTuple<S>, HT: ExecutorHooksTuple<S>,
OT: ObserversTuple<S>, OT: ObserversTuple<S>,
S: State + HasExecutions + HasSolutions + HasCorpus, S: State + HasExecutions + HasSolutions + HasCorpus,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn generic<EM, OF, Z>( pub fn generic<EM, OF, Z>(
@ -320,6 +328,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
@ -355,6 +365,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
user_hooks, observers, fuzzer, state, event_mgr, timeout, user_hooks, observers, fuzzer, state, event_mgr, timeout,
@ -431,7 +443,7 @@ where
pub fn run_observers_and_save_state<E, EM, OF, Z>( pub fn run_observers_and_save_state<E, EM, OF, Z>(
executor: &mut E, executor: &mut E,
state: &mut E::State, state: &mut E::State,
input: &<E::State as UsesInput>::Input, input: &E::Input,
fuzzer: &mut Z, fuzzer: &mut Z,
event_mgr: &mut EM, event_mgr: &mut EM,
exitkind: ExitKind, exitkind: ExitKind,
@ -439,8 +451,9 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
E: HasObservers, E: HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>, EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
{ {
let mut observers = executor.observers_mut(); let mut observers = executor.observers_mut();
@ -500,10 +513,11 @@ where
E: Executor<EM, Z> + HasObservers, E: Executor<EM, Z> + HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>, EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF, State = E::State> Z: HasObjective<Objective = OF, State = E::State>
+ HasScheduler<State = E::State> + HasScheduler<State = E::State>
+ ExecutionProcessor, + ExecutionProcessor,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
{ {
let data = addr_of_mut!(GLOBAL_STATE); let data = addr_of_mut!(GLOBAL_STATE);
let in_handler = (*data).set_in_handler(true); let in_handler = (*data).set_in_handler(true);

View File

@ -11,6 +11,7 @@ use core::{
use libafl_bolts::tuples::{tuple_list, RefIndexable}; use libafl_bolts::tuples::{tuple_list, RefIndexable};
use crate::{ use crate::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple}, hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
@ -157,6 +158,8 @@ where
H: FnMut(&mut ES, &mut S, &<S as UsesInput>::Input) -> ExitKind + ?Sized, H: FnMut(&mut ES, &mut S, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
OT: ObserversTuple<S>, OT: ObserversTuple<S>,
S: HasExecutions + HasSolutions + HasCorpus + State, S: HasExecutions + HasSolutions + HasCorpus + State,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn new<EM, OF, Z>( pub fn new<EM, OF, Z>(
@ -203,6 +206,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
tuple_list!(), tuple_list!(),
@ -244,6 +249,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
tuple_list!(), tuple_list!(),
@ -289,6 +296,8 @@ where
HT: ExecutorHooksTuple<S>, HT: ExecutorHooksTuple<S>,
OT: ObserversTuple<S>, OT: ObserversTuple<S>,
S: State + HasExecutions + HasSolutions + HasCorpus, S: State + HasExecutions + HasSolutions + HasCorpus,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn generic<EM, OF, Z>( pub fn generic<EM, OF, Z>(
@ -336,6 +345,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, EM, OF, Z>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
@ -373,6 +384,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: State, S: State,
Z: HasObjective<Objective = OF, State = S>, Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, EM, OF, Z>(
user_hooks, observers, fuzzer, state, event_mgr, timeout, user_hooks, observers, fuzzer, state, event_mgr, timeout,

View File

@ -82,7 +82,8 @@ impl<'a, S> Named for NautilusFeedback<'a, S> {
impl<'a, S> Feedback<S> for NautilusFeedback<'a, S> impl<'a, S> Feedback<S> for NautilusFeedback<'a, S>
where where
S: HasMetadata + HasCorpus<Input = NautilusInput> + State<Input = NautilusInput>, S: HasMetadata + HasCorpus + State<Input = NautilusInput>,
S::Corpus: Corpus<Input = NautilusInput>,
{ {
#[allow(clippy::wrong_self_convention)] #[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>( fn is_interesting<EM, OT>(

View File

@ -372,13 +372,9 @@ where
CS: Scheduler<S::Input, S>, CS: Scheduler<S::Input, S>,
F: Feedback<S>, F: Feedback<S>,
OF: Feedback<S>, OF: Feedback<S>,
S: HasCorpus S: HasCorpus + HasSolutions + HasExecutions + HasCorpus + HasCurrentCorpusId + State,
+ HasSolutions S::Corpus: Corpus<Input = S::Input>, //delete me
+ HasExecutions S::Solutions: Corpus<Input = S::Input>, //delete me
+ HasCorpus
+ HasCurrentTestcase<S::Input>
+ HasCurrentCorpusId
+ State,
{ {
fn check_results<EM, OT>( fn check_results<EM, OT>(
&mut self, &mut self,
@ -535,7 +531,7 @@ where
&mut self, &mut self,
state: &mut Self::State, state: &mut Self::State,
manager: &mut EM, manager: &mut EM,
input: &<Self::State as UsesInput>::Input, input: &S::Input,
exec_res: &ExecuteInputResult, exec_res: &ExecuteInputResult,
observers: &OT, observers: &OT,
) -> Result<Option<CorpusId>, Error> ) -> Result<Option<CorpusId>, Error>
@ -596,6 +592,8 @@ where
F: Feedback<S>, F: Feedback<S>,
OF: Feedback<S>, OF: Feedback<S>,
S: HasCorpus + HasSolutions + HasExecutions + State, S: HasCorpus + HasSolutions + HasExecutions + State,
S::Corpus: Corpus<Input = S::Input>, //delete me
S::Solutions: Corpus<Input = S::Input>, //delete me
{ {
/// Process one input, adding to the respective corpora if needed and firing the right events /// Process one input, adding to the respective corpora if needed and firing the right events
#[inline] #[inline]
@ -629,6 +627,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
OT: ObserversTuple<S> + Serialize + DeserializeOwned, OT: ObserversTuple<S> + Serialize + DeserializeOwned,
S: HasCorpus + HasSolutions + HasExecutions + HasLastFoundTime + State, S: HasCorpus + HasSolutions + HasExecutions + HasLastFoundTime + State,
S::Corpus: Corpus<Input = S::Input>, //delete me
S::Solutions: Corpus<Input = S::Input>, //delete me
{ {
/// Process one input, adding to the respective corpora if needed and firing the right events /// Process one input, adding to the respective corpora if needed and firing the right events
#[inline] #[inline]
@ -765,8 +765,8 @@ where
S: HasExecutions S: HasExecutions
+ HasMetadata + HasMetadata
+ HasCorpus + HasCorpus
+ HasTestcase
+ HasLastReportTime + HasLastReportTime
+ HasTestcase
+ HasCurrentCorpusId + HasCurrentCorpusId
+ HasCurrentStageId + HasCurrentStageId
+ State, + State,

View File

@ -34,10 +34,7 @@ pub struct Automaton {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Generates random inputs from a grammar automaton /// Generates random inputs from a grammar automaton
pub struct GramatronGenerator<'a, S> pub struct GramatronGenerator<'a, S> {
where
S: HasRand,
{
automaton: &'a Automaton, automaton: &'a Automaton,
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }

View File

@ -5,11 +5,7 @@ use core::marker::PhantomData;
use libafl_bolts::rands::Rand; use libafl_bolts::rands::Rand;
use crate::{ use crate::{inputs::bytes::BytesInput, state::HasRand, Error};
inputs::{bytes::BytesInput, Input},
state::HasRand,
Error,
};
pub mod gramatron; pub mod gramatron;
pub use gramatron::*; pub use gramatron::*;
@ -20,10 +16,7 @@ pub mod nautilus;
pub use nautilus::*; pub use nautilus::*;
/// Generators can generate ranges of bytes. /// Generators can generate ranges of bytes.
pub trait Generator<I, S> pub trait Generator<I, S> {
where
I: Input,
{
/// Generate a new input /// Generate a new input
fn generate(&mut self, state: &mut S) -> Result<I, Error>; fn generate(&mut self, state: &mut S) -> Result<I, Error>;
} }
@ -35,7 +28,6 @@ where
impl<T, I, S> Generator<I, S> for T impl<T, I, S> Generator<I, S> for T
where where
T: Iterator<Item = I>, T: Iterator<Item = I>,
I: Input,
{ {
fn generate(&mut self, _state: &mut S) -> Result<I, Error> { fn generate(&mut self, _state: &mut S) -> Result<I, Error> {
match self.next() { match self.next() {
@ -49,21 +41,13 @@ where
/// An [`Iterator`] built from a [`Generator`]. /// An [`Iterator`] built from a [`Generator`].
#[derive(Debug)] #[derive(Debug)]
pub struct GeneratorIter<'a, I, S, G> pub struct GeneratorIter<'a, I, S, G> {
where
I: Input,
G: Generator<I, S>,
{
gen: G, gen: G,
state: &'a mut S, state: &'a mut S,
phantom: PhantomData<I>, phantom: PhantomData<I>,
} }
impl<'a, I, S, G> GeneratorIter<'a, I, S, G> impl<'a, I, S, G> GeneratorIter<'a, I, S, G> {
where
I: Input,
G: Generator<I, S>,
{
/// Create a new [`GeneratorIter`] /// Create a new [`GeneratorIter`]
pub fn new(gen: G, state: &'a mut S) -> Self { pub fn new(gen: G, state: &'a mut S) -> Self {
Self { Self {
@ -76,7 +60,6 @@ where
impl<'a, I, S, G> Iterator for GeneratorIter<'a, I, S, G> impl<'a, I, S, G> Iterator for GeneratorIter<'a, I, S, G>
where where
I: Input,
G: Generator<I, S>, G: Generator<I, S>,
{ {
type Item = I; type Item = I;
@ -88,10 +71,7 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Generates random bytes /// Generates random bytes
pub struct RandBytesGenerator<S> pub struct RandBytesGenerator<S> {
where
S: HasRand,
{
max_size: usize, max_size: usize,
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }
@ -112,10 +92,7 @@ where
} }
} }
impl<S> RandBytesGenerator<S> impl<S> RandBytesGenerator<S> {
where
S: HasRand,
{
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes. /// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
#[must_use] #[must_use]
pub fn new(max_size: usize) -> Self { pub fn new(max_size: usize) -> Self {
@ -128,10 +105,7 @@ where
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
/// Generates random printable characters /// Generates random printable characters
pub struct RandPrintablesGenerator<S> pub struct RandPrintablesGenerator<S> {
where
S: HasRand,
{
max_size: usize, max_size: usize,
phantom: PhantomData<S>, phantom: PhantomData<S>,
} }
@ -153,10 +127,7 @@ where
} }
} }
impl<S> RandPrintablesGenerator<S> impl<S> RandPrintablesGenerator<S> {
where
S: HasRand,
{
/// Creates a new [`RandPrintablesGenerator`], generating up to `max_size` random printable characters. /// Creates a new [`RandPrintablesGenerator`], generating up to `max_size` random printable characters.
#[must_use] #[must_use]
pub fn new(max_size: usize) -> Self { pub fn new(max_size: usize) -> Self {

View File

@ -135,7 +135,10 @@ mod tests {
#[cfg(miri)] #[cfg(miri)]
use libafl_bolts::serdeany::RegistryBuilder; use libafl_bolts::serdeany::RegistryBuilder;
use libafl_bolts::{rands::StdRand, tuples::tuple_list}; use libafl_bolts::{
rands::{RomuDuoJrRand, StdRand},
tuples::tuple_list,
};
#[cfg(miri)] #[cfg(miri)]
use crate::stages::ExecutionCountRestartHelperMetadata; use crate::stages::ExecutionCountRestartHelperMetadata;
@ -221,7 +224,15 @@ mod tests {
InMemoryCorpus<BytesInput>, InMemoryCorpus<BytesInput>,
StdRand, StdRand,
InMemoryCorpus<BytesInput>, InMemoryCorpus<BytesInput>,
> = postcard::from_bytes(state_serialized.as_slice()).unwrap(); > = postcard::from_bytes::<
StdState<
BytesInput,
InMemoryCorpus<BytesInput>,
RomuDuoJrRand,
InMemoryCorpus<BytesInput>,
>,
>(state_serialized.as_slice())
.unwrap();
assert_eq!(state.corpus().count(), state_deserialized.corpus().count()); assert_eq!(state.corpus().count(), state_deserialized.corpus().count());
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap(); let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();

View File

@ -10,7 +10,7 @@ use libafl_bolts::{
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
inputs::{EncodedInput, UsesInput}, inputs::EncodedInput,
mutators::{ mutators::{
mutations::{buffer_copy, buffer_self_copy, ARITH_MAX}, mutations::{buffer_copy, buffer_self_copy, ARITH_MAX},
MutationResult, Mutator, Named, MutationResult, Mutator, Named,
@ -285,9 +285,10 @@ impl EncodedCopyMutator {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct EncodedCrossoverInsertMutator; pub struct EncodedCrossoverInsertMutator;
impl<S> Mutator<S::Input, S> for EncodedCrossoverInsertMutator impl<S> Mutator<EncodedInput, S> for EncodedCrossoverInsertMutator
where where
S: UsesInput<Input = EncodedInput> + HasRand + HasCorpus + HasMaxSize, S: HasRand + HasCorpus + HasMaxSize,
S::Corpus: Corpus<Input = EncodedInput>,
{ {
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
let size = input.codes().len(); let size = input.codes().len();
@ -355,9 +356,10 @@ impl EncodedCrossoverInsertMutator {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct EncodedCrossoverReplaceMutator; pub struct EncodedCrossoverReplaceMutator;
impl<S> Mutator<S::Input, S> for EncodedCrossoverReplaceMutator impl<S> Mutator<EncodedInput, S> for EncodedCrossoverReplaceMutator
where where
S: UsesInput<Input = EncodedInput> + HasRand + HasCorpus, S: HasRand + HasCorpus,
S::Corpus: Corpus<Input = EncodedInput>,
{ {
fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut EncodedInput) -> Result<MutationResult, Error> {
let size = input.codes().len(); let size = input.codes().len();

View File

@ -12,7 +12,7 @@ use libafl_bolts::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, HasTestcase}, corpus::Corpus,
generators::GramatronGenerator, generators::GramatronGenerator,
inputs::{GramatronInput, Terminal}, inputs::{GramatronInput, Terminal},
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
@ -105,9 +105,10 @@ impl GramatronIdxMapMetadata {
#[derive(Default, Debug)] #[derive(Default, Debug)]
pub struct GramatronSpliceMutator; pub struct GramatronSpliceMutator;
impl<S> Mutator<S::Input, S> for GramatronSpliceMutator impl<S> Mutator<GramatronInput, S> for GramatronSpliceMutator
where where
S: HasRand + HasCorpus<Input = GramatronInput> + HasMetadata + HasTestcase, S: HasRand + HasCorpus + HasMetadata,
S::Corpus: Corpus<Input = GramatronInput>,
{ {
fn mutate( fn mutate(
&mut self, &mut self,

View File

@ -49,8 +49,7 @@ pub type HavocMutationsNoCrossoverType = tuple_list_type!(
); );
/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations
pub type HavocCrossoverType<I> = pub type HavocCrossoverType = tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator);
tuple_list_type!(CrossoverInsertMutator<I>, CrossoverReplaceMutator<I>);
/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types /// Tuple type of the mutations that compose the Havoc mutator's crossover mutations for mapped input types
pub type MappedHavocCrossoverType<F, O> = tuple_list_type!( pub type MappedHavocCrossoverType<F, O> = tuple_list_type!(
@ -59,7 +58,7 @@ pub type MappedHavocCrossoverType<F, O> = tuple_list_type!(
); );
/// Tuple type of the mutations that compose the Havoc mutator /// Tuple type of the mutations that compose the Havoc mutator
pub type HavocMutationsType<I> = tuple_list_type!( pub type HavocMutationsType = tuple_list_type!(
BitFlipMutator, BitFlipMutator,
ByteFlipMutator, ByteFlipMutator,
ByteIncMutator, ByteIncMutator,
@ -85,8 +84,8 @@ pub type HavocMutationsType<I> = tuple_list_type!(
BytesCopyMutator, BytesCopyMutator,
BytesInsertCopyMutator, BytesInsertCopyMutator,
BytesSwapMutator, BytesSwapMutator,
CrossoverInsertMutator<I>, CrossoverInsertMutator,
CrossoverReplaceMutator<I>, CrossoverReplaceMutator,
); );
/// Tuple type of the mutations that compose the Havoc mutator for mapped input types /// Tuple type of the mutations that compose the Havoc mutator for mapped input types
@ -193,7 +192,7 @@ pub fn havoc_mutations_no_crossover() -> HavocMutationsNoCrossoverType {
/// Get the mutations that compose the Havoc mutator's crossover strategy /// Get the mutations that compose the Havoc mutator's crossover strategy
#[must_use] #[must_use]
pub fn havoc_crossover<I>() -> HavocCrossoverType<I> { pub fn havoc_crossover() -> HavocCrossoverType {
tuple_list!( tuple_list!(
CrossoverInsertMutator::new(), CrossoverInsertMutator::new(),
CrossoverReplaceMutator::new(), CrossoverReplaceMutator::new(),
@ -228,7 +227,7 @@ where
/// Get the mutations that compose the Havoc mutator /// Get the mutations that compose the Havoc mutator
#[must_use] #[must_use]
pub fn havoc_mutations<I>() -> HavocMutationsType<I> { pub fn havoc_mutations() -> HavocMutationsType {
havoc_mutations_no_crossover().merge(havoc_crossover()) havoc_mutations_no_crossover().merge(havoc_crossover())
} }

View File

@ -161,12 +161,6 @@ pub trait MutatorsTuple<I, S>: HasLen {
corpus_id: Option<CorpusId>, corpus_id: Option<CorpusId>,
) -> Result<(), Error>; ) -> Result<(), Error>;
/// Gets all names of the wrapped [`Mutator`]`s`, reversed.
fn names_reversed(&self) -> Vec<&str>;
/// Gets all names of the wrapped [`Mutator`]`s`.
fn names(&self) -> Vec<&str>;
} }
impl<I, S> MutatorsTuple<I, S> for () { impl<I, S> MutatorsTuple<I, S> for () {
@ -203,16 +197,6 @@ impl<I, S> MutatorsTuple<I, S> for () {
) -> Result<(), Error> { ) -> Result<(), Error> {
Ok(()) Ok(())
} }
#[inline]
fn names_reversed(&self) -> Vec<&str> {
Vec::new()
}
#[inline]
fn names(&self) -> Vec<&str> {
Vec::new()
}
} }
impl<Head, Tail, I, S> MutatorsTuple<I, S> for (Head, Tail) impl<Head, Tail, I, S> MutatorsTuple<I, S> for (Head, Tail)
@ -263,18 +247,6 @@ where
self.1.get_and_post_exec(index - 1, state, new_corpus_id) self.1.get_and_post_exec(index - 1, state, new_corpus_id)
} }
} }
fn names_reversed(&self) -> Vec<&str> {
let mut ret = self.1.names_reversed();
ret.push(self.0.name());
ret
}
fn names(&self) -> Vec<&str> {
let mut ret = self.names_reversed();
ret.reverse();
ret
}
} }
impl<Head, Tail, I, S> IntoVec<Box<dyn Mutator<I, S>>> for (Head, Tail) impl<Head, Tail, I, S> IntoVec<Box<dyn Mutator<I, S>>> for (Head, Tail)
@ -329,14 +301,6 @@ where
) -> Result<(), Error> { ) -> Result<(), Error> {
self.0.get_and_post_exec(index, state, new_corpus_id) self.0.get_and_post_exec(index, state, new_corpus_id)
} }
fn names(&self) -> Vec<&str> {
self.0.names()
}
fn names_reversed(&self) -> Vec<&str> {
self.0.names_reversed()
}
} }
impl<Tail, I, S> IntoVec<Box<dyn Mutator<I, S>>> for (Tail,) impl<Tail, I, S> IntoVec<Box<dyn Mutator<I, S>>> for (Tail,)
@ -394,14 +358,6 @@ impl<I, S> MutatorsTuple<I, S> for Vec<Box<dyn Mutator<I, S>>> {
.ok_or_else(|| Error::key_not_found("Mutator with id {index:?} not found."))?; .ok_or_else(|| Error::key_not_found("Mutator with id {index:?} not found."))?;
mutator.post_exec(state, new_corpus_id) mutator.post_exec(state, new_corpus_id)
} }
fn names_reversed(&self) -> Vec<&str> {
self.iter().rev().map(|x| x.name().as_ref()).collect()
}
fn names(&self) -> Vec<&str> {
self.iter().map(|x| x.name().as_ref()).collect()
}
} }
impl<I, S> IntoVec<Box<dyn Mutator<I, S>>> for Vec<Box<dyn Mutator<I, S>>> { impl<I, S> IntoVec<Box<dyn Mutator<I, S>>> for Vec<Box<dyn Mutator<I, S>>> {

View File

@ -3,13 +3,11 @@
//! It uses a modified Particle Swarm Optimization algorithm to determine an optimal distribution of mutators. //! It uses a modified Particle Swarm Optimization algorithm to determine an optimal distribution of mutators.
//! See <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu> //! See <https://github.com/puppet-meteor/MOpt-AFL> and <https://www.usenix.org/conference/usenixsecurity19/presentation/lyu>
use alloc::{borrow::Cow, string::ToString, vec::Vec}; use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{ use core::fmt::{self, Debug};
fmt::{self, Debug},
marker::PhantomData,
};
use libafl_bolts::{ use libafl_bolts::{
rands::{Rand, StdRand}, rands::{Rand, StdRand},
tuples::NamedTuple,
Named, Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -363,35 +361,16 @@ pub enum MOptMode {
/// This is the main struct of `MOpt`, an `AFL` mutator. /// This is the main struct of `MOpt`, an `AFL` mutator.
/// See the original `MOpt` implementation in <https://github.com/puppet-meteor/MOpt-AFL> /// See the original `MOpt` implementation in <https://github.com/puppet-meteor/MOpt-AFL>
pub struct StdMOptMutator<I, MT, S> #[derive(Debug)]
where pub struct StdMOptMutator<MT> {
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
name: Cow<'static, str>, name: Cow<'static, str>,
mode: MOptMode, mode: MOptMode,
finds_before: usize, finds_before: usize,
mutations: MT, mutations: MT,
max_stack_pow: usize, max_stack_pow: usize,
phantom: PhantomData<(I, S)>,
} }
impl<I, MT, S> Debug for StdMOptMutator<I, MT, S> impl<I, MT, S> Mutator<I, S> for StdMOptMutator<MT>
where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"StdMOptMutator with {} mutations for Input type {}",
self.mutations.len(),
core::any::type_name::<I>()
)
}
}
impl<I, MT, S> Mutator<I, S> for StdMOptMutator<I, MT, S>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions, S: HasRand + HasMetadata + HasCorpus + HasSolutions,
@ -516,21 +495,21 @@ where
} }
} }
impl<I, MT, S> StdMOptMutator<I, MT, S> impl<MT> StdMOptMutator<MT> {
where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
/// Create a new [`StdMOptMutator`]. /// Create a new [`StdMOptMutator`].
pub fn new( pub fn new<I, S>(
state: &mut S, state: &mut S,
mutations: MT, mutations: MT,
max_stack_pow: usize, max_stack_pow: usize,
swarm_num: usize, swarm_num: usize,
) -> Result<Self, Error> { ) -> Result<Self, Error>
where
S: HasMetadata + HasRand,
MT: NamedTuple,
{
if !state.has_metadata::<MOpt>() { if !state.has_metadata::<MOpt>() {
let rand_seed = state.rand_mut().next(); let rand_seed = state.rand_mut().next();
state.add_metadata::<MOpt>(MOpt::new(mutations.len(), swarm_num, rand_seed)?); state.add_metadata::<MOpt>(MOpt::new(MT::LEN, swarm_num, rand_seed)?);
} }
Ok(Self { Ok(Self {
name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))), name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))),
@ -538,10 +517,13 @@ where
finds_before: 0, finds_before: 0,
mutations, mutations,
max_stack_pow, max_stack_pow,
phantom: PhantomData,
}) })
} }
fn core_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn core_mutate<I, S>(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
S: HasMetadata + HasRand + HasSolutions + HasCorpus,
MT: MutatorsTuple<I, S>,
{
let mut r = MutationResult::Skipped; let mut r = MutationResult::Skipped;
let mopt = state.metadata_map_mut().get_mut::<MOpt>().unwrap(); let mopt = state.metadata_map_mut().get_mut::<MOpt>().unwrap();
for i in 0..mopt.operator_num { for i in 0..mopt.operator_num {
@ -564,7 +546,11 @@ where
Ok(r) Ok(r)
} }
fn pilot_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn pilot_mutate<I, S>(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error>
where
S: HasMetadata + HasRand + HasSolutions + HasCorpus,
MT: MutatorsTuple<I, S>,
{
let mut r = MutationResult::Skipped; let mut r = MutationResult::Skipped;
let swarm_now; let swarm_now;
{ {
@ -595,11 +581,9 @@ where
} }
} }
impl<I, MT, S> ComposedByMutations<I, MT, S> for StdMOptMutator<I, MT, S> impl<MT> ComposedByMutations for StdMOptMutator<MT> {
where type Mutations = MT;
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
/// Get the mutations /// Get the mutations
#[inline] #[inline]
fn mutations(&self) -> &MT { fn mutations(&self) -> &MT {
@ -613,17 +597,13 @@ where
} }
} }
impl<I, MT, S> Named for StdMOptMutator<I, MT, S> impl<MT> Named for StdMOptMutator<MT> {
where
MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
{
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
impl<I, MT, S> ScheduledMutator<I, MT, S> for StdMOptMutator<I, MT, S> impl<I, MT, S> ScheduledMutator<I, S> for StdMOptMutator<MT>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata + HasCorpus + HasSolutions, S: HasRand + HasMetadata + HasCorpus + HasSolutions,

View File

@ -114,10 +114,11 @@ impl_default_multipart!(
I2SRandReplace, I2SRandReplace,
); );
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator<I> impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator
where where
S: HasCorpus<Input = MultipartInput<I>> + HasMaxSize + HasRand, S: HasCorpus + HasMaxSize + HasRand,
I: Input + HasMutatorBytes, I: Input + HasMutatorBytes,
S::Corpus: Corpus<Input = MultipartInput<I>>,
{ {
fn mutate( fn mutate(
&mut self, &mut self,
@ -224,10 +225,11 @@ where
} }
} }
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverReplaceMutator<I> impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverReplaceMutator
where where
S: HasCorpus<Input = MultipartInput<I>> + HasMaxSize + HasRand, S: HasCorpus + HasMaxSize + HasRand,
I: Input + HasMutatorBytes, I: Input + HasMutatorBytes,
S::Corpus: Corpus<Input = MultipartInput<I>>,
{ {
fn mutate( fn mutate(
&mut self, &mut self,

View File

@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Named};
use crate::{ use crate::{
corpus::Corpus, corpus::Corpus,
inputs::{HasMutatorBytes, UsesInput}, inputs::HasMutatorBytes,
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
random_corpus_id_with_disabled, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand}, state::{HasCorpus, HasMaxSize, HasRand},
@ -1025,18 +1025,19 @@ impl BytesSwapMutator {
/// Crossover insert mutation for inputs with a bytes vector /// Crossover insert mutation for inputs with a bytes vector
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct CrossoverInsertMutator<I> { pub struct CrossoverInsertMutator;
phantom: PhantomData<I>,
}
impl<I: HasMutatorBytes> CrossoverInsertMutator<I> { impl CrossoverInsertMutator {
pub(crate) fn crossover_insert( pub(crate) fn crossover_insert<I>(
input: &mut I, input: &mut I,
size: usize, size: usize,
target: usize, target: usize,
range: Range<usize>, range: Range<usize>,
other: &[u8], other: &[u8],
) -> MutationResult { ) -> MutationResult
where
I: HasMutatorBytes,
{
input.resize(size + range.len(), 0); input.resize(size + range.len(), 0);
unsafe { unsafe {
buffer_self_copy( buffer_self_copy(
@ -1054,10 +1055,10 @@ impl<I: HasMutatorBytes> CrossoverInsertMutator<I> {
} }
} }
impl<I, S> Mutator<I, S> for CrossoverInsertMutator<I> impl<I, S> Mutator<I, S> for CrossoverInsertMutator
where where
S: HasCorpus + HasRand + HasMaxSize, S: HasCorpus + HasRand + HasMaxSize,
S::Input: HasMutatorBytes, <S::Corpus as Corpus>::Input: HasMutatorBytes,
I: HasMutatorBytes, I: HasMutatorBytes,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
@ -1101,36 +1102,35 @@ where
} }
} }
impl<I> Named for CrossoverInsertMutator<I> { impl Named for CrossoverInsertMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverInsertMutator"); static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverInsertMutator");
&NAME &NAME
} }
} }
impl<I> CrossoverInsertMutator<I> { impl CrossoverInsertMutator {
/// Creates a new [`CrossoverInsertMutator`]. /// Creates a new [`CrossoverInsertMutator`].
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {}
phantom: PhantomData,
}
} }
} }
/// Crossover replace mutation for inputs with a bytes vector /// Crossover replace mutation for inputs with a bytes vector
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct CrossoverReplaceMutator<I> { pub struct CrossoverReplaceMutator;
phantom: PhantomData<I>,
}
impl<I: HasMutatorBytes> CrossoverReplaceMutator<I> { impl CrossoverReplaceMutator {
pub(crate) fn crossover_replace( pub(crate) fn crossover_replace<I>(
input: &mut I, input: &mut I,
target: usize, target: usize,
range: Range<usize>, range: Range<usize>,
other: &[u8], other: &[u8],
) -> MutationResult { ) -> MutationResult
where
I: HasMutatorBytes,
{
unsafe { unsafe {
buffer_copy(input.bytes_mut(), other, range.start, target, range.len()); buffer_copy(input.bytes_mut(), other, range.start, target, range.len());
} }
@ -1138,10 +1138,10 @@ impl<I: HasMutatorBytes> CrossoverReplaceMutator<I> {
} }
} }
impl<I, S> Mutator<I, S> for CrossoverReplaceMutator<I> impl<I, S> Mutator<I, S> for CrossoverReplaceMutator
where where
S: HasCorpus + HasRand, S: HasCorpus + HasRand,
S::Input: HasMutatorBytes, <S::Corpus as Corpus>::Input: HasMutatorBytes,
I: HasMutatorBytes, I: HasMutatorBytes,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
@ -1178,20 +1178,18 @@ where
} }
} }
impl<I> Named for CrossoverReplaceMutator<I> { impl Named for CrossoverReplaceMutator {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverReplaceMutator"); static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverReplaceMutator");
&NAME &NAME
} }
} }
impl<I> CrossoverReplaceMutator<I> { impl CrossoverReplaceMutator {
/// Creates a new [`CrossoverReplaceMutator`]. /// Creates a new [`CrossoverReplaceMutator`].
#[must_use] #[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {}
phantom: PhantomData,
}
} }
} }
@ -1244,11 +1242,11 @@ impl<F, O> MappedCrossoverInsertMutator<F, O> {
impl<S, F, I, O> Mutator<I, S> for MappedCrossoverInsertMutator<F, O> impl<S, F, I, O> Mutator<I, S> for MappedCrossoverInsertMutator<F, O>
where where
S: HasCorpus + HasMaxSize + HasRand + UsesInput, S: HasCorpus + HasMaxSize + HasRand,
I: HasMutatorBytes, I: HasMutatorBytes,
for<'a> O: IntoOptionBytes, for<'a> O: IntoOptionBytes,
for<'a> O::Type<'a>: IntoOptionBytes, for<'a> O::Type<'a>: IntoOptionBytes,
for<'a> F: Fn(&'a S::Input) -> <O as IntoOptionBytes>::Type<'a>, for<'a> F: Fn(&'a <S::Corpus as Corpus>::Input) -> <O as IntoOptionBytes>::Type<'a>,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len(); let size = input.bytes().len();
@ -1324,11 +1322,11 @@ impl<F, O> MappedCrossoverReplaceMutator<F, O> {
impl<S, F, I, O> Mutator<I, S> for MappedCrossoverReplaceMutator<F, O> impl<S, F, I, O> Mutator<I, S> for MappedCrossoverReplaceMutator<F, O>
where where
S: HasCorpus + HasMaxSize + HasRand + UsesInput, S: HasCorpus + HasMaxSize + HasRand,
I: HasMutatorBytes, I: HasMutatorBytes,
O: IntoOptionBytes, O: IntoOptionBytes,
for<'a> O::Type<'a>: IntoOptionBytes, for<'a> O::Type<'a>: IntoOptionBytes,
for<'a> F: Fn(&'a S::Input) -> <O as IntoOptionBytes>::Type<'a>, for<'a> F: Fn(&'a <S::Corpus as Corpus>::Input) -> <O as IntoOptionBytes>::Type<'a>,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let size = input.bytes().len(); let size = input.bytes().len();
@ -1404,13 +1402,14 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct SpliceMutator; pub struct SpliceMutator;
impl<S> Mutator<S::Input, S> for SpliceMutator impl<I, S> Mutator<I, S> for SpliceMutator
where where
S: HasCorpus + HasRand, S: HasCorpus + HasRand,
S::Input: HasMutatorBytes, <S::Corpus as Corpus>::Input: HasMutatorBytes,
I: HasMutatorBytes,
{ {
#[allow(clippy::cast_sign_loss)] #[allow(clippy::cast_sign_loss)]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut()); let id = random_corpus_id_with_disabled!(state.corpus(), state.rand_mut());
// We don't want to use the testcase we're already using for splicing // We don't want to use the testcase we're already using for splicing
if let Some(cur) = state.corpus().current() { if let Some(cur) = state.corpus().current() {

View File

@ -162,7 +162,7 @@ impl Debug for NautilusSpliceMutator<'_> {
impl<S> Mutator<NautilusInput, S> for NautilusSpliceMutator<'_> impl<S> Mutator<NautilusInput, S> for NautilusSpliceMutator<'_>
where where
S: HasCorpus<Input = NautilusInput> + HasMetadata + HasRand, S: HasCorpus + HasMetadata + HasRand,
{ {
fn mutate( fn mutate(
&mut self, &mut self,

View File

@ -2,14 +2,13 @@
use alloc::{borrow::Cow, vec::Vec}; use alloc::{borrow::Cow, vec::Vec};
use core::{ use core::{
fmt::{self, Debug}, fmt::Debug,
marker::PhantomData,
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
}; };
use libafl_bolts::{ use libafl_bolts::{
rands::Rand, rands::Rand,
tuples::{tuple_list, tuple_list_type, NamedTuple}, tuples::{tuple_list, tuple_list_type, HasConstLen, NamedTuple},
Named, Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -60,21 +59,20 @@ impl LogMutationMetadata {
} }
/// A [`Mutator`] that composes multiple mutations into one. /// A [`Mutator`] that composes multiple mutations into one.
pub trait ComposedByMutations<I, MT, S> pub trait ComposedByMutations {
where /// The mutations of this
MT: MutatorsTuple<I, S>, type Mutations;
{
/// Get the mutations /// Get the mutations
fn mutations(&self) -> &MT; fn mutations(&self) -> &Self::Mutations;
/// Get the mutations (mutable) /// Get the mutations (mutable)
fn mutations_mut(&mut self) -> &mut MT; fn mutations_mut(&mut self) -> &mut Self::Mutations;
} }
/// A [`Mutator`] scheduling multiple [`Mutator`]s for an input. /// A [`Mutator`] scheduling multiple [`Mutator`]s for an input.
pub trait ScheduledMutator<I, MT, S>: ComposedByMutations<I, MT, S> + Mutator<I, S> pub trait ScheduledMutator<I, S>: ComposedByMutations + Mutator<I, S>
where where
MT: MutatorsTuple<I, S>, Self::Mutations: MutatorsTuple<I, S>,
{ {
/// Compute the number of iterations used to apply stacked mutations /// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, input: &I) -> u64; fn iterations(&self, state: &mut S, input: &I) -> u64;
@ -99,43 +97,20 @@ where
} }
/// A [`Mutator`] that schedules one of the embedded mutations on each call. /// A [`Mutator`] that schedules one of the embedded mutations on each call.
pub struct StdScheduledMutator<I, MT, S> #[derive(Debug)]
where pub struct StdScheduledMutator<MT> {
MT: MutatorsTuple<I, S>,
S: HasRand,
{
name: Cow<'static, str>, name: Cow<'static, str>,
mutations: MT, mutations: MT,
max_stack_pow: usize, max_stack_pow: usize,
phantom: PhantomData<(I, S)>,
} }
impl<I, MT, S> Debug for StdScheduledMutator<I, MT, S> impl<MT> Named for StdScheduledMutator<MT> {
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"StdScheduledMutator with {} mutations for Input type {}",
self.mutations.len(),
core::any::type_name::<I>()
)
}
}
impl<I, MT, S> Named for StdScheduledMutator<I, MT, S>
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
impl<I, MT, S> Mutator<I, S> for StdScheduledMutator<I, MT, S> impl<I, MT, S> Mutator<I, S> for StdScheduledMutator<MT>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand, S: HasRand,
@ -146,11 +121,8 @@ where
} }
} }
impl<I, MT, S> ComposedByMutations<I, MT, S> for StdScheduledMutator<I, MT, S> impl<MT> ComposedByMutations for StdScheduledMutator<MT> {
where type Mutations = MT;
MT: MutatorsTuple<I, S>,
S: HasRand,
{
/// Get the mutations /// Get the mutations
#[inline] #[inline]
fn mutations(&self) -> &MT { fn mutations(&self) -> &MT {
@ -164,7 +136,7 @@ where
} }
} }
impl<I, MT, S> ScheduledMutator<I, MT, S> for StdScheduledMutator<I, MT, S> impl<I, MT, S> ScheduledMutator<I, S> for StdScheduledMutator<MT>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand, S: HasRand,
@ -181,10 +153,9 @@ where
} }
} }
impl<I, MT, S> StdScheduledMutator<I, MT, S> impl<MT> StdScheduledMutator<MT>
where where
MT: MutatorsTuple<I, S>, MT: NamedTuple,
S: HasRand,
{ {
/// Create a new [`StdScheduledMutator`] instance specifying mutations /// Create a new [`StdScheduledMutator`] instance specifying mutations
pub fn new(mutations: MT) -> Self { pub fn new(mutations: MT) -> Self {
@ -195,7 +166,6 @@ where
)), )),
mutations, mutations,
max_stack_pow: 7, max_stack_pow: 7,
phantom: PhantomData,
} }
} }
@ -208,7 +178,6 @@ where
)), )),
mutations, mutations,
max_stack_pow, max_stack_pow,
phantom: PhantomData,
} }
} }
} }
@ -220,50 +189,24 @@ pub fn tokens_mutations() -> tuple_list_type!(TokenInsert, TokenReplace) {
} }
/// A logging [`Mutator`] that wraps around a [`StdScheduledMutator`]. /// A logging [`Mutator`] that wraps around a [`StdScheduledMutator`].
pub struct LoggerScheduledMutator<I, MT, S, SM> #[derive(Debug)]
where pub struct LoggerScheduledMutator<SM> {
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
name: Cow<'static, str>, name: Cow<'static, str>,
scheduled: SM, scheduled: SM,
mutation_log: Vec<MutationId>, mutation_log: Vec<MutationId>,
phantom: PhantomData<(I, MT, S)>,
} }
impl<I, MT, S, SM> Debug for LoggerScheduledMutator<I, MT, S, SM> impl<SM> Named for LoggerScheduledMutator<SM> {
where
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"LoggerScheduledMutator with {} mutations for Input type {}",
MT::LEN,
core::any::type_name::<I>()
)
}
}
impl<I, MT, S, SM> Named for LoggerScheduledMutator<I, MT, S, SM>
where
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
impl<I, MT, S, SM> Mutator<I, S> for LoggerScheduledMutator<I, MT, S, SM> impl<I, S, SM> Mutator<I, S> for LoggerScheduledMutator<SM>
where where
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus, S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>, SM: ScheduledMutator<I, S>,
SM::Mutations: MutatorsTuple<I, S> + NamedTuple,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
self.scheduled_mutate(state, input) self.scheduled_mutate(state, input)
@ -286,28 +229,27 @@ where
} }
} }
impl<I, MT, S, SM> ComposedByMutations<I, MT, S> for LoggerScheduledMutator<I, MT, S, SM> impl<SM> ComposedByMutations for LoggerScheduledMutator<SM>
where where
MT: MutatorsTuple<I, S> + NamedTuple, SM: ComposedByMutations,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{ {
type Mutations = SM::Mutations;
#[inline] #[inline]
fn mutations(&self) -> &MT { fn mutations(&self) -> &SM::Mutations {
self.scheduled.mutations() self.scheduled.mutations()
} }
#[inline] #[inline]
fn mutations_mut(&mut self) -> &mut MT { fn mutations_mut(&mut self) -> &mut SM::Mutations {
self.scheduled.mutations_mut() self.scheduled.mutations_mut()
} }
} }
impl<I, MT, S, SM> ScheduledMutator<I, MT, S> for LoggerScheduledMutator<I, MT, S, SM> impl<I, S, SM> ScheduledMutator<I, S> for LoggerScheduledMutator<SM>
where where
MT: MutatorsTuple<I, S> + NamedTuple,
S: HasRand + HasCorpus, S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>, SM: ScheduledMutator<I, S>,
SM::Mutations: MutatorsTuple<I, S> + NamedTuple,
{ {
/// Compute the number of iterations used to apply stacked mutations /// Compute the number of iterations used to apply stacked mutations
fn iterations(&self, state: &mut S, _: &I) -> u64 { fn iterations(&self, state: &mut S, _: &I) -> u64 {
@ -316,8 +258,11 @@ where
/// Get the next mutation to apply /// Get the next mutation to apply
fn schedule(&self, state: &mut S, _: &I) -> MutationId { fn schedule(&self, state: &mut S, _: &I) -> MutationId {
debug_assert!(MT::LEN != 0); debug_assert!(<SM::Mutations as HasConstLen>::LEN != 0);
state.rand_mut().below(MT::LEN).into() state
.rand_mut()
.below(<SM::Mutations as HasConstLen>::LEN)
.into()
} }
fn scheduled_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn scheduled_mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
@ -336,11 +281,9 @@ where
} }
} }
impl<I, MT, S, SM> LoggerScheduledMutator<I, MT, S, SM> impl<SM> LoggerScheduledMutator<SM>
where where
MT: MutatorsTuple<I, S> + NamedTuple, SM: Named,
S: HasRand + HasCorpus,
SM: ScheduledMutator<I, MT, S>,
{ {
/// Create a new [`LoggerScheduledMutator`] instance without mutations and corpus /// Create a new [`LoggerScheduledMutator`] instance without mutations and corpus
/// This mutator logs all mutators. /// This mutator logs all mutators.
@ -349,7 +292,6 @@ where
name: Cow::from(format!("LoggerScheduledMutator[{}]", scheduled.name())), name: Cow::from(format!("LoggerScheduledMutator[{}]", scheduled.name())),
scheduled, scheduled,
mutation_log: vec![], mutation_log: vec![],
phantom: PhantomData,
} }
} }
} }

View File

@ -24,7 +24,7 @@ use serde::{Deserialize, Serialize};
use crate::mutators::str_decode; use crate::mutators::str_decode;
use crate::{ use crate::{
corpus::{CorpusId, HasCurrentCorpusId}, corpus::{CorpusId, HasCurrentCorpusId},
inputs::{HasMutatorBytes, UsesInput}, inputs::HasMutatorBytes,
mutators::{ mutators::{
buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named, buffer_self_copy, mutations::buffer_copy, MultiMutator, MutationResult, Mutator, Named,
}, },
@ -367,7 +367,7 @@ pub struct TokenReplace;
impl<I, S> Mutator<I, S> for TokenReplace impl<I, S> Mutator<I, S> for TokenReplace
where where
S: UsesInput + HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorBytes, I: HasMutatorBytes,
{ {
fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut I) -> Result<MutationResult, Error> {
@ -426,7 +426,7 @@ pub struct I2SRandReplace;
impl<I, S> Mutator<I, S> for I2SRandReplace impl<I, S> Mutator<I, S> for I2SRandReplace
where where
S: UsesInput + HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorBytes, I: HasMutatorBytes,
{ {
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
@ -621,7 +621,7 @@ where
impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly
where where
S: UsesInput + HasMetadata + HasRand + HasMaxSize, S: HasMetadata + HasRand + HasMaxSize,
I: HasMutatorBytes, I: HasMutatorBytes,
{ {
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
@ -1294,7 +1294,7 @@ impl AFLppRedQueen {
impl<I, S> MultiMutator<I, S> for AFLppRedQueen impl<I, S> MultiMutator<I, S> for AFLppRedQueen
where where
S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId, S: HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId,
I: HasMutatorBytes + From<Vec<u8>>, I: HasMutatorBytes + From<Vec<u8>>,
{ {
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]

View File

@ -4,13 +4,11 @@
//! a specific mutator for a specified amount of iterations //! a specific mutator for a specified amount of iterations
use alloc::{borrow::Cow, vec::Vec}; use alloc::{borrow::Cow, vec::Vec};
use core::{ use core::fmt::Debug;
fmt::{self, Debug},
marker::PhantomData,
};
use libafl_bolts::{ use libafl_bolts::{
impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand, Named, impl_serdeany, math::calculate_cumulative_distribution_in_place, rands::Rand,
tuples::NamedTuple, Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -81,33 +79,14 @@ impl TuneableScheduledMutatorMetadata {
/// A [`Mutator`] that schedules one of the embedded mutations on each call. /// A [`Mutator`] that schedules one of the embedded mutations on each call.
/// The index of the next mutation can be set. /// The index of the next mutation can be set.
pub struct TuneableScheduledMutator<I, MT, S> #[derive(Debug)]
where pub struct TuneableScheduledMutator<MT> {
MT: MutatorsTuple<I, S>,
S: HasRand,
{
name: Cow<'static, str>, name: Cow<'static, str>,
mutations: MT, mutations: MT,
max_stack_pow: usize, max_stack_pow: usize,
phantom: PhantomData<(I, S)>,
} }
impl<I, MT, S> Debug for TuneableScheduledMutator<I, MT, S> impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<MT>
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"TuneableScheduledMutator with {} mutations for Input type {}",
self.mutations.len(),
core::any::type_name::<I>()
)
}
}
impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<I, MT, S>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata, S: HasRand + HasMetadata,
@ -118,11 +97,8 @@ where
} }
} }
impl<I, MT, S> ComposedByMutations<I, MT, S> for TuneableScheduledMutator<I, MT, S> impl<MT> ComposedByMutations for TuneableScheduledMutator<MT> {
where type Mutations = MT;
MT: MutatorsTuple<I, S>,
S: HasRand,
{
/// Get the mutations /// Get the mutations
#[inline] #[inline]
fn mutations(&self) -> &MT { fn mutations(&self) -> &MT {
@ -136,17 +112,13 @@ where
} }
} }
impl<I, MT, S> Named for TuneableScheduledMutator<I, MT, S> impl<MT> Named for TuneableScheduledMutator<MT> {
where
MT: MutatorsTuple<I, S>,
S: HasRand,
{
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
&self.name &self.name
} }
} }
impl<I, MT, S> ScheduledMutator<I, MT, S> for TuneableScheduledMutator<I, MT, S> impl<I, MT, S> ScheduledMutator<I, S> for TuneableScheduledMutator<MT>
where where
MT: MutatorsTuple<I, S>, MT: MutatorsTuple<I, S>,
S: HasRand + HasMetadata, S: HasRand + HasMetadata,
@ -228,13 +200,13 @@ where
} }
} }
impl<I, MT, S> TuneableScheduledMutator<I, MT, S> impl<MT> TuneableScheduledMutator<MT> {
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
pub fn new<S>(state: &mut S, mutations: MT) -> Self
where where
MT: MutatorsTuple<I, S>, MT: NamedTuple,
S: HasRand + HasMetadata, S: HasRand + HasMetadata,
{ {
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
pub fn new(state: &mut S, mutations: MT) -> Self {
if !state.has_metadata::<TuneableScheduledMutatorMetadata>() { if !state.has_metadata::<TuneableScheduledMutatorMetadata>() {
state.add_metadata(TuneableScheduledMutatorMetadata::default()); state.add_metadata(TuneableScheduledMutatorMetadata::default());
} }
@ -242,36 +214,22 @@ where
name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))), name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))),
mutations, mutations,
max_stack_pow: 7, max_stack_pow: 7,
phantom: PhantomData,
} }
} }
} }
impl<S> TuneableScheduledMutator<(), (), S> impl<MT> TuneableScheduledMutator<MT> {
where
S: HasRand + HasMetadata,
{
fn metadata_mut(state: &mut S) -> &mut TuneableScheduledMutatorMetadata {
state
.metadata_map_mut()
.get_mut::<TuneableScheduledMutatorMetadata>()
.unwrap()
}
fn metadata(state: &S) -> &TuneableScheduledMutatorMetadata {
state
.metadata_map()
.get::<TuneableScheduledMutatorMetadata>()
.unwrap()
}
/// Sets the next iterations count, i.e., how many times to mutate the input /// Sets the next iterations count, i.e., how many times to mutate the input
/// ///
/// Using `set_mutation_ids_and_iter` to set multiple values at the same time /// Using `set_mutation_ids_and_iter` to set multiple values at the same time
/// will be faster than setting them individually /// will be faster than setting them individually
/// as it internally only needs a single metadata lookup /// as it internally only needs a single metadata lookup
pub fn set_iters(state: &mut S, iters: u64) { pub fn set_iters<S>(&self, state: &mut S, iters: u64)
let metadata = Self::metadata_mut(state); where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.iters = Some(iters); metadata.iters = Some(iters);
metadata.iter_probabilities_pow_cumulative.clear(); metadata.iter_probabilities_pow_cumulative.clear();
} }
@ -285,16 +243,20 @@ where
/// These will be applied for each call of this `mutate` function. /// These will be applied for each call of this `mutate` function.
/// ///
/// Setting this function will unset everything previously set in `set_iters`. /// Setting this function will unset everything previously set in `set_iters`.
pub fn set_iter_probabilities_pow( pub fn set_iter_probabilities_pow<S>(
&self,
state: &mut S, state: &mut S,
mut iter_probabilities_pow: Vec<f32>, mut iter_probabilities_pow: Vec<f32>,
) -> Result<(), Error> { ) -> Result<(), Error>
where
S: HasMetadata,
{
if iter_probabilities_pow.len() >= 32 { if iter_probabilities_pow.len() >= 32 {
return Err(Error::illegal_argument( return Err(Error::illegal_argument(
"Cannot stack more than 2^32 mutations", "Cannot stack more than 2^32 mutations",
)); ));
} }
let metadata = Self::metadata_mut(state); let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.iters = None; metadata.iters = None;
// we precalculate the cumulative probability to be faster when sampling later. // we precalculate the cumulative probability to be faster when sampling later.
@ -305,13 +267,19 @@ where
} }
/// Gets the set amount of iterations /// Gets the set amount of iterations
pub fn get_iters(state: &S) -> Option<u64> { pub fn get_iters<S>(&self, state: &S) -> Option<u64>
let metadata = Self::metadata(state); where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get(state).unwrap();
metadata.iters metadata.iters
} }
/// Sets the mutation ids /// Sets the mutation ids
pub fn set_mutation_ids(state: &mut S, mutations: Vec<MutationId>) { pub fn set_mutation_ids<S>(&self, state: &mut S, mutations: Vec<MutationId>)
where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap(); let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.mutation_ids = mutations; metadata.mutation_ids = mutations;
metadata.next_id = 0.into(); metadata.next_id = 0.into();
@ -321,10 +289,14 @@ where
/// The `Vec` contains a probability per [`MutationId`]: between 0 and 1, and they have to add /// The `Vec` contains a probability per [`MutationId`]: between 0 and 1, and they have to add
/// up to 1. /// up to 1.
/// Setting the probabilities will remove the value set through `set_mutation_ids`. /// Setting the probabilities will remove the value set through `set_mutation_ids`.
pub fn set_mutation_probabilities( pub fn set_mutation_probabilities<S>(
&self,
state: &mut S, state: &mut S,
mut mutation_probabilities: Vec<f32>, mut mutation_probabilities: Vec<f32>,
) -> Result<(), Error> { ) -> Result<(), Error>
where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap(); let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.mutation_ids.clear(); metadata.mutation_ids.clear();
metadata.next_id = 0.into(); metadata.next_id = 0.into();
@ -336,7 +308,14 @@ where
} }
/// mutation ids and iterations /// mutation ids and iterations
pub fn set_mutation_ids_and_iters(state: &mut S, mutations: Vec<MutationId>, iters: u64) { pub fn set_mutation_ids_and_iters<S>(
&self,
state: &mut S,
mutations: Vec<MutationId>,
iters: u64,
) where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap(); let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.mutation_ids = mutations; metadata.mutation_ids = mutations;
metadata.next_id = 0.into(); metadata.next_id = 0.into();
@ -344,14 +323,23 @@ where
} }
/// Appends a mutation id to the end of the mutations /// Appends a mutation id to the end of the mutations
pub fn push_mutation_id(state: &mut S, mutation_id: MutationId) { pub fn push_mutation_id<S>(state: &mut S, mutation_id: MutationId)
where
S: HasMetadata,
{
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap(); let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
metadata.mutation_ids.push(mutation_id); metadata.mutation_ids.push(mutation_id);
} }
/// Resets this to a randomic mutational stage /// Resets this to a randomic mutational stage
pub fn reset(state: &mut S) { pub fn reset<S>(self, state: &mut S)
let metadata = Self::metadata_mut(state); where
S: HasMetadata,
{
let metadata = state
.metadata_map_mut()
.get_mut::<TuneableScheduledMutatorMetadata>()
.unwrap();
metadata.mutation_ids.clear(); metadata.mutation_ids.clear();
metadata.next_id = 0.into(); metadata.next_id = 0.into();
metadata.iters = None; metadata.iters = None;
@ -417,43 +405,35 @@ mod test {
let input = BytesInput::new(vec![42]); let input = BytesInput::new(vec![42]);
// Basic tests over the probability distribution. // Basic tests over the probability distribution.
assert!( assert!(tuneable
TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![0.0]).is_err() .set_mutation_probabilities(&mut state, vec![0.0])
); .is_err());
assert!( assert!(tuneable
TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![1.0; 3]).is_err() .set_mutation_probabilities(&mut state, vec![1.0; 3])
); .is_err());
assert!(TuneableScheduledMutator::set_mutation_probabilities( assert!(tuneable
&mut state, .set_mutation_probabilities(&mut state, vec![-1.0, 1.0, 1.0])
vec![-1.0, 1.0, 1.0] .is_err());
) assert!(tuneable
.set_mutation_probabilities(&mut state, vec![])
.is_err()); .is_err());
assert!(TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![]).is_err());
assert!(TuneableScheduledMutator::set_mutation_probabilities( assert!(tuneable
&mut state, .set_mutation_probabilities(&mut state, vec![0.0, 0.0, 1.0])
vec![0.0, 0.0, 1.0]
)
.is_ok()); .is_ok());
assert_eq!(tuneable.schedule(&mut state, &input), 2.into()); assert_eq!(tuneable.schedule(&mut state, &input), 2.into());
assert!(TuneableScheduledMutator::set_mutation_probabilities( assert!(tuneable
&mut state, .set_mutation_probabilities(&mut state, vec![0.0, 1.0, 0.0])
vec![0.0, 1.0, 0.0]
)
.is_ok()); .is_ok());
assert_eq!(tuneable.schedule(&mut state, &input), 1.into()); assert_eq!(tuneable.schedule(&mut state, &input), 1.into());
assert!(TuneableScheduledMutator::set_mutation_probabilities( assert!(tuneable
&mut state, .set_mutation_probabilities(&mut state, vec![1.0, 0.0, 0.0])
vec![1.0, 0.0, 0.0]
)
.is_ok()); .is_ok());
assert_eq!(tuneable.schedule(&mut state, &input), 0.into()); assert_eq!(tuneable.schedule(&mut state, &input), 0.into());
// We should not choose a mutation with p=0. // We should not choose a mutation with p=0.
assert!(TuneableScheduledMutator::set_mutation_probabilities( assert!(tuneable
&mut state, .set_mutation_probabilities(&mut state, vec![0.5, 0.0, 0.5])
vec![0.5, 0.0, 0.5]
)
.is_ok()); .is_ok());
assert!(tuneable.schedule(&mut state, &input) != 1.into()); assert!(tuneable.schedule(&mut state, &input) != 1.into());
} }

View File

@ -9,7 +9,7 @@ use core::{
use libafl_bolts::{rands::Rand, Error, HasLen, Named}; use libafl_bolts::{rands::Rand, Error, HasLen, Named};
use crate::{ use crate::{
corpus::{CorpusId, HasTestcase, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, Testcase},
inputs::{BytesInput, HasMutatorBytes}, inputs::{BytesInput, HasMutatorBytes},
mutators::{rand_range, MutationResult, Mutator, Tokens}, mutators::{rand_range, MutationResult, Mutator, Tokens},
stages::{ stages::{
@ -32,7 +32,8 @@ pub type UnicodeInput = (BytesInput, UnicodeIdentificationMetadata);
impl<S> MutatedTransform<BytesInput, S> for UnicodeInput impl<S> MutatedTransform<BytesInput, S> for UnicodeInput
where where
S: HasCorpus<Input = BytesInput> + HasTestcase, S: HasCorpus + HasTestcase,
S::Corpus: Corpus<Input = BytesInput>,
{ {
type Post = UnicodeIdentificationMetadata; type Post = UnicodeIdentificationMetadata;

View File

@ -110,11 +110,12 @@ pub struct CoverageAccountingScheduler<'a, CS, O> {
inner: IndexesLenTimeMinimizerScheduler<CS, O>, inner: IndexesLenTimeMinimizerScheduler<CS, O>,
} }
impl<'a, CS, I, O, S> Scheduler<I, S> for CoverageAccountingScheduler<'a, CS, O> impl<'a, CS, O, S> Scheduler<<S::Corpus as Corpus>::Input, S>
for CoverageAccountingScheduler<'a, CS, O>
where where
CS: Scheduler<I, S>, CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
S: HasCorpus<Input = I> + HasMetadata + HasRand, S: HasCorpus + HasMetadata + HasRand,
I: HasLen, <S::Corpus as Corpus>::Input: HasLen,
O: CanTrack, O: CanTrack,
{ {
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
@ -122,7 +123,12 @@ where
self.inner.on_add(state, id) self.inner.on_add(state, id)
} }
fn on_evaluation<OT>(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> fn on_evaluation<OT>(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
observers: &OT,
) -> Result<(), Error>
where where
OT: MatchName, OT: MatchName,
{ {

View File

@ -79,19 +79,21 @@ pub struct MinimizerScheduler<CS, F, M, S> {
phantom: PhantomData<(F, M, S)>, phantom: PhantomData<(F, M, S)>,
} }
impl<CS, F, I, M, O, S> RemovableScheduler<I, S> for MinimizerScheduler<CS, F, M, O> impl<CS, F, M, O, S> RemovableScheduler<<S::Corpus as Corpus>::Input, S>
for MinimizerScheduler<CS, F, M, O>
where where
CS: RemovableScheduler<I, S> + Scheduler<I, S>, CS: RemovableScheduler<<S::Corpus as Corpus>::Input, S>
F: TestcaseScore<I, S>, + Scheduler<<S::Corpus as Corpus>::Input, S>,
F: TestcaseScore<S>,
M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt,
S: HasCorpus<Input = I> + HasMetadata + HasRand, S: HasCorpus + HasMetadata + HasRand,
{ {
/// Replaces the [`Testcase`] at the given [`CorpusId`] /// Replaces the [`Testcase`] at the given [`CorpusId`]
fn on_replace( fn on_replace(
&mut self, &mut self,
state: &mut S, state: &mut S,
id: CorpusId, id: CorpusId,
testcase: &Testcase<I>, testcase: &Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.base.on_replace(state, id, testcase)?; self.base.on_replace(state, id, testcase)?;
self.update_score(state, id) self.update_score(state, id)
@ -102,7 +104,7 @@ where
&mut self, &mut self,
state: &mut S, state: &mut S,
id: CorpusId, id: CorpusId,
testcase: &Option<Testcase<I>>, testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.base.on_remove(state, id, testcase)?; self.base.on_remove(state, id, testcase)?;
let mut entries = let mut entries =
@ -186,12 +188,12 @@ where
} }
} }
impl<CS, F, I, M, O, S> Scheduler<I, S> for MinimizerScheduler<CS, F, M, O> impl<CS, F, M, O, S> Scheduler<<S::Corpus as Corpus>::Input, S> for MinimizerScheduler<CS, F, M, O>
where where
CS: Scheduler<I, S>, CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt, M: for<'a> AsIter<'a, Item = usize> + SerdeAny + HasRefCnt,
S: HasCorpus<Input = I> + HasMetadata + HasRand, S: HasCorpus + HasMetadata + HasRand,
{ {
/// Called when a [`Testcase`] is added to the corpus /// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
@ -200,7 +202,12 @@ where
} }
/// An input has been evaluated /// An input has been evaluated
fn on_evaluation<OT>(&mut self, state: &mut S, input: &I, observers: &OT) -> Result<(), Error> fn on_evaluation<OT>(
&mut self,
state: &mut S,
input: &<S::Corpus as Corpus>::Input,
observers: &OT,
) -> Result<(), Error>
where where
OT: MatchName, OT: MatchName,
{ {
@ -243,10 +250,10 @@ where
/// Update the [`Corpus`] score using the [`MinimizerScheduler`] /// Update the [`Corpus`] score using the [`MinimizerScheduler`]
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
#[allow(clippy::cast_possible_wrap)] #[allow(clippy::cast_possible_wrap)]
pub fn update_score<I, S>(&self, state: &mut S, id: CorpusId) -> Result<(), Error> pub fn update_score<S>(&self, state: &mut S, id: CorpusId) -> Result<(), Error>
where where
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
S: HasCorpus<Input = I> + HasMetadata, S: HasCorpus + HasMetadata,
{ {
// Create a new top rated meta if not existing // Create a new top rated meta if not existing
if state.metadata_map().get::<TopRatedsMetadata>().is_none() { if state.metadata_map().get::<TopRatedsMetadata>().is_none() {

View File

@ -215,7 +215,7 @@ pub struct RandScheduler<S> {
impl<I, S> Scheduler<I, S> for RandScheduler<S> impl<I, S> Scheduler<I, S> for RandScheduler<S>
where where
S: HasCorpus + HasRand + HasTestcase, S: HasCorpus + HasRand,
{ {
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
// Set parent id // Set parent id

View File

@ -10,7 +10,6 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase}, corpus::{Corpus, CorpusId, Testcase},
inputs::Input,
schedulers::{RemovableScheduler, Scheduler, TestcaseScore}, schedulers::{RemovableScheduler, Scheduler, TestcaseScore},
state::{HasCorpus, HasRand}, state::{HasCorpus, HasRand},
Error, HasMetadata, Error, HasMetadata,
@ -66,11 +65,10 @@ impl<F> ProbabilitySamplingScheduler<F> {
/// Calculate the score and store in `ProbabilityMetadata` /// Calculate the score and store in `ProbabilityMetadata`
#[allow(clippy::cast_precision_loss)] #[allow(clippy::cast_precision_loss)]
#[allow(clippy::unused_self)] #[allow(clippy::unused_self)]
pub fn store_probability<I, S>(&self, state: &mut S, id: CorpusId) -> Result<(), Error> pub fn store_probability<S>(&self, state: &mut S, id: CorpusId) -> Result<(), Error>
where where
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
I: Input, S: HasCorpus + HasMetadata + HasRand,
S: HasCorpus<Input = I> + HasMetadata + HasRand,
{ {
let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?; let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?;
debug_assert!( debug_assert!(
@ -87,17 +85,16 @@ impl<F> ProbabilitySamplingScheduler<F> {
} }
} }
impl<I, F, S> RemovableScheduler<I, S> for ProbabilitySamplingScheduler<F> impl<F, S> RemovableScheduler<<S::Corpus as Corpus>::Input, S> for ProbabilitySamplingScheduler<F>
where where
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
I: Input, S: HasCorpus + HasMetadata + HasRand,
S: HasCorpus<Input = I> + HasMetadata + HasRand,
{ {
fn on_remove( fn on_remove(
&mut self, &mut self,
state: &mut S, state: &mut S,
id: CorpusId, id: CorpusId,
_testcase: &Option<Testcase<I>>, _testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let meta = state let meta = state
.metadata_map_mut() .metadata_map_mut()
@ -113,7 +110,7 @@ where
&mut self, &mut self,
state: &mut S, state: &mut S,
id: CorpusId, id: CorpusId,
_prev: &Testcase<I>, _prev: &Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let meta = state let meta = state
.metadata_map_mut() .metadata_map_mut()
@ -127,11 +124,10 @@ where
} }
} }
impl<I, F, S> Scheduler<I, S> for ProbabilitySamplingScheduler<F> impl<F, S> Scheduler<<S::Corpus as Corpus>::Input, S> for ProbabilitySamplingScheduler<F>
where where
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
I: Input, S: HasCorpus + HasMetadata + HasRand,
S: HasCorpus<Input = I> + HasMetadata + HasRand,
{ {
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
let current_id = *state.corpus().current(); let current_id = *state.corpus().current();
@ -209,11 +205,14 @@ mod tests {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct UniformDistribution {} pub struct UniformDistribution {}
impl<I, S> TestcaseScore<I, S> for UniformDistribution impl<S> TestcaseScore<S> for UniformDistribution
where where
S: HasCorpus, S: HasCorpus,
{ {
fn compute(_state: &S, _: &mut Testcase<I>) -> Result<f64, Error> { fn compute(
_state: &S,
_: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
Ok(FACTOR) Ok(FACTOR)
} }
} }

View File

@ -15,9 +15,13 @@ use crate::{
}; };
/// Compute the favor factor of a [`Testcase`]. Higher is better. /// Compute the favor factor of a [`Testcase`]. Higher is better.
pub trait TestcaseScore<I, S> { pub trait TestcaseScore<S>
where
S: HasCorpus,
{
/// Computes the favor factor of a [`Testcase`]. Higher is better. /// Computes the favor factor of a [`Testcase`]. Higher is better.
fn compute(state: &S, entry: &mut Testcase<I>) -> Result<f64, Error>; fn compute(state: &S, entry: &mut Testcase<<S::Corpus as Corpus>::Input>)
-> Result<f64, Error>;
} }
/// Multiply the testcase size with the execution time. /// Multiply the testcase size with the execution time.
@ -25,13 +29,16 @@ pub trait TestcaseScore<I, S> {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LenTimeMulTestcaseScore {} pub struct LenTimeMulTestcaseScore {}
impl<I, S> TestcaseScore<I, S> for LenTimeMulTestcaseScore impl<S> TestcaseScore<S> for LenTimeMulTestcaseScore
where where
S: HasCorpus<Input = I>, S: HasCorpus,
I: HasLen, <S::Corpus as Corpus>::Input: HasLen,
{ {
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[allow(clippy::cast_precision_loss, clippy::cast_lossless)]
fn compute(state: &S, entry: &mut Testcase<I>) -> Result<f64, Error> { fn compute(
state: &S,
entry: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
// TODO maybe enforce entry.exec_time().is_some() // TODO maybe enforce entry.exec_time().is_some()
Ok(entry.exec_time().map_or(1, |d| d.as_millis()) as f64 Ok(entry.exec_time().map_or(1, |d| d.as_millis()) as f64
* entry.load_len(state.corpus())? as f64) * entry.load_len(state.corpus())? as f64)
@ -48,7 +55,7 @@ const HAVOC_MAX_MULT: f64 = 64.0;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CorpusPowerTestcaseScore {} pub struct CorpusPowerTestcaseScore {}
impl<I, S> TestcaseScore<I, S> for CorpusPowerTestcaseScore impl<S> TestcaseScore<S> for CorpusPowerTestcaseScore
where where
S: HasCorpus + HasMetadata, S: HasCorpus + HasMetadata,
{ {
@ -59,7 +66,10 @@ where
clippy::cast_sign_loss, clippy::cast_sign_loss,
clippy::cast_lossless clippy::cast_lossless
)] )]
fn compute(state: &S, entry: &mut Testcase<I>) -> Result<f64, Error> { fn compute(
state: &S,
entry: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
let psmeta = state.metadata::<SchedulerMetadata>()?; let psmeta = state.metadata::<SchedulerMetadata>()?;
let fuzz_mu = if let Some(strat) = psmeta.strat() { let fuzz_mu = if let Some(strat) = psmeta.strat() {
@ -267,13 +277,16 @@ where
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct CorpusWeightTestcaseScore {} pub struct CorpusWeightTestcaseScore {}
impl<I, S> TestcaseScore<I, S> for CorpusWeightTestcaseScore impl<S> TestcaseScore<S> for CorpusWeightTestcaseScore
where where
S: HasCorpus + HasMetadata, S: HasCorpus + HasMetadata,
{ {
/// Compute the `weight` used in weighted corpus entry selection algo /// Compute the `weight` used in weighted corpus entry selection algo
#[allow(clippy::cast_precision_loss, clippy::cast_lossless)] #[allow(clippy::cast_precision_loss, clippy::cast_lossless)]
fn compute(state: &S, entry: &mut Testcase<I>) -> Result<f64, Error> { fn compute(
state: &S,
entry: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<f64, Error> {
let mut weight = 1.0; let mut weight = 1.0;
let psmeta = state.metadata::<SchedulerMetadata>()?; let psmeta = state.metadata::<SchedulerMetadata>()?;

View File

@ -16,7 +16,6 @@ use serde::{Deserialize, Serialize};
use super::powersched::PowerSchedule; use super::powersched::PowerSchedule;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, HasTestcase, Testcase}, corpus::{Corpus, CorpusId, HasTestcase, Testcase},
inputs::Input,
observers::MapObserver, observers::MapObserver,
random_corpus_id, random_corpus_id,
schedulers::{ schedulers::{
@ -163,11 +162,10 @@ where
clippy::cast_precision_loss, clippy::cast_precision_loss,
clippy::cast_lossless clippy::cast_lossless
)] )]
pub fn create_alias_table<I, S>(&self, state: &mut S) -> Result<(), Error> pub fn create_alias_table<S>(&self, state: &mut S) -> Result<(), Error>
where where
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
I: Input, S: HasCorpus + HasMetadata,
S: HasCorpus<Input = I> + HasMetadata,
{ {
let n = state.corpus().count(); let n = state.corpus().count();
@ -312,13 +310,12 @@ impl<C, F, O> HasQueueCycles for WeightedScheduler<C, F, O> {
} }
} }
impl<C, F, I, O, S> Scheduler<I, S> for WeightedScheduler<C, F, O> impl<C, F, O, S> Scheduler<<S::Corpus as Corpus>::Input, S> for WeightedScheduler<C, F, O>
where where
C: AsRef<O> + Named, C: AsRef<O> + Named,
F: TestcaseScore<I, S>, F: TestcaseScore<S>,
I: Input,
O: MapObserver, O: MapObserver,
S: HasCorpus<Input = I> + HasMetadata + HasRand + HasTestcase, S: HasCorpus + HasMetadata + HasRand + HasTestcase,
{ {
/// Called when a [`Testcase`] is added to the corpus /// Called when a [`Testcase`] is added to the corpus
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> { fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
@ -327,7 +324,12 @@ where
Ok(()) Ok(())
} }
fn on_evaluation<OT>(&mut self, state: &mut S, _input: &I, observers: &OT) -> Result<(), Error> fn on_evaluation<OT>(
&mut self,
state: &mut S,
_input: &<S::Corpus as Corpus>::Input,
observers: &OT,
) -> Result<(), Error>
where where
OT: MatchName, OT: MatchName,
{ {

View File

@ -100,8 +100,9 @@ where
C: AsRef<O>, C: AsRef<O>,
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static, for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
OT: ObserversTuple<Self::State>, OT: ObserversTuple<Self::State>,
Self::State: HasCorpus + HasMetadata + HasNamedMetadata + HasExecutions, E::State: HasCorpus + HasMetadata + HasNamedMetadata + HasExecutions + HasCurrentTestcase,
Z: Evaluator<E, EM, State = Self::State>, Z: Evaluator<E, EM, State = Self::State>,
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
#[allow( #[allow(

View File

@ -14,6 +14,7 @@ use libafl_bolts::{
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::Corpus,
events::EventFirer, events::EventFirer,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::HasMutatorBytes, inputs::HasMutatorBytes,
@ -87,11 +88,12 @@ impl<C, E, EM, O, Z> Stage<E, EM, Z> for ColorizationStage<C, E, EM, O, Z>
where where
EM: UsesState<State = Self::State> + EventFirer, EM: UsesState<State = Self::State> + EventFirer,
E: HasObservers + Executor<EM, Z>, E: HasObservers + Executor<EM, Z>,
Self::State: HasCorpus + HasMetadata + HasRand + HasNamedMetadata, E::State: HasCorpus + HasMetadata + HasRand + HasNamedMetadata,
E::Input: HasMutatorBytes, E::Input: HasMutatorBytes,
O: MapObserver, O: MapObserver,
C: AsRef<O> + Named, C: AsRef<O> + Named,
Z: UsesState<State = Self::State>, Z: UsesState<State = Self::State>,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>, //delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
@ -165,9 +167,10 @@ where
O: MapObserver, O: MapObserver,
C: AsRef<O> + Named, C: AsRef<O> + Named,
E: HasObservers + Executor<EM, Z>, E: HasObservers + Executor<EM, Z>,
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand, <E as UsesState>::State: HasCorpus + HasMetadata + HasRand,
E::Input: HasMutatorBytes, E::Input: HasMutatorBytes,
Z: UsesState<State = <Self as UsesState>::State>, Z: UsesState<State = <Self as UsesState>::State>,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>, //delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]

View File

@ -17,6 +17,7 @@ use crate::monitors::PerfFeature;
#[cfg(all(feature = "introspection", feature = "concolic_mutation"))] #[cfg(all(feature = "introspection", feature = "concolic_mutation"))]
use crate::state::HasClientPerfMonitor; use crate::state::HasClientPerfMonitor;
use crate::{ use crate::{
corpus::Corpus,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
observers::concolic::ConcolicObserver, observers::concolic::ConcolicObserver,
stages::{RetryCountRestartHelper, Stage, TracingStage}, stages::{RetryCountRestartHelper, Stage, TracingStage},
@ -62,8 +63,9 @@ where
E: UsesState<State = Self::State>, E: UsesState<State = Self::State>,
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
TE: Executor<EM, Z> + HasObservers, TE: Executor<EM, Z> + HasObservers,
Self::State: HasExecutions + HasCorpus + HasNamedMetadata, TE::State: HasExecutions + HasCorpus + HasNamedMetadata + HasCurrentTestcase,
Z: UsesState<State = Self::State>, Z: UsesState<State = Self::State>,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
fn perform( fn perform(
@ -395,7 +397,9 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Z::Input: HasMutatorBytes, Z::Input: HasMutatorBytes,
Self::State: State + HasExecutions + HasCorpus + HasMetadata + HasNamedMetadata, Z::State:
State + HasExecutions + HasCorpus + HasMetadata + HasNamedMetadata + HasCurrentTestcase,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, //delete me
{ {
#[inline] #[inline]
fn perform( fn perform(

View File

@ -9,7 +9,6 @@ use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId}, corpus::{Corpus, CorpusId},
inputs::UsesInput,
stages::Stage, stages::Stage,
state::{HasCorpus, HasRand, HasSolutions, UsesState}, state::{HasCorpus, HasRand, HasSolutions, UsesState},
Error, HasMetadata, Error, HasMetadata,
@ -46,11 +45,13 @@ where
impl<CB, E, EM, Z> Stage<E, EM, Z> for DumpToDiskStage<CB, EM, Z> impl<CB, E, EM, Z> Stage<E, EM, Z> for DumpToDiskStage<CB, EM, Z>
where where
CB: FnMut(&<Self::State as UsesInput>::Input, &Self::State) -> Vec<u8>, CB: FnMut(&Self::Input, &Self::State) -> Vec<u8>,
EM: UsesState, EM: UsesState,
E: UsesState<State = Self::State>, E: UsesState<State = Self::State>,
Z: UsesState<State = Self::State>, Z: UsesState<State = Self::State>,
Self::State: HasCorpus + HasSolutions + HasRand + HasMetadata, EM::State: HasCorpus + HasSolutions + HasRand + HasMetadata,
<<EM as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
<<EM as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
fn perform( fn perform(

View File

@ -73,9 +73,10 @@ where
O: MapObserver, O: MapObserver,
C: CanTrack + AsRef<O> + Named, C: CanTrack + AsRef<O> + Named,
E: Executor<EM, Z, State = Self::State> + HasObservers, E: Executor<EM, Z, State = Self::State> + HasObservers,
Self::State: EM::State:
UsesInput<Input = BytesInput> + HasExecutions + HasMetadata + HasCorpus + HasNamedMetadata, UsesInput<Input = BytesInput> + HasExecutions + HasMetadata + HasCorpus + HasNamedMetadata,
EM: UsesState, EM: UsesState,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = BytesInput>, //delete me
Z: UsesState<State = Self::State>, Z: UsesState<State = Self::State>,
{ {
#[inline] #[inline]

View File

@ -60,7 +60,8 @@ where
impl<I, S> MutatedTransform<I, S> for I impl<I, S> MutatedTransform<I, S> for I
where where
I: Input + Clone, I: Input + Clone,
S: HasCorpus<Input = I>, S: HasCorpus,
S::Corpus: Corpus<Input = I>,
{ {
type Post = (); type Post = ();
@ -85,8 +86,9 @@ where
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
Z: Evaluator<E, EM, State = Self::State>, Z: Evaluator<E, EM, State = Self::State>,
Self::State: HasCorpus, Self::State: HasCorpus + HasCurrentTestcase,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>,
{ {
/// The mutator registered for this stage /// The mutator registered for this stage
fn mutator(&self) -> &M; fn mutator(&self) -> &M;
@ -171,8 +173,9 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Self::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasNamedMetadata, Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasNamedMetadata,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
#[inline] #[inline]
@ -216,8 +219,9 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Self::State: HasCorpus + HasRand + HasMetadata + HasExecutions + HasNamedMetadata, Z::State: HasCorpus + HasRand + HasMetadata + HasExecutions + HasNamedMetadata,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
@ -329,8 +333,9 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
M: MultiMutator<I, Self::State>, M: MultiMutator<I, Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Self::State: HasCorpus + HasRand + HasNamedMetadata, Z::State: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
fn should_restart(&mut self, state: &mut Self::State) -> Result<bool, Error> { fn should_restart(&mut self, state: &mut Self::State) -> Result<bool, Error> {

View File

@ -9,6 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named; use libafl_bolts::Named;
use crate::{ use crate::{
corpus::Corpus,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
fuzzer::Evaluator, fuzzer::Evaluator,
inputs::Input, inputs::Input,
@ -50,12 +51,14 @@ impl<E, F, EM, I, M, Z> MutationalStage<E, EM, I, M, Z> for PowerMutationalStage
where where
E: Executor<EM, Z> + HasObservers, E: Executor<EM, Z> + HasObservers,
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
F: TestcaseScore<I, Self::State>, F: TestcaseScore<Self::State>,
I: Input, I: Input,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Self::State: HasCorpus<Input = I> + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, E::State:
HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata + HasCurrentTestcase,
Z: Evaluator<E, EM, State = Self::State>, Z: Evaluator<E, EM, State = Self::State>,
I: MutatedTransform<E::Input, Self::State> + Clone, I: MutatedTransform<E::Input, Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
#[inline] #[inline]
@ -84,11 +87,13 @@ impl<E, F, EM, I, M, Z> Stage<E, EM, Z> for PowerMutationalStage<E, F, EM, I, M,
where where
E: Executor<EM, Z> + HasObservers, E: Executor<EM, Z> + HasObservers,
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
F: TestcaseScore<I, Self::State>, F: TestcaseScore<Self::State>,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Self::State: HasCorpus<Input = I> + HasMetadata + HasRand + HasExecutions + HasNamedMetadata, E::State:
HasCorpus + HasMetadata + HasRand + HasExecutions + HasNamedMetadata + HasCurrentTestcase,
Z: Evaluator<E, EM, State = Self::State>, Z: Evaluator<E, EM, State = Self::State>,
I: MutatedTransform<Self::Input, Self::State> + Clone + Input, I: MutatedTransform<Self::Input, Self::State> + Clone + Input,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
@ -117,7 +122,7 @@ impl<E, F, EM, I, M, Z> PowerMutationalStage<E, F, EM, I, M, Z>
where where
E: Executor<EM, Z> + HasObservers, E: Executor<EM, Z> + HasObservers,
EM: UsesState<State = <Self as UsesState>::State>, EM: UsesState<State = <Self as UsesState>::State>,
F: TestcaseScore<I, <Self as UsesState>::State>, F: TestcaseScore<<Self as UsesState>::State>,
I: Input, I: Input,
M: Mutator<I, <Self as UsesState>::State>, M: Mutator<I, <Self as UsesState>::State>,
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand, <Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,

View File

@ -21,7 +21,7 @@ use crate::{
observers::ObserversTuple, observers::ObserversTuple,
schedulers::Scheduler, schedulers::Scheduler,
start_timer, start_timer,
state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand}, state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand, UsesState},
Error, EvaluatorObservers, ExecutionProcessor, HasMetadata, HasScheduler, Error, EvaluatorObservers, ExecutionProcessor, HasMetadata, HasScheduler,
}; };
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
@ -88,6 +88,7 @@ where
OT: ObserversTuple<Z::State> + Serialize, OT: ObserversTuple<Z::State> + Serialize,
Z::State: HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug, Z::State: HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>, Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, //delete me
{ {
#[inline] #[inline]
fn push_stage_helper(&self) -> &PushStageHelper<CS, EM, OT, Z> { fn push_stage_helper(&self) -> &PushStageHelper<CS, EM, OT, Z> {
@ -196,6 +197,7 @@ where
OT: ObserversTuple<Z::State> + Serialize, OT: ObserversTuple<Z::State> + Serialize,
Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug, Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>, Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, //delete me
{ {
type Item = Result<<Z::State as UsesInput>::Input, Error>; type Item = Result<<Z::State as UsesInput>::Input, Error>;

View File

@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::state::HasClientPerfMonitor; use crate::state::HasClientPerfMonitor;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, HasTestcase}, corpus::{Corpus, CorpusId},
events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer}, events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer},
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor}, fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
@ -249,7 +249,7 @@ where
impl<E, EM, IC, ICB, DI, S, SP, Z> Stage<E, EM, Z> for SyncFromBrokerStage<DI, IC, ICB, S, SP> impl<E, EM, IC, ICB, DI, S, SP, Z> Stage<E, EM, Z> for SyncFromBrokerStage<DI, IC, ICB, S, SP>
where where
EM: UsesState<State = S> + EventFirer, EM: UsesState<State = S> + EventFirer,
S: State + HasExecutions + HasCorpus + HasRand + HasMetadata + HasTestcase, S: State + HasExecutions + HasCorpus + HasRand + HasMetadata,
SP: ShMemProvider, SP: ShMemProvider,
E: HasObservers<State = S> + Executor<EM, Z>, E: HasObservers<State = S> + Executor<EM, Z>,
for<'a> E::Observers: Deserialize<'a>, for<'a> E::Observers: Deserialize<'a>,
@ -257,6 +257,8 @@ where
IC: InputConverter<From = S::Input, To = DI>, IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>, ICB: InputConverter<From = DI, To = S::Input>,
DI: Input, DI: Input,
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone,
S::Corpus: Corpus<Input = S::Input>, // delete me
{ {
#[inline] #[inline]
fn perform( fn perform(

View File

@ -48,7 +48,7 @@ where
<E as UsesObservers>::Observers: Serialize, <E as UsesObservers>::Observers: Serialize,
EM: UsesState<State = Self::State> + EventFirer, EM: UsesState<State = Self::State> + EventFirer,
F: Feedback<Self::State>, F: Feedback<Self::State>,
Self::State: HasMaxSize + HasCorpus + HasSolutions + HasExecutions, Self::State: HasMaxSize + HasCorpus + HasSolutions + HasExecutions + HasCurrentTestcase,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + Hash + HasLen, Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + Hash + HasLen,
IP: Clone + MutatedTransformPost<Self::State>, IP: Clone + MutatedTransformPost<Self::State>,
M: Mutator<Self::Input, Self::State>, M: Mutator<Self::Input, Self::State>,
@ -58,6 +58,7 @@ where
+ ExecutesInput<E, EM> + ExecutesInput<E, EM>
+ ExecutionProcessor, + ExecutionProcessor,
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>, Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>,
{ {
/// The mutator registered for this stage /// The mutator registered for this stage
fn mutator(&self) -> &M; fn mutator(&self) -> &M;
@ -246,10 +247,11 @@ where
FF: FeedbackFactory<F, E::Observers>, FF: FeedbackFactory<F, E::Observers>,
F: Feedback<Self::State>, F: Feedback<Self::State>,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash, Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
Self::State: Z::State:
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata, HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata,
M: Mutator<Self::Input, Self::State>, M: Mutator<Self::Input, Self::State>,
IP: MutatedTransformPost<Self::State> + Clone, IP: MutatedTransformPost<Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
{ {
fn should_restart(&mut self, state: &mut Self::State) -> Result<bool, Error> { fn should_restart(&mut self, state: &mut Self::State) -> Result<bool, Error> {
self.restart_helper.should_restart(state, &self.name) self.restart_helper.should_restart(state, &self.name)
@ -308,10 +310,16 @@ where
FF: FeedbackFactory<F, E::Observers>, FF: FeedbackFactory<F, E::Observers>,
F: Feedback<Self::State>, F: Feedback<Self::State>,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash, Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
Self::State: Z::State: HasMetadata
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata, + HasExecutions
+ HasSolutions
+ HasCorpus
+ HasMaxSize
+ HasNamedMetadata
+ HasCurrentTestcase,
M: Mutator<Self::Input, Self::State>, M: Mutator<Self::Input, Self::State>,
IP: MutatedTransformPost<Self::State> + Clone, IP: MutatedTransformPost<Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
{ {
/// The mutator, added to this stage /// The mutator, added to this stage
#[inline] #[inline]

View File

@ -9,6 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::Named; use libafl_bolts::Named;
use crate::{ use crate::{
corpus::Corpus,
executors::{Executor, HasObservers, ShadowExecutor}, executors::{Executor, HasObservers, ShadowExecutor},
mark_feature_time, mark_feature_time,
observers::ObserversTuple, observers::ObserversTuple,
@ -39,9 +40,10 @@ where
impl<EM, TE, Z> TracingStage<EM, TE, Z> impl<EM, TE, Z> TracingStage<EM, TE, Z>
where where
TE: Executor<EM, Z> + HasObservers, TE: Executor<EM, Z> + HasObservers,
<Self as UsesState>::State: HasExecutions + HasCorpus + HasNamedMetadata, <TE as UsesState>::State: HasExecutions + HasCorpus + HasNamedMetadata + HasCurrentTestcase,
EM: UsesState<State = <Self as UsesState>::State>, EM: UsesState<State = <Self as UsesState>::State>,
Z: UsesState<State = <Self as UsesState>::State>, Z: UsesState<State = <Self as UsesState>::State>,
<<TE as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = TE::Input>, // delete me
{ {
#[allow(rustdoc::broken_intra_doc_links)] #[allow(rustdoc::broken_intra_doc_links)]
/// Perform tracing on the given `CorpusId`. Useful for if wrapping [`TracingStage`] with your /// Perform tracing on the given `CorpusId`. Useful for if wrapping [`TracingStage`] with your
@ -84,9 +86,10 @@ impl<E, EM, TE, Z> Stage<E, EM, Z> for TracingStage<EM, TE, Z>
where where
E: UsesState<State = <Self as UsesState>::State>, E: UsesState<State = <Self as UsesState>::State>,
TE: Executor<EM, Z> + HasObservers, TE: Executor<EM, Z> + HasObservers,
<Self as UsesState>::State: HasExecutions + HasCorpus + HasNamedMetadata, <TE as UsesState>::State: HasExecutions + HasCorpus + HasNamedMetadata,
EM: UsesState<State = <Self as UsesState>::State>, EM: UsesState<State = <Self as UsesState>::State>,
Z: UsesState<State = <Self as UsesState>::State>, Z: UsesState<State = <Self as UsesState>::State>,
<<TE as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = TE::Input>, // delete me
{ {
#[inline] #[inline]
fn perform( fn perform(
@ -181,7 +184,9 @@ where
EM: UsesState<State = <Self as UsesState>::State>, EM: UsesState<State = <Self as UsesState>::State>,
SOT: ObserversTuple<E::State>, SOT: ObserversTuple<E::State>,
Z: UsesState<State = <Self as UsesState>::State>, Z: UsesState<State = <Self as UsesState>::State>,
<Self as UsesState>::State: State + HasExecutions + HasCorpus + HasNamedMetadata + Debug, <E as UsesState>::State:
State + HasExecutions + HasCorpus + HasNamedMetadata + Debug + HasCurrentTestcase,
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>, // delete me
{ {
#[inline] #[inline]
fn perform( fn perform(

View File

@ -7,6 +7,7 @@ use libafl_bolts::{current_time, impl_serdeany, rands::Rand};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::Corpus,
mark_feature_time, mark_feature_time,
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
stages::{ stages::{
@ -164,8 +165,10 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Self::State: HasCorpus + HasRand + HasNamedMetadata + HasMetadata + HasExecutions, Z::State:
HasCorpus + HasRand + HasNamedMetadata + HasMetadata + HasExecutions + HasCurrentTestcase,
I: MutatedTransform<Z::Input, Self::State> + Clone, I: MutatedTransform<Z::Input, Self::State> + Clone,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, // delete me
{ {
/// Runs this (mutational) stage for the given `testcase` /// Runs this (mutational) stage for the given `testcase`
/// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support. /// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support.
@ -263,8 +266,10 @@ where
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
M: Mutator<I, Self::State>, M: Mutator<I, Self::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
Self::State: HasCorpus + HasRand + HasNamedMetadata + HasMetadata + HasExecutions, Z::State:
HasCorpus + HasRand + HasNamedMetadata + HasMetadata + HasExecutions + HasCurrentTestcase,
I: MutatedTransform<Self::Input, Self::State> + Clone, I: MutatedTransform<Self::Input, Self::State> + Clone,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, // delete me
{ {
#[inline] #[inline]
#[allow(clippy::let_and_return)] #[allow(clippy::let_and_return)]
@ -298,9 +303,10 @@ where
EM: UsesState<State = <Self as UsesState>::State>, EM: UsesState<State = <Self as UsesState>::State>,
M: Mutator<I, <Self as UsesState>::State>, M: Mutator<I, <Self as UsesState>::State>,
Z: Evaluator<E, EM>, Z: Evaluator<E, EM>,
<Self as UsesState>::State: <Z as UsesState>::State:
HasCorpus + HasRand + HasNamedMetadata + HasExecutions + HasMetadata, HasCorpus + HasRand + HasNamedMetadata + HasExecutions + HasMetadata + HasCurrentTestcase,
I: MutatedTransform<Z::Input, <Self as UsesState>::State> + Clone, I: MutatedTransform<Z::Input, <Self as UsesState>::State> + Clone,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, // delete me
{ {
fn execs_since_progress_start( fn execs_since_progress_start(
&mut self, &mut self,

View File

@ -8,7 +8,7 @@ use libafl_bolts::{impl_serdeany, Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::HasTestcase, corpus::Corpus,
inputs::{BytesInput, HasMutatorBytes}, inputs::{BytesInput, HasMutatorBytes},
stages::Stage, stages::Stage,
state::{HasCorpus, HasCurrentTestcase, State, UsesState}, state::{HasCorpus, HasCurrentTestcase, State, UsesState},
@ -100,7 +100,8 @@ where
impl<S, E, EM, Z> Stage<E, EM, Z> for UnicodeIdentificationStage<S> impl<S, E, EM, Z> Stage<E, EM, Z> for UnicodeIdentificationStage<S>
where where
S: HasTestcase<Input = BytesInput> + HasCorpus + State, S: HasCorpus + State + HasCurrentTestcase,
S::Corpus: Corpus<Input = BytesInput>,
E: UsesState<State = S>, E: UsesState<State = S>,
EM: UsesState<State = S>, EM: UsesState<State = S>,
Z: UsesState<State = S>, Z: UsesState<State = S>,

View File

@ -74,9 +74,9 @@ where
} }
/// Trait for elements offering a corpus /// Trait for elements offering a corpus
pub trait HasCorpus: UsesInput { pub trait HasCorpus {
/// The associated type implementing [`Corpus`]. /// The associated type implementing [`Corpus`].
type Corpus: Corpus<Input = <Self as UsesInput>::Input>; type Corpus: Corpus;
/// The testcase corpus /// The testcase corpus
fn corpus(&self) -> &Self::Corpus; fn corpus(&self) -> &Self::Corpus;
@ -84,6 +84,22 @@ pub trait HasCorpus: UsesInput {
fn corpus_mut(&mut self) -> &mut Self::Corpus; fn corpus_mut(&mut self) -> &mut Self::Corpus;
} }
// Reflexivity
impl<C> HasCorpus for C
where
C: Corpus,
{
type Corpus = Self;
fn corpus(&self) -> &Self::Corpus {
self
}
fn corpus_mut(&mut self) -> &mut Self::Corpus {
self
}
}
/// Interact with the maximum size /// Interact with the maximum size
pub trait HasMaxSize { pub trait HasMaxSize {
/// The maximum size hint for items and mutations returned /// The maximum size hint for items and mutations returned
@ -93,9 +109,9 @@ pub trait HasMaxSize {
} }
/// Trait for elements offering a corpus of solutions /// Trait for elements offering a corpus of solutions
pub trait HasSolutions: UsesInput { pub trait HasSolutions {
/// The associated type implementing [`Corpus`] for solutions /// The associated type implementing [`Corpus`] for solutions
type Solutions: Corpus<Input = <Self as UsesInput>::Input>; type Solutions: Corpus;
/// The solutions corpus /// The solutions corpus
fn solutions(&self) -> &Self::Solutions; fn solutions(&self) -> &Self::Solutions;
@ -289,9 +305,9 @@ where
impl<I, C, R, SC> State for StdState<I, C, R, SC> impl<I, C, R, SC> State for StdState<I, C, R, SC>
where where
C: Corpus<Input = Self::Input>, C: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
R: Rand, R: Rand,
SC: Corpus<Input = Self::Input>, SC: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
Self: UsesInput, Self: UsesInput,
{ {
} }
@ -317,9 +333,7 @@ where
impl<I, C, R, SC> HasCorpus for StdState<I, C, R, SC> impl<I, C, R, SC> HasCorpus for StdState<I, C, R, SC>
where where
I: Input, C: Corpus,
C: Corpus<Input = <Self as UsesInput>::Input>,
R: Rand,
{ {
type Corpus = C; type Corpus = C;
@ -338,23 +352,15 @@ where
impl<I, C, R, SC> HasTestcase for StdState<I, C, R, SC> impl<I, C, R, SC> HasTestcase for StdState<I, C, R, SC>
where where
I: Input, C: Corpus,
C: Corpus<Input = <Self as UsesInput>::Input>,
R: Rand,
{ {
/// To get the testcase /// To get the testcase
fn testcase( fn testcase(&self, id: CorpusId) -> Result<Ref<'_, Testcase<C::Input>>, Error> {
&self,
id: CorpusId,
) -> Result<Ref<'_, Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow()) Ok(self.corpus().get(id)?.borrow())
} }
/// To get mutable testcase /// To get mutable testcase
fn testcase_mut( fn testcase_mut(&self, id: CorpusId) -> Result<RefMut<'_, Testcase<C::Input>>, Error> {
&self,
id: CorpusId,
) -> Result<RefMut<'_, Testcase<<Self as UsesInput>::Input>>, Error> {
Ok(self.corpus().get(id)?.borrow_mut()) Ok(self.corpus().get(id)?.borrow_mut())
} }
} }
@ -504,20 +510,20 @@ impl<I, C, R, SC> HasCurrentCorpusId for StdState<I, C, R, SC> {
} }
/// Has information about the current [`Testcase`] we are fuzzing /// Has information about the current [`Testcase`] we are fuzzing
pub trait HasCurrentTestcase<I> pub trait HasCurrentTestcase: HasCorpus {
where
I: Input,
{
/// Gets the current [`Testcase`] we are fuzzing /// Gets the current [`Testcase`] we are fuzzing
/// ///
/// Will return [`Error::key_not_found`] if no `corpus_id` is currently set. /// Will return [`Error::key_not_found`] if no `corpus_id` is currently set.
fn current_testcase(&self) -> Result<Ref<'_, Testcase<I>>, Error>; fn current_testcase(&self)
-> Result<Ref<'_, Testcase<<Self::Corpus as Corpus>::Input>>, Error>;
//fn current_testcase(&self) -> Result<&Testcase<I>, Error>; //fn current_testcase(&self) -> Result<&Testcase<I>, Error>;
/// Gets the current [`Testcase`] we are fuzzing (mut) /// Gets the current [`Testcase`] we are fuzzing (mut)
/// ///
/// Will return [`Error::key_not_found`] if no `corpus_id` is currently set. /// Will return [`Error::key_not_found`] if no `corpus_id` is currently set.
fn current_testcase_mut(&self) -> Result<RefMut<'_, Testcase<I>>, Error>; fn current_testcase_mut(
&self,
) -> Result<RefMut<'_, Testcase<<Self::Corpus as Corpus>::Input>>, Error>;
//fn current_testcase_mut(&self) -> Result<&mut Testcase<I>, Error>; //fn current_testcase_mut(&self) -> Result<&mut Testcase<I>, Error>;
/// Gets a cloned representation of the current [`Testcase`]. /// Gets a cloned representation of the current [`Testcase`].
@ -527,15 +533,17 @@ where
/// # Note /// # Note
/// This allocates memory and copies the contents! /// This allocates memory and copies the contents!
/// For performance reasons, if you just need to access the testcase, use [`Self::current_testcase`] instead. /// For performance reasons, if you just need to access the testcase, use [`Self::current_testcase`] instead.
fn current_input_cloned(&self) -> Result<I, Error>; fn current_input_cloned(&self) -> Result<<Self::Corpus as Corpus>::Input, Error>;
} }
impl<I, T> HasCurrentTestcase<I> for T impl<T> HasCurrentTestcase for T
where where
I: Input, T: HasCorpus + HasCurrentCorpusId,
T: HasCorpus + HasCurrentCorpusId + UsesInput<Input = I>, <Self::Corpus as Corpus>::Input: Clone,
{ {
fn current_testcase(&self) -> Result<Ref<'_, Testcase<I>>, Error> { fn current_testcase(
&self,
) -> Result<Ref<'_, Testcase<<Self::Corpus as Corpus>::Input>>, Error> {
let Some(corpus_id) = self.current_corpus_id()? else { let Some(corpus_id) = self.current_corpus_id()? else {
return Err(Error::key_not_found( return Err(Error::key_not_found(
"We are not currently processing a testcase", "We are not currently processing a testcase",
@ -545,7 +553,9 @@ where
Ok(self.corpus().get(corpus_id)?.borrow()) Ok(self.corpus().get(corpus_id)?.borrow())
} }
fn current_testcase_mut(&self) -> Result<RefMut<'_, Testcase<I>>, Error> { fn current_testcase_mut(
&self,
) -> Result<RefMut<'_, Testcase<<Self::Corpus as Corpus>::Input>>, Error> {
let Some(corpus_id) = self.current_corpus_id()? else { let Some(corpus_id) = self.current_corpus_id()? else {
return Err(Error::illegal_state( return Err(Error::illegal_state(
"We are not currently processing a testcase", "We are not currently processing a testcase",
@ -555,7 +565,7 @@ where
Ok(self.corpus().get(corpus_id)?.borrow_mut()) Ok(self.corpus().get(corpus_id)?.borrow_mut())
} }
fn current_input_cloned(&self) -> Result<I, Error> { fn current_input_cloned(&self) -> Result<<Self::Corpus as Corpus>::Input, Error> {
let mut testcase = self.current_testcase_mut()?; let mut testcase = self.current_testcase_mut()?;
Ok(testcase.borrow_mut().load_input(self.corpus())?.clone()) Ok(testcase.borrow_mut().load_input(self.corpus())?.clone())
} }
@ -1153,6 +1163,8 @@ where
where where
F: Feedback<Self>, F: Feedback<Self>,
O: Feedback<Self>, O: Feedback<Self>,
C: Serialize + DeserializeOwned,
SC: Serialize + DeserializeOwned,
{ {
let mut state = Self { let mut state = Self {
rand, rand,

View File

@ -417,6 +417,9 @@ where
pub trait NamedTuple: HasConstLen { pub trait NamedTuple: HasConstLen {
/// Gets the name of this tuple /// Gets the name of this tuple
fn name(&self, index: usize) -> Option<&Cow<'static, str>>; fn name(&self, index: usize) -> Option<&Cow<'static, str>>;
/// Gets all the names
fn names(&self) -> Vec<Cow<'static, str>>;
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -424,6 +427,10 @@ impl NamedTuple for () {
fn name(&self, _index: usize) -> Option<&Cow<'static, str>> { fn name(&self, _index: usize) -> Option<&Cow<'static, str>> {
None None
} }
fn names(&self) -> Vec<Cow<'static, str>> {
Vec::new()
}
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -448,6 +455,13 @@ where
self.1.name(index - 1) self.1.name(index - 1)
} }
} }
fn names(&self) -> Vec<Cow<'static, str>> {
let first = self.0.name().clone();
let mut last = self.1.names();
last.insert(0, first);
last
}
} }
/// Match for a name and return the value /// Match for a name and return the value
@ -596,7 +610,6 @@ pub struct RefIndexable<RM, M>(RM, PhantomData<M>);
impl<RM, M> From<RM> for RefIndexable<RM, M> impl<RM, M> From<RM> for RefIndexable<RM, M>
where where
RM: Deref<Target = M>, RM: Deref<Target = M>,
M: MatchName,
{ {
fn from(value: RM) -> Self { fn from(value: RM) -> Self {
RefIndexable(value, PhantomData) RefIndexable(value, PhantomData)

View File

@ -9,6 +9,7 @@ use frida_gum::{
}; };
#[cfg(windows)] #[cfg(windows)]
use libafl::{ use libafl::{
corpus::Corpus,
executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks}, executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks},
state::{HasCorpus, HasSolutions}, state::{HasCorpus, HasSolutions},
}; };
@ -242,6 +243,8 @@ where
S::Input: HasTargetBytes, S::Input: HasTargetBytes,
OT: ObserversTuple<S>, OT: ObserversTuple<S>,
RT: FridaRuntimeTuple, RT: FridaRuntimeTuple,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
/// the timeout handler /// the timeout handler
#[inline] #[inline]

View File

@ -12,7 +12,7 @@ use libafl::{
inmemory::{TestcaseStorage, TestcaseStorageMap}, inmemory::{TestcaseStorage, TestcaseStorageMap},
Corpus, CorpusId, Testcase, Corpus, CorpusId, Testcase,
}, },
inputs::{Input, UsesInput}, inputs::Input,
}; };
use libafl_bolts::Error; use libafl_bolts::Error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -140,17 +140,12 @@ where
} }
} }
impl<I> UsesInput for LibfuzzerCorpus<I>
where
I: Input + Serialize + for<'de> Deserialize<'de>,
{
type Input = I;
}
impl<I> Corpus for LibfuzzerCorpus<I> impl<I> Corpus for LibfuzzerCorpus<I>
where where
I: Input + Serialize + for<'de> Deserialize<'de>, I: Input + Serialize + for<'de> Deserialize<'de>,
{ {
type Input = I;
#[inline] #[inline]
fn count(&self) -> usize { fn count(&self) -> usize {
self.mapping.enabled.map.len() self.mapping.enabled.map.len()
@ -282,17 +277,12 @@ where
} }
} }
impl<I> UsesInput for ArtifactCorpus<I>
where
I: Input + Serialize + for<'de> Deserialize<'de>,
{
type Input = I;
}
impl<I> Corpus for ArtifactCorpus<I> impl<I> Corpus for ArtifactCorpus<I>
where where
I: Input + Serialize + for<'de> Deserialize<'de>, I: Input + Serialize + for<'de> Deserialize<'de>,
{ {
type Input = I;
fn count(&self) -> usize { fn count(&self) -> usize {
self.count self.count
} }

View File

@ -355,7 +355,7 @@ macro_rules! fuzz_with {
// TODO configure with mutation stacking options from libfuzzer // TODO configure with mutation stacking options from libfuzzer
let std_mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations())); let std_mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let std_power = StdPowerMutationalStage::new(std_mutator); let std_power: StdPowerMutationalStage<_, _, BytesInput, _, _> = StdPowerMutationalStage::new(std_mutator);
let std_power = IfStage::new(|_, _, _, _| Ok(mutator_status.std_mutational.into()), (std_power, ())); let std_power = IfStage::new(|_, _, _, _| Ok(mutator_status.std_mutational.into()), (std_power, ()));
// for custom mutator and crossover, each have access to the LLVMFuzzerMutate -- but it appears // for custom mutator and crossover, each have access to the LLVMFuzzerMutate -- but it appears
@ -376,7 +376,7 @@ macro_rules! fuzz_with {
}; };
let std_mutator_no_mutate = StdScheduledMutator::with_max_stack_pow(havoc_crossover(), 3); let std_mutator_no_mutate = StdScheduledMutator::with_max_stack_pow(havoc_crossover(), 3);
let cm_power = StdPowerMutationalStage::new(custom_mutator); let cm_power: StdPowerMutationalStage<_, _, BytesInput, _, _> = StdPowerMutationalStage::new(custom_mutator);
let cm_power = IfStage::new(|_, _, _, _| Ok(mutator_status.custom_mutation.into()), (cm_power, ())); let cm_power = IfStage::new(|_, _, _, _| Ok(mutator_status.custom_mutation.into()), (cm_power, ()));
let cm_std_power = StdMutationalStage::new(std_mutator_no_mutate); let cm_std_power = StdMutationalStage::new(std_mutator_no_mutate);
let cm_std_power = let cm_std_power =
@ -395,7 +395,7 @@ macro_rules! fuzz_with {
let cc_power = StdMutationalStage::new(custom_crossover); let cc_power = StdMutationalStage::new(custom_crossover);
let cc_power = IfStage::new(|_, _, _, _| Ok(mutator_status.custom_crossover.into()), (cc_power, ())); let cc_power = IfStage::new(|_, _, _, _| Ok(mutator_status.custom_crossover.into()), (cc_power, ()));
let cc_std_power = StdPowerMutationalStage::new(std_mutator_no_crossover); let cc_std_power: StdPowerMutationalStage<_, _, BytesInput, _, _> = StdPowerMutationalStage::new(std_mutator_no_crossover);
let cc_std_power = let cc_std_power =
IfStage::new(|_, _, _, _| Ok(mutator_status.std_no_crossover.into()), (cc_std_power, ())); IfStage::new(|_, _, _, _| Ok(mutator_status.std_no_crossover.into()), (cc_std_power, ()));

View File

@ -7,11 +7,8 @@ use core::{
#[cfg(emulation_mode = "usermode")] #[cfg(emulation_mode = "usermode")]
use std::ptr; use std::ptr;
#[cfg(feature = "fork")]
use libafl::{
events::EventManager, executors::InProcessForkExecutor, state::HasLastReportTime, HasMetadata,
};
use libafl::{ use libafl::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::inprocess::InProcessExecutorHandlerData, hooks::inprocess::InProcessExecutorHandlerData,
@ -26,6 +23,10 @@ use libafl::{
Error, ExecutionProcessor, HasScheduler, Error, ExecutionProcessor, HasScheduler,
}; };
#[cfg(feature = "fork")] #[cfg(feature = "fork")]
use libafl::{
events::EventManager, executors::InProcessForkExecutor, state::HasLastReportTime, HasMetadata,
};
#[cfg(feature = "fork")]
use libafl_bolts::shmem::ShMemProvider; use libafl_bolts::shmem::ShMemProvider;
use libafl_bolts::{ use libafl_bolts::{
os::unix_signals::{ucontext_t, Signal}, os::unix_signals::{ucontext_t, Signal},
@ -85,6 +86,8 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus, E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
if BREAK_ON_TMOUT { if BREAK_ON_TMOUT {
libafl_exit_request_timeout(); libafl_exit_request_timeout();
@ -133,6 +136,8 @@ where
OF: Feedback<S>, OF: Feedback<S>,
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions, S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
Z: HasObjective<Objective = OF, State = S> + HasScheduler<State = S> + ExecutionProcessor, Z: HasObjective<Objective = OF, State = S> + HasScheduler<State = S> + ExecutionProcessor,
S::Solutions: Corpus<Input = S::Input>, //delete me
<S::Corpus as Corpus>::Input: Clone, //delete me
{ {
let mut inner = StatefulInProcessExecutor::with_timeout( let mut inner = StatefulInProcessExecutor::with_timeout(
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,

View File

@ -2,6 +2,7 @@ use alloc::borrow::{Cow, ToOwned};
use core::marker::PhantomData; use core::marker::PhantomData;
use libafl::{ use libafl::{
corpus::Corpus,
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
inputs::{BytesInput, UsesInput}, inputs::{BytesInput, UsesInput},
observers::ObserversTuple, observers::ObserversTuple,
@ -51,10 +52,15 @@ impl<E, EM, TE, Z> Stage<E, EM, Z> for AFLppCmplogTracingStage<'_, EM, TE, Z>
where where
E: UsesState<State = Self::State>, E: UsesState<State = Self::State>,
TE: Executor<EM, Z> + HasObservers, TE: Executor<EM, Z> + HasObservers,
Self::State: TE::State: HasExecutions
HasExecutions + HasCorpus + HasMetadata + UsesInput<Input = BytesInput> + HasNamedMetadata, + HasCorpus
+ HasMetadata
+ UsesInput<Input = BytesInput>
+ HasNamedMetadata
+ HasCurrentTestcase,
EM: UsesState<State = Self::State>, EM: UsesState<State = Self::State>,
Z: UsesState<State = Self::State>, Z: UsesState<State = Self::State>,
<Self::State as HasCorpus>::Corpus: Corpus<Input = BytesInput>, //delete me
{ {
#[inline] #[inline]
fn perform( fn perform(

View File

@ -82,7 +82,7 @@ pub extern "C" fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize)
/// A proxy which wraps a targeted mutator. This is used to provide dynamic access to a global /// A proxy which wraps a targeted mutator. This is used to provide dynamic access to a global
/// mutator without knowing the concrete type, which is necessary for custom mutators. /// mutator without knowing the concrete type, which is necessary for custom mutators.
struct MutatorProxy<'a, M, MT, S> { struct MutatorProxy<'a, M, S> {
/// Pointer to the state of the fuzzer /// Pointer to the state of the fuzzer
state: Rc<RefCell<*mut S>>, // refcell to prevent double-mutability over the pointer state: Rc<RefCell<*mut S>>, // refcell to prevent double-mutability over the pointer
/// A weak reference to the mutator to provide to the custom mutator /// A weak reference to the mutator to provide to the custom mutator
@ -90,10 +90,10 @@ struct MutatorProxy<'a, M, MT, S> {
/// The result of mutation, to be propagated to the mutational stage /// The result of mutation, to be propagated to the mutational stage
result: Rc<RefCell<Result<MutationResult, Error>>>, result: Rc<RefCell<Result<MutationResult, Error>>>,
/// Stage index, which is used by libafl mutator implementations /// Stage index, which is used by libafl mutator implementations
phantom: PhantomData<(&'a mut (), MT)>, phantom: PhantomData<&'a mut ()>,
} }
impl<'a, M, MT, S> MutatorProxy<'a, M, MT, S> { impl<'a, M, S> MutatorProxy<'a, M, S> {
/// Crate a new mutator proxy for the given state and mutator /// Crate a new mutator proxy for the given state and mutator
fn new( fn new(
state: &'a mut S, state: &'a mut S,
@ -110,9 +110,7 @@ impl<'a, M, MT, S> MutatorProxy<'a, M, MT, S> {
/// Create a weak version of the proxy, which will become unusable when the custom mutator /// Create a weak version of the proxy, which will become unusable when the custom mutator
/// is no longer permitted to be executed. /// is no longer permitted to be executed.
fn weak( fn weak(&self) -> WeakMutatorProxy<impl Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool, M, S> {
&self,
) -> WeakMutatorProxy<impl Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool, M, MT, S> {
let state = Rc::downgrade(&self.state); let state = Rc::downgrade(&self.state);
WeakMutatorProxy { WeakMutatorProxy {
accessor: move |f: &mut dyn for<'b> FnMut(&'b mut S)| { accessor: move |f: &mut dyn for<'b> FnMut(&'b mut S)| {
@ -136,7 +134,7 @@ impl<'a, M, MT, S> MutatorProxy<'a, M, MT, S> {
/// that once a libafl mutator exits scope (e.g., once the mutational stage is over) that the /// that once a libafl mutator exits scope (e.g., once the mutational stage is over) that the
/// mutator is no longer accessible by the custom mutator. /// mutator is no longer accessible by the custom mutator.
#[derive(Clone)] #[derive(Clone)]
struct WeakMutatorProxy<F, M, MT, S> { struct WeakMutatorProxy<F, M, S> {
/// Function which will perform the access to the state. /// Function which will perform the access to the state.
accessor: F, accessor: F,
@ -145,14 +143,14 @@ struct WeakMutatorProxy<F, M, MT, S> {
/// The result of mutation, to be propagated to the mutational stage /// The result of mutation, to be propagated to the mutational stage
result: Rc<RefCell<Result<MutationResult, Error>>>, result: Rc<RefCell<Result<MutationResult, Error>>>,
phantom: PhantomData<(MT, S)>, phantom: PhantomData<S>,
} }
impl<F, M, MT, S> ErasedLLVMFuzzerMutator for WeakMutatorProxy<F, M, MT, S> impl<F, M, S> ErasedLLVMFuzzerMutator for WeakMutatorProxy<F, M, S>
where where
F: Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool, F: Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool,
M: ScheduledMutator<BytesInput, MT, S>, M: ScheduledMutator<BytesInput, S>,
MT: MutatorsTuple<BytesInput, S>, M::Mutations: MutatorsTuple<BytesInput, S>,
S: HasMaxSize + UsesInput<Input = BytesInput>, S: HasMaxSize + UsesInput<Input = BytesInput>,
{ {
fn mutate(&self, data: *mut u8, size: usize, max_size: usize) -> usize { fn mutate(&self, data: *mut u8, size: usize, max_size: usize) -> usize {
@ -204,12 +202,12 @@ where
/// You should avoid using crossover-like mutators with custom mutators as this may lead to the /// You should avoid using crossover-like mutators with custom mutators as this may lead to the
/// injection of some input portions to another in ways which violate structure. /// injection of some input portions to another in ways which violate structure.
#[derive(Debug)] #[derive(Debug)]
pub struct LLVMCustomMutator<MT, SM, const CROSSOVER: bool> { pub struct LLVMCustomMutator<S, SM, const CROSSOVER: bool> {
mutator: Rc<RefCell<SM>>, mutator: Rc<RefCell<SM>>,
phantom: PhantomData<MT>, phantom: PhantomData<S>,
} }
impl<MT, SM> LLVMCustomMutator<MT, SM, false> { impl<S, SM> LLVMCustomMutator<S, SM, false> {
/// Create the mutator which will invoke the custom mutator, emitting an error if the custom mutator is not present /// Create the mutator which will invoke the custom mutator, emitting an error if the custom mutator is not present
/// ///
/// # Safety /// # Safety
@ -238,7 +236,7 @@ impl<MT, SM> LLVMCustomMutator<MT, SM, false> {
} }
} }
impl<MT, SM> LLVMCustomMutator<MT, SM, true> { impl<S, SM> LLVMCustomMutator<S, SM, true> {
/// Create the mutator which will invoke the custom crossover, emitting an error if the custom crossover is not present /// Create the mutator which will invoke the custom crossover, emitting an error if the custom crossover is not present
/// ///
/// # Safety /// # Safety
@ -267,34 +265,33 @@ impl<MT, SM> LLVMCustomMutator<MT, SM, true> {
} }
} }
impl<MT, S, SM, const CROSSOVER: bool> ComposedByMutations<BytesInput, MT, S> impl<S, SM, const CROSSOVER: bool> ComposedByMutations for LLVMCustomMutator<S, SM, CROSSOVER>
for LLVMCustomMutator<MT, SM, CROSSOVER>
where where
MT: MutatorsTuple<BytesInput, S>, SM: ScheduledMutator<BytesInput, S>,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize, SM::Mutations: MutatorsTuple<BytesInput, S>,
SM: ScheduledMutator<BytesInput, MT, S>,
{ {
fn mutations(&self) -> &MT { type Mutations = SM::Mutations;
fn mutations(&self) -> &Self::Mutations {
unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.") unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.")
} }
fn mutations_mut(&mut self) -> &mut MT { fn mutations_mut(&mut self) -> &mut Self::Mutations {
unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.") unimplemented!("It is unsafe to provide reference-based access to the mutators as they are behind a RefCell.")
} }
} }
impl<MT, SM> Named for LLVMCustomMutator<MT, SM, false> { impl<S, SM> Named for LLVMCustomMutator<S, SM, false> {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator"); static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator");
&NAME &NAME
} }
} }
impl<MT, S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<MT, SM, false> impl<S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<S, SM, false>
where where
MT: MutatorsTuple<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static, S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static,
SM: ScheduledMutator<BytesInput, MT, S> + 'static, SM: ScheduledMutator<BytesInput, S> + 'static,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{ {
#[inline] #[inline]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
@ -302,11 +299,11 @@ where
} }
} }
impl<MT, S, SM> ScheduledMutator<BytesInput, MT, S> for LLVMCustomMutator<MT, SM, false> impl<S, SM> ScheduledMutator<BytesInput, S> for LLVMCustomMutator<S, SM, false>
where where
SM: ScheduledMutator<BytesInput, MT, S> + 'static, SM: ScheduledMutator<BytesInput, S> + 'static,
MT: MutatorsTuple<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static, S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{ {
fn iterations(&self, state: &mut S, input: &S::Input) -> u64 { fn iterations(&self, state: &mut S, input: &S::Input) -> u64 {
let mutator = self.mutator.deref().borrow(); let mutator = self.mutator.deref().borrow();
@ -359,18 +356,19 @@ where
} }
} }
impl<MT, SM> Named for LLVMCustomMutator<MT, SM, true> { impl<S, SM> Named for LLVMCustomMutator<S, SM, true> {
fn name(&self) -> &Cow<'static, str> { fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator"); static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator");
&NAME &NAME
} }
} }
impl<MT, S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<MT, SM, true> impl<S, SM> Mutator<BytesInput, S> for LLVMCustomMutator<S, SM, true>
where where
MT: MutatorsTuple<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static, S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static,
SM: ScheduledMutator<BytesInput, MT, S> + 'static, SM: ScheduledMutator<BytesInput, S> + 'static,
S::Corpus: Corpus<Input = BytesInput>,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{ {
#[inline] #[inline]
fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> { fn mutate(&mut self, state: &mut S, input: &mut S::Input) -> Result<MutationResult, Error> {
@ -378,11 +376,12 @@ where
} }
} }
impl<MT, S, SM> ScheduledMutator<BytesInput, MT, S> for LLVMCustomMutator<MT, SM, true> impl<S, SM> ScheduledMutator<BytesInput, S> for LLVMCustomMutator<S, SM, true>
where where
SM: ScheduledMutator<BytesInput, MT, S> + 'static, SM: ScheduledMutator<BytesInput, S> + 'static,
MT: MutatorsTuple<BytesInput, S> + 'static,
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static, S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + HasCorpus + 'static,
S::Corpus: Corpus<Input = BytesInput>,
SM::Mutations: MutatorsTuple<BytesInput, S>,
{ {
fn iterations(&self, state: &mut S, input: &S::Input) -> u64 { fn iterations(&self, state: &mut S, input: &S::Input) -> u64 {
let mutator = self.mutator.deref().borrow(); let mutator = self.mutator.deref().borrow();

View File

@ -1,10 +1,11 @@
//! Setup asan death callbback //! Setup asan death callbback
use libafl::{ use libafl::{
corpus::Corpus,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers}, executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers},
feedbacks::Feedback, feedbacks::Feedback,
state::{HasCorpus, HasExecutions, HasSolutions}, state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
HasObjective, HasObjective,
}; };
@ -34,6 +35,8 @@ where
OF: Feedback<E::State>, OF: Feedback<E::State>,
E::State: HasSolutions + HasCorpus + HasExecutions, E::State: HasSolutions + HasCorpus + HasExecutions,
Z: HasObjective<Objective = OF, State = E::State>, Z: HasObjective<Objective = OF, State = E::State>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
<<<E as UsesState>::State as HasCorpus>::Corpus as Corpus>::Input: Clone, //delete me
{ {
__sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, OF, Z>)); __sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, OF, Z>));
} }