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:
parent
79cd1afec0
commit
79b8390214
1
.github/workflows/build_and_test.yml
vendored
1
.github/workflows/build_and_test.yml
vendored
@ -110,7 +110,6 @@ jobs:
|
||||
|
||||
ubuntu-miri:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: ubuntu
|
||||
steps:
|
||||
- name: Add nightly clippy
|
||||
run: rustup toolchain install nightly --component miri --allow-downgrade
|
||||
|
@ -94,8 +94,8 @@ pub fn main() -> Result<(), Error> {
|
||||
.expect("Failed to generate the initial corpus");
|
||||
|
||||
// Setup a mutational stage with a basic bytes mutator
|
||||
let mutator = StdScheduledMutator::new(havoc_mutations::<BytesInput>());
|
||||
let minimizer = StdScheduledMutator::new(havoc_mutations::<BytesInput>());
|
||||
let mutator = StdScheduledMutator::new(havoc_mutations());
|
||||
let minimizer = StdScheduledMutator::new(havoc_mutations());
|
||||
let mut stages = tuple_list!(
|
||||
StdMutationalStage::new(mutator),
|
||||
StdTMinMutationalStage::new(minimizer, factory, 128)
|
||||
@ -121,7 +121,7 @@ pub fn main() -> Result<(), Error> {
|
||||
|
||||
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(
|
||||
minimizer,
|
||||
CrashFeedback::new(),
|
||||
|
@ -301,14 +301,15 @@ fn fuzz(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -307,14 +307,15 @@ fn fuzz(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -185,14 +185,15 @@ impl<'a, M: Monitor> Instance<'a, M> {
|
||||
)));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// The order of the stages matter!
|
||||
let mut stages = tuple_list!(calibration, tracing, i2s, power);
|
||||
|
@ -293,14 +293,15 @@ fn fuzz(
|
||||
println!("Let's fuzz :)");
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -293,14 +293,15 @@ fn fuzz(
|
||||
println!("Let's fuzz :)");
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -9,7 +9,7 @@ use std::{
|
||||
};
|
||||
|
||||
use libafl::{
|
||||
corpus::{Corpus, HasCurrentCorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
|
||||
corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase},
|
||||
events::EventFirer,
|
||||
executors::HasObservers,
|
||||
inputs::UsesInput,
|
||||
@ -236,11 +236,11 @@ where
|
||||
+ HasStartTime
|
||||
+ HasExecutions
|
||||
+ HasNamedMetadata
|
||||
+ Stoppable
|
||||
+ HasTestcase,
|
||||
+ Stoppable,
|
||||
O: MapObserver,
|
||||
C: AsRef<O> + Named,
|
||||
<Z as HasScheduler>::Scheduler: HasQueueCycles,
|
||||
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>,
|
||||
{
|
||||
fn perform(
|
||||
&mut self,
|
||||
|
@ -2,7 +2,6 @@ use std::marker::PhantomData;
|
||||
|
||||
use libafl::{
|
||||
corpus::{Corpus, CorpusId, HasTestcase, SchedulerTestcaseMetadata, Testcase},
|
||||
inputs::Input,
|
||||
schedulers::{HasQueueCycles, RemovableScheduler, Scheduler},
|
||||
state::HasCorpus,
|
||||
Error, HasMetadata,
|
||||
@ -14,17 +13,19 @@ pub enum SupportedSchedulers<Q, W> {
|
||||
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
|
||||
Q: Scheduler<I, S> + RemovableScheduler<I, S>,
|
||||
W: Scheduler<I, S> + RemovableScheduler<I, S>,
|
||||
Q: Scheduler<<S::Corpus as Corpus>::Input, 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,
|
||||
{
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
id: CorpusId,
|
||||
testcase: &Option<Testcase<I>>,
|
||||
testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
match self {
|
||||
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 {
|
||||
Self::Queue(queue, _) => queue.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
|
||||
I: Input,
|
||||
Q: Scheduler<I, S>,
|
||||
W: Scheduler<I, S>,
|
||||
Q: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
W: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasTestcase,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
@ -77,7 +82,12 @@ where
|
||||
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
|
||||
OTB: MatchName,
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::{borrow::Cow, marker::PhantomData};
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
inputs::Input,
|
||||
mutators::Mutator,
|
||||
stages::{mutational::MutatedTransform, MutationalStage, Stage},
|
||||
@ -26,6 +27,7 @@ where
|
||||
SM: MutationalStage<E, EM, I, M, Z, State = S>,
|
||||
P: MutationalStage<E, EM, I, M, Z, State = S>,
|
||||
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
|
||||
#[inline]
|
||||
@ -85,6 +87,7 @@ where
|
||||
SM: MutationalStage<E, EM, I, M, Z, State = S>,
|
||||
P: MutationalStage<E, EM, I, M, Z, State = S>,
|
||||
S: State<Input = I> + HasRand + HasCorpus + HasNamedMetadata,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
|
@ -304,14 +304,15 @@ fn fuzz(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -298,14 +298,15 @@ fn fuzz(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -308,14 +308,15 @@ fn fuzz(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
|
@ -365,14 +365,15 @@ fn fuzz_binary(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
let scheduler = IndexesLenTimeMinimizerScheduler::new(
|
||||
@ -577,14 +578,15 @@ fn fuzz_text(
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
// Setup a MOPT mutator
|
||||
let mutator = StdMOptMutator::new(
|
||||
let mutator = StdMOptMutator::new::<BytesInput, _>(
|
||||
&mut state,
|
||||
havoc_mutations().merge(tokens_mutations()),
|
||||
7,
|
||||
5,
|
||||
)?;
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let grimoire_mutator = StdScheduledMutator::with_max_stack_pow(
|
||||
tuple_list!(
|
||||
|
@ -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 power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
||||
|
@ -6,10 +6,7 @@ use std::ptr;
|
||||
use std::{env, path::PathBuf};
|
||||
|
||||
use libafl::{
|
||||
corpus::{
|
||||
minimizer::{CorpusMinimizer, StdCorpusMinimizer},
|
||||
Corpus, InMemoryCorpus, OnDiskCorpus,
|
||||
},
|
||||
corpus::{minimizer::StdCorpusMinimizer, Corpus, InMemoryCorpus, OnDiskCorpus},
|
||||
events::{setup_restarting_mgr_std, EventConfig, EventFirer, EventRestarter, LogSeverity},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
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 power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
||||
|
@ -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 power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
||||
|
@ -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 power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, BytesInput, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
||||
|
@ -128,7 +128,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// Setup a lain mutator with a mutational stage
|
||||
let mutator = LainMutator::new();
|
||||
|
||||
let power = StdPowerMutationalStage::new(mutator);
|
||||
let power: StdPowerMutationalStage<_, _, PacketData, _, _> =
|
||||
StdPowerMutationalStage::new(mutator);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use libafl::{
|
||||
corpus::Testcase,
|
||||
corpus::{Corpus, Testcase},
|
||||
events::EventFirer,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, MapIndexesMetadata},
|
||||
@ -22,11 +22,14 @@ pub struct PacketLenMetadata {
|
||||
|
||||
pub struct PacketLenTestcaseScore {}
|
||||
|
||||
impl<S> TestcaseScore<PacketData, S> for PacketLenTestcaseScore
|
||||
impl<S> TestcaseScore<S> for PacketLenTestcaseScore
|
||||
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
|
||||
.metadata_map()
|
||||
.get::<PacketLenMetadata>()
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId,
|
||||
HasTestcase, Testcase,
|
||||
},
|
||||
inputs::{Input, UsesInput},
|
||||
inputs::Input,
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -20,23 +20,12 @@ use crate::{
|
||||
/// The eviction policy is FIFO.
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct CachedOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct CachedOnDiskCorpus<I> {
|
||||
inner: InMemoryOnDiskCorpus<I>,
|
||||
cached_indexes: RefCell<VecDeque<CorpusId>>,
|
||||
cache_max_len: usize,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for CachedOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> CachedOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
@ -71,6 +60,8 @@ impl<I> Corpus for CachedOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
|
||||
/// Returns the number of all enabled entries
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
@ -193,22 +184,16 @@ impl<I> HasTestcase for CachedOnDiskCorpus<I>
|
||||
where
|
||||
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())
|
||||
}
|
||||
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
id: CorpusId,
|
||||
) -> Result<core::cell::RefMut<Testcase<Self::Input>>, Error> {
|
||||
fn testcase_mut(&self, id: CorpusId) -> Result<core::cell::RefMut<Testcase<I>>, Error> {
|
||||
Ok(self.get(id)?.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> CachedOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> CachedOnDiskCorpus<I> {
|
||||
/// Creates the [`CachedOnDiskCorpus`].
|
||||
///
|
||||
/// This corpus stores (and reads) all testcases to/from disk
|
||||
|
@ -8,18 +8,13 @@ use serde::{Deserialize, Serialize};
|
||||
use super::HasTestcase;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
inputs::{Input, UsesInput},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Keep track of the stored `Testcase` and the siblings ids (insertion order)
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct TestcaseStorageItem<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct TestcaseStorageItem<I> {
|
||||
/// The stored testcase
|
||||
pub testcase: RefCell<Testcase<I>>,
|
||||
/// 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`)
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct TestcaseStorageMap<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct TestcaseStorageMap<I> {
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
/// A map of `CorpusId` to `TestcaseStorageItem`
|
||||
pub map: hashbrown::HashMap<CorpusId, TestcaseStorageItem<I>>,
|
||||
@ -51,10 +42,7 @@ where
|
||||
last_id: Option<CorpusId>,
|
||||
}
|
||||
|
||||
impl<I> TestcaseStorageMap<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> TestcaseStorageMap<I> {
|
||||
/// Insert a key in the keys set
|
||||
fn insert_key(&mut self, id: CorpusId) {
|
||||
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
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct TestcaseStorage<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct TestcaseStorage<I> {
|
||||
/// The map in which enabled testcases are stored
|
||||
pub enabled: TestcaseStorageMap<I>,
|
||||
/// The map in which disabled testcases are stored
|
||||
@ -248,17 +232,7 @@ where
|
||||
progressive_id: usize,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for TestcaseStorage<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> TestcaseStorage<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> TestcaseStorage<I> {
|
||||
/// Insert a testcase assigning a `CorpusId` to it
|
||||
pub fn insert(&mut self, testcase: RefCell<Testcase<I>>) -> CorpusId {
|
||||
self.insert_inner(testcase, false)
|
||||
@ -335,26 +309,14 @@ where
|
||||
|
||||
/// A corpus handling all in memory.
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct InMemoryCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct InMemoryCorpus<I> {
|
||||
storage: TestcaseStorage<I>,
|
||||
current: Option<CorpusId>,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for InMemoryCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> Corpus for InMemoryCorpus<I> {
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> Corpus for InMemoryCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
/// Returns the number of all enabled entries
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
@ -492,29 +454,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> HasTestcase for InMemoryCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> HasTestcase for InMemoryCorpus<I> {
|
||||
fn testcase(
|
||||
&self,
|
||||
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())
|
||||
}
|
||||
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> InMemoryCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> InMemoryCorpus<I> {
|
||||
/// 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.
|
||||
#[must_use]
|
||||
|
@ -24,7 +24,7 @@ use super::{
|
||||
};
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase},
|
||||
inputs::{Input, UsesInput},
|
||||
inputs::Input,
|
||||
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.
|
||||
#[cfg(feature = "std")]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct InMemoryOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct InMemoryOnDiskCorpus<I> {
|
||||
inner: InMemoryCorpus<I>,
|
||||
dir_path: PathBuf,
|
||||
meta_format: Option<OnDiskMetadataFormat>,
|
||||
@ -64,17 +60,12 @@ where
|
||||
locking: bool,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for InMemoryOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> Corpus for InMemoryOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
|
||||
/// Returns the number of all enabled entries
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
@ -228,22 +219,19 @@ where
|
||||
fn testcase(
|
||||
&self,
|
||||
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())
|
||||
}
|
||||
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> InMemoryOnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> InMemoryOnDiskCorpus<I> {
|
||||
/// Creates an [`InMemoryOnDiskCorpus`].
|
||||
///
|
||||
/// 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(|| {
|
||||
// TODO walk entry metadata to ask for pieces of filename (e.g. :havoc in AFL)
|
||||
testcase.input().as_ref().unwrap().generate_name(Some(id))
|
||||
|
@ -24,28 +24,6 @@ use crate::{
|
||||
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`.
|
||||
///
|
||||
/// 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
|
||||
E: UsesState,
|
||||
E::State: HasCorpus + HasMetadata,
|
||||
TS: TestcaseScore<E::Input, E::State>,
|
||||
TS: TestcaseScore<E::State>,
|
||||
C: Named,
|
||||
{
|
||||
/// 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
|
||||
E: UsesState,
|
||||
for<'a> O: MapObserver<Entry = T> + AsIter<'a, Item = T>,
|
||||
C: AsRef<O>,
|
||||
E::State: HasMetadata + HasCorpus + HasExecutions,
|
||||
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>,
|
||||
T: Copy + Hash + Eq,
|
||||
TS: TestcaseScore<E::Input, E::State>,
|
||||
TS: TestcaseScore<E::State>,
|
||||
{
|
||||
/// Do the minimization
|
||||
#[allow(clippy::too_many_lines)]
|
||||
fn minimize<CS, EM, Z>(
|
||||
pub fn minimize<CS, EM, Z>(
|
||||
&self,
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut E,
|
||||
|
@ -31,7 +31,7 @@ pub use minimizer::*;
|
||||
pub use nop::NopCorpus;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{inputs::UsesInput, Error};
|
||||
use crate::Error;
|
||||
|
||||
/// An abstraction for the index that identify a testcase in the corpus
|
||||
#[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
|
||||
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
|
||||
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>;
|
||||
|
||||
/// 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();
|
||||
Ok(testcase.load_input(self)?.clone())
|
||||
}
|
||||
|
@ -5,29 +5,18 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
inputs::{Input, UsesInput},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A corpus which does not store any [`Testcase`]s.
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct NopCorpus<I> {
|
||||
empty: Option<CorpusId>,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for NopCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> Corpus for NopCorpus<I> {
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> Corpus for NopCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
/// Returns the number of all enabled entries
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
@ -142,10 +131,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> NopCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> NopCorpus<I> {
|
||||
/// Creates a new [`NopCorpus`].
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
|
@ -6,7 +6,10 @@
|
||||
//! which stores a certain number of [`Testcase`]s in memory and removes additional ones in a FIFO manner.
|
||||
|
||||
use alloc::string::String;
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
use core::{
|
||||
cell::{Ref, RefCell, RefMut},
|
||||
time::Duration,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use libafl_bolts::serdeany::SerdeAnyMap;
|
||||
@ -14,7 +17,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase},
|
||||
inputs::{Input, UsesInput},
|
||||
inputs::Input,
|
||||
Error,
|
||||
};
|
||||
|
||||
@ -49,28 +52,18 @@ pub struct OnDiskMetadata<'a> {
|
||||
///
|
||||
/// Metadata is written to a `.<filename>.metadata` file in the same folder by default.
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||
pub struct OnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub struct OnDiskCorpus<I> {
|
||||
/// The root directory backing this corpus
|
||||
dir_path: PathBuf,
|
||||
/// We wrapp a cached corpus and set its size to 1.
|
||||
inner: CachedOnDiskCorpus<I>,
|
||||
}
|
||||
|
||||
impl<I> UsesInput for OnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
}
|
||||
|
||||
impl<I> Corpus for OnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
type Input = I;
|
||||
/// Returns the number of all enabled entries
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
@ -188,25 +181,16 @@ impl<I> HasTestcase for OnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
fn testcase(
|
||||
&self,
|
||||
id: CorpusId,
|
||||
) -> Result<core::cell::Ref<Testcase<<Self as UsesInput>::Input>>, Error> {
|
||||
fn testcase(&self, id: CorpusId) -> Result<Ref<Testcase<I>>, Error> {
|
||||
Ok(self.get(id)?.borrow())
|
||||
}
|
||||
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
id: CorpusId,
|
||||
) -> Result<core::cell::RefMut<Testcase<<Self as UsesInput>::Input>>, Error> {
|
||||
fn testcase_mut(&self, id: CorpusId) -> Result<RefMut<Testcase<I>>, Error> {
|
||||
Ok(self.get(id)?.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> OnDiskCorpus<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
impl<I> OnDiskCorpus<I> {
|
||||
/// Creates an [`OnDiskCorpus`].
|
||||
///
|
||||
/// This corpus stores all testcases to disk.
|
||||
|
@ -15,21 +15,24 @@ use libafl_bolts::{serdeany::SerdeAnyMap, HasLen};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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`].
|
||||
/// 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`].
|
||||
/// 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`].
|
||||
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
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
|
||||
|
@ -28,11 +28,12 @@ use crate::executors::hooks::unix::unix_signal_handler;
|
||||
#[cfg(windows)]
|
||||
use crate::state::State;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers},
|
||||
feedbacks::Feedback,
|
||||
inputs::UsesInput,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
Error, HasObjective,
|
||||
};
|
||||
/// The inmem executor's handlers.
|
||||
@ -236,6 +237,8 @@ where
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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
|
||||
// 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>,
|
||||
E::State: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
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;
|
||||
#[cfg(feature = "std")]
|
||||
|
@ -9,6 +9,7 @@ pub mod unix_signal_handler {
|
||||
use libc::siginfo_t;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
common_signals,
|
||||
@ -19,7 +20,7 @@ pub mod unix_signal_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::{Input, UsesInput},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr = unsafe fn(
|
||||
@ -80,6 +81,8 @@ pub mod unix_signal_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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();
|
||||
panic::set_hook(Box::new(move |panic_info| unsafe {
|
||||
@ -127,6 +130,8 @@ pub mod unix_signal_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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
|
||||
if !data.executor_ptr.is_null()
|
||||
@ -182,6 +187,8 @@ pub mod unix_signal_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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"))]
|
||||
let _context = _context.map(|p| {
|
||||
|
@ -12,6 +12,7 @@ pub mod windows_asan_handler {
|
||||
};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor,
|
||||
@ -20,7 +21,7 @@ pub mod windows_asan_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::UsesInput,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
};
|
||||
|
||||
/// # Safety
|
||||
@ -32,6 +33,8 @@ pub mod windows_asan_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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);
|
||||
(*data).set_in_handler(true);
|
||||
@ -125,6 +128,7 @@ pub mod windows_exception_handler {
|
||||
};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE},
|
||||
@ -134,7 +138,7 @@ pub mod windows_exception_handler {
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::{Input, UsesInput},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||
};
|
||||
|
||||
pub(crate) type HandlerFuncPtr =
|
||||
@ -180,6 +184,8 @@ pub mod windows_exception_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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();
|
||||
panic::set_hook(Box::new(move |panic_info| unsafe {
|
||||
@ -240,6 +246,8 @@ pub mod windows_exception_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: State + HasExecutions + HasSolutions + HasCorpus,
|
||||
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 =
|
||||
&mut *(global_state as *mut InProcessExecutorHandlerData);
|
||||
@ -310,6 +318,8 @@ pub mod windows_exception_handler {
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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?
|
||||
if data.ptp_timer.is_some() {
|
||||
|
@ -16,6 +16,7 @@ use crate::executors::hooks::inprocess::HasTimeout;
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
use crate::executors::hooks::inprocess::HasTimeout;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::{
|
||||
@ -178,6 +179,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks,
|
||||
@ -205,6 +208,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -235,6 +240,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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 mut hooks = tuple_list!(default).merge(user_hooks);
|
||||
|
@ -168,6 +168,8 @@ where
|
||||
H: FnMut(&S::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S>,
|
||||
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)
|
||||
pub fn new<EM, OF, Z>(
|
||||
@ -211,6 +213,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
tuple_list!(),
|
||||
@ -250,6 +254,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
tuple_list!(),
|
||||
@ -275,6 +281,8 @@ where
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
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)
|
||||
pub fn generic<EM, OF, Z>(
|
||||
@ -320,6 +328,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -355,6 +365,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, timeout,
|
||||
@ -431,7 +443,7 @@ where
|
||||
pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
executor: &mut E,
|
||||
state: &mut E::State,
|
||||
input: &<E::State as UsesInput>::Input,
|
||||
input: &E::Input,
|
||||
fuzzer: &mut Z,
|
||||
event_mgr: &mut EM,
|
||||
exitkind: ExitKind,
|
||||
@ -439,8 +451,9 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
||||
E: HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
|
||||
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();
|
||||
|
||||
@ -500,10 +513,11 @@ where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
|
||||
Z: HasObjective<Objective = OF, State = E::State>
|
||||
+ HasScheduler<State = E::State>
|
||||
+ ExecutionProcessor,
|
||||
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
|
||||
{
|
||||
let data = addr_of_mut!(GLOBAL_STATE);
|
||||
let in_handler = (*data).set_in_handler(true);
|
||||
|
@ -11,6 +11,7 @@ use core::{
|
||||
use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
|
||||
@ -157,6 +158,8 @@ where
|
||||
H: FnMut(&mut ES, &mut S, &<S as UsesInput>::Input) -> ExitKind + ?Sized,
|
||||
OT: ObserversTuple<S>,
|
||||
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)
|
||||
pub fn new<EM, OF, Z>(
|
||||
@ -203,6 +206,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
tuple_list!(),
|
||||
@ -244,6 +249,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
tuple_list!(),
|
||||
@ -289,6 +296,8 @@ where
|
||||
HT: ExecutorHooksTuple<S>,
|
||||
OT: ObserversTuple<S>,
|
||||
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)
|
||||
pub fn generic<EM, OF, Z>(
|
||||
@ -336,6 +345,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
|
||||
@ -373,6 +384,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: State,
|
||||
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>(
|
||||
user_hooks, observers, fuzzer, state, event_mgr, timeout,
|
||||
|
@ -82,7 +82,8 @@ impl<'a, S> Named for NautilusFeedback<'a, S> {
|
||||
|
||||
impl<'a, S> Feedback<S> for NautilusFeedback<'a, S>
|
||||
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)]
|
||||
fn is_interesting<EM, OT>(
|
||||
|
@ -372,13 +372,9 @@ where
|
||||
CS: Scheduler<S::Input, S>,
|
||||
F: Feedback<S>,
|
||||
OF: Feedback<S>,
|
||||
S: HasCorpus
|
||||
+ HasSolutions
|
||||
+ HasExecutions
|
||||
+ HasCorpus
|
||||
+ HasCurrentTestcase<S::Input>
|
||||
+ HasCurrentCorpusId
|
||||
+ State,
|
||||
S: HasCorpus + HasSolutions + HasExecutions + HasCorpus + HasCurrentCorpusId + State,
|
||||
S::Corpus: Corpus<Input = S::Input>, //delete me
|
||||
S::Solutions: Corpus<Input = S::Input>, //delete me
|
||||
{
|
||||
fn check_results<EM, OT>(
|
||||
&mut self,
|
||||
@ -535,7 +531,7 @@ where
|
||||
&mut self,
|
||||
state: &mut Self::State,
|
||||
manager: &mut EM,
|
||||
input: &<Self::State as UsesInput>::Input,
|
||||
input: &S::Input,
|
||||
exec_res: &ExecuteInputResult,
|
||||
observers: &OT,
|
||||
) -> Result<Option<CorpusId>, Error>
|
||||
@ -596,6 +592,8 @@ where
|
||||
F: Feedback<S>,
|
||||
OF: Feedback<S>,
|
||||
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
|
||||
#[inline]
|
||||
@ -629,6 +627,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
OT: ObserversTuple<S> + Serialize + DeserializeOwned,
|
||||
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
|
||||
#[inline]
|
||||
@ -765,8 +765,8 @@ where
|
||||
S: HasExecutions
|
||||
+ HasMetadata
|
||||
+ HasCorpus
|
||||
+ HasTestcase
|
||||
+ HasLastReportTime
|
||||
+ HasTestcase
|
||||
+ HasCurrentCorpusId
|
||||
+ HasCurrentStageId
|
||||
+ State,
|
||||
|
@ -34,10 +34,7 @@ pub struct Automaton {
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Generates random inputs from a grammar automaton
|
||||
pub struct GramatronGenerator<'a, S>
|
||||
where
|
||||
S: HasRand,
|
||||
{
|
||||
pub struct GramatronGenerator<'a, S> {
|
||||
automaton: &'a Automaton,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
|
@ -5,11 +5,7 @@ use core::marker::PhantomData;
|
||||
|
||||
use libafl_bolts::rands::Rand;
|
||||
|
||||
use crate::{
|
||||
inputs::{bytes::BytesInput, Input},
|
||||
state::HasRand,
|
||||
Error,
|
||||
};
|
||||
use crate::{inputs::bytes::BytesInput, state::HasRand, Error};
|
||||
|
||||
pub mod gramatron;
|
||||
pub use gramatron::*;
|
||||
@ -20,10 +16,7 @@ pub mod nautilus;
|
||||
pub use nautilus::*;
|
||||
|
||||
/// Generators can generate ranges of bytes.
|
||||
pub trait Generator<I, S>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub trait Generator<I, S> {
|
||||
/// Generate a new input
|
||||
fn generate(&mut self, state: &mut S) -> Result<I, Error>;
|
||||
}
|
||||
@ -35,7 +28,6 @@ where
|
||||
impl<T, I, S> Generator<I, S> for T
|
||||
where
|
||||
T: Iterator<Item = I>,
|
||||
I: Input,
|
||||
{
|
||||
fn generate(&mut self, _state: &mut S) -> Result<I, Error> {
|
||||
match self.next() {
|
||||
@ -49,21 +41,13 @@ where
|
||||
|
||||
/// An [`Iterator`] built from a [`Generator`].
|
||||
#[derive(Debug)]
|
||||
pub struct GeneratorIter<'a, I, S, G>
|
||||
where
|
||||
I: Input,
|
||||
G: Generator<I, S>,
|
||||
{
|
||||
pub struct GeneratorIter<'a, I, S, G> {
|
||||
gen: G,
|
||||
state: &'a mut S,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<'a, I, S, G> GeneratorIter<'a, I, S, G>
|
||||
where
|
||||
I: Input,
|
||||
G: Generator<I, S>,
|
||||
{
|
||||
impl<'a, I, S, G> GeneratorIter<'a, I, S, G> {
|
||||
/// Create a new [`GeneratorIter`]
|
||||
pub fn new(gen: G, state: &'a mut S) -> Self {
|
||||
Self {
|
||||
@ -76,7 +60,6 @@ where
|
||||
|
||||
impl<'a, I, S, G> Iterator for GeneratorIter<'a, I, S, G>
|
||||
where
|
||||
I: Input,
|
||||
G: Generator<I, S>,
|
||||
{
|
||||
type Item = I;
|
||||
@ -88,10 +71,7 @@ where
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Generates random bytes
|
||||
pub struct RandBytesGenerator<S>
|
||||
where
|
||||
S: HasRand,
|
||||
{
|
||||
pub struct RandBytesGenerator<S> {
|
||||
max_size: usize,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
@ -112,10 +92,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> RandBytesGenerator<S>
|
||||
where
|
||||
S: HasRand,
|
||||
{
|
||||
impl<S> RandBytesGenerator<S> {
|
||||
/// Returns a new [`RandBytesGenerator`], generating up to `max_size` random bytes.
|
||||
#[must_use]
|
||||
pub fn new(max_size: usize) -> Self {
|
||||
@ -128,10 +105,7 @@ where
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Generates random printable characters
|
||||
pub struct RandPrintablesGenerator<S>
|
||||
where
|
||||
S: HasRand,
|
||||
{
|
||||
pub struct RandPrintablesGenerator<S> {
|
||||
max_size: usize,
|
||||
phantom: PhantomData<S>,
|
||||
}
|
||||
@ -153,10 +127,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> RandPrintablesGenerator<S>
|
||||
where
|
||||
S: HasRand,
|
||||
{
|
||||
impl<S> RandPrintablesGenerator<S> {
|
||||
/// Creates a new [`RandPrintablesGenerator`], generating up to `max_size` random printable characters.
|
||||
#[must_use]
|
||||
pub fn new(max_size: usize) -> Self {
|
||||
|
@ -135,7 +135,10 @@ mod tests {
|
||||
|
||||
#[cfg(miri)]
|
||||
use libafl_bolts::serdeany::RegistryBuilder;
|
||||
use libafl_bolts::{rands::StdRand, tuples::tuple_list};
|
||||
use libafl_bolts::{
|
||||
rands::{RomuDuoJrRand, StdRand},
|
||||
tuples::tuple_list,
|
||||
};
|
||||
|
||||
#[cfg(miri)]
|
||||
use crate::stages::ExecutionCountRestartHelperMetadata;
|
||||
@ -221,7 +224,15 @@ mod tests {
|
||||
InMemoryCorpus<BytesInput>,
|
||||
StdRand,
|
||||
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());
|
||||
|
||||
let corpus_serialized = postcard::to_allocvec(state.corpus()).unwrap();
|
||||
|
@ -10,7 +10,7 @@ use libafl_bolts::{
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
inputs::{EncodedInput, UsesInput},
|
||||
inputs::EncodedInput,
|
||||
mutators::{
|
||||
mutations::{buffer_copy, buffer_self_copy, ARITH_MAX},
|
||||
MutationResult, Mutator, Named,
|
||||
@ -285,9 +285,10 @@ impl EncodedCopyMutator {
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EncodedCrossoverInsertMutator;
|
||||
|
||||
impl<S> Mutator<S::Input, S> for EncodedCrossoverInsertMutator
|
||||
impl<S> Mutator<EncodedInput, S> for EncodedCrossoverInsertMutator
|
||||
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> {
|
||||
let size = input.codes().len();
|
||||
@ -355,9 +356,10 @@ impl EncodedCrossoverInsertMutator {
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EncodedCrossoverReplaceMutator;
|
||||
|
||||
impl<S> Mutator<S::Input, S> for EncodedCrossoverReplaceMutator
|
||||
impl<S> Mutator<EncodedInput, S> for EncodedCrossoverReplaceMutator
|
||||
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> {
|
||||
let size = input.codes().len();
|
||||
|
@ -12,7 +12,7 @@ use libafl_bolts::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, HasTestcase},
|
||||
corpus::Corpus,
|
||||
generators::GramatronGenerator,
|
||||
inputs::{GramatronInput, Terminal},
|
||||
mutators::{MutationResult, Mutator},
|
||||
@ -105,9 +105,10 @@ impl GramatronIdxMapMetadata {
|
||||
#[derive(Default, Debug)]
|
||||
pub struct GramatronSpliceMutator;
|
||||
|
||||
impl<S> Mutator<S::Input, S> for GramatronSpliceMutator
|
||||
impl<S> Mutator<GramatronInput, S> for GramatronSpliceMutator
|
||||
where
|
||||
S: HasRand + HasCorpus<Input = GramatronInput> + HasMetadata + HasTestcase,
|
||||
S: HasRand + HasCorpus + HasMetadata,
|
||||
S::Corpus: Corpus<Input = GramatronInput>,
|
||||
{
|
||||
fn mutate(
|
||||
&mut self,
|
||||
|
@ -49,8 +49,7 @@ pub type HavocMutationsNoCrossoverType = tuple_list_type!(
|
||||
);
|
||||
|
||||
/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations
|
||||
pub type HavocCrossoverType<I> =
|
||||
tuple_list_type!(CrossoverInsertMutator<I>, CrossoverReplaceMutator<I>);
|
||||
pub type HavocCrossoverType = tuple_list_type!(CrossoverInsertMutator, CrossoverReplaceMutator);
|
||||
|
||||
/// 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!(
|
||||
@ -59,7 +58,7 @@ pub type MappedHavocCrossoverType<F, O> = tuple_list_type!(
|
||||
);
|
||||
|
||||
/// Tuple type of the mutations that compose the Havoc mutator
|
||||
pub type HavocMutationsType<I> = tuple_list_type!(
|
||||
pub type HavocMutationsType = tuple_list_type!(
|
||||
BitFlipMutator,
|
||||
ByteFlipMutator,
|
||||
ByteIncMutator,
|
||||
@ -85,8 +84,8 @@ pub type HavocMutationsType<I> = tuple_list_type!(
|
||||
BytesCopyMutator,
|
||||
BytesInsertCopyMutator,
|
||||
BytesSwapMutator,
|
||||
CrossoverInsertMutator<I>,
|
||||
CrossoverReplaceMutator<I>,
|
||||
CrossoverInsertMutator,
|
||||
CrossoverReplaceMutator,
|
||||
);
|
||||
|
||||
/// 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
|
||||
#[must_use]
|
||||
pub fn havoc_crossover<I>() -> HavocCrossoverType<I> {
|
||||
pub fn havoc_crossover() -> HavocCrossoverType {
|
||||
tuple_list!(
|
||||
CrossoverInsertMutator::new(),
|
||||
CrossoverReplaceMutator::new(),
|
||||
@ -228,7 +227,7 @@ where
|
||||
|
||||
/// Get the mutations that compose the Havoc mutator
|
||||
#[must_use]
|
||||
pub fn havoc_mutations<I>() -> HavocMutationsType<I> {
|
||||
pub fn havoc_mutations() -> HavocMutationsType {
|
||||
havoc_mutations_no_crossover().merge(havoc_crossover())
|
||||
}
|
||||
|
||||
|
@ -161,12 +161,6 @@ pub trait MutatorsTuple<I, S>: HasLen {
|
||||
|
||||
corpus_id: Option<CorpusId>,
|
||||
) -> 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 () {
|
||||
@ -203,16 +197,6 @@ impl<I, S> MutatorsTuple<I, S> for () {
|
||||
) -> Result<(), Error> {
|
||||
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)
|
||||
@ -263,18 +247,6 @@ where
|
||||
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)
|
||||
@ -329,14 +301,6 @@ where
|
||||
) -> Result<(), Error> {
|
||||
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,)
|
||||
@ -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."))?;
|
||||
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>>> {
|
||||
|
@ -3,13 +3,11 @@
|
||||
//! 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>
|
||||
use alloc::{borrow::Cow, string::ToString, vec::Vec};
|
||||
use core::{
|
||||
fmt::{self, Debug},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use core::fmt::{self, Debug};
|
||||
|
||||
use libafl_bolts::{
|
||||
rands::{Rand, StdRand},
|
||||
tuples::NamedTuple,
|
||||
Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -363,35 +361,16 @@ pub enum MOptMode {
|
||||
|
||||
/// This is the main struct of `MOpt`, an `AFL` mutator.
|
||||
/// See the original `MOpt` implementation in <https://github.com/puppet-meteor/MOpt-AFL>
|
||||
pub struct StdMOptMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
{
|
||||
#[derive(Debug)]
|
||||
pub struct StdMOptMutator<MT> {
|
||||
name: Cow<'static, str>,
|
||||
mode: MOptMode,
|
||||
finds_before: usize,
|
||||
mutations: MT,
|
||||
max_stack_pow: usize,
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
impl<I, MT, S> Debug for StdMOptMutator<I, MT, S>
|
||||
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>
|
||||
impl<I, MT, S> Mutator<I, S> for StdMOptMutator<MT>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
@ -516,21 +495,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> StdMOptMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
{
|
||||
impl<MT> StdMOptMutator<MT> {
|
||||
/// Create a new [`StdMOptMutator`].
|
||||
pub fn new(
|
||||
pub fn new<I, S>(
|
||||
state: &mut S,
|
||||
mutations: MT,
|
||||
max_stack_pow: usize,
|
||||
swarm_num: usize,
|
||||
) -> Result<Self, Error> {
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
S: HasMetadata + HasRand,
|
||||
MT: NamedTuple,
|
||||
{
|
||||
if !state.has_metadata::<MOpt>() {
|
||||
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 {
|
||||
name: Cow::from(format!("StdMOptMutator[{}]", mutations.names().join(","))),
|
||||
@ -538,10 +517,13 @@ where
|
||||
finds_before: 0,
|
||||
mutations,
|
||||
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 mopt = state.metadata_map_mut().get_mut::<MOpt>().unwrap();
|
||||
for i in 0..mopt.operator_num {
|
||||
@ -564,7 +546,11 @@ where
|
||||
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 swarm_now;
|
||||
{
|
||||
@ -595,11 +581,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> ComposedByMutations<I, MT, S> for StdMOptMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
{
|
||||
impl<MT> ComposedByMutations for StdMOptMutator<MT> {
|
||||
type Mutations = MT;
|
||||
|
||||
/// Get the mutations
|
||||
#[inline]
|
||||
fn mutations(&self) -> &MT {
|
||||
@ -613,17 +597,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> Named for StdMOptMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
{
|
||||
impl<MT> Named for StdMOptMutator<MT> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata + HasCorpus + HasSolutions,
|
||||
|
@ -114,10 +114,11 @@ impl_default_multipart!(
|
||||
I2SRandReplace,
|
||||
);
|
||||
|
||||
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator<I>
|
||||
impl<I, S> Mutator<MultipartInput<I>, S> for CrossoverInsertMutator
|
||||
where
|
||||
S: HasCorpus<Input = MultipartInput<I>> + HasMaxSize + HasRand,
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: Input + HasMutatorBytes,
|
||||
S::Corpus: Corpus<Input = MultipartInput<I>>,
|
||||
{
|
||||
fn mutate(
|
||||
&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
|
||||
S: HasCorpus<Input = MultipartInput<I>> + HasMaxSize + HasRand,
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: Input + HasMutatorBytes,
|
||||
S::Corpus: Corpus<Input = MultipartInput<I>>,
|
||||
{
|
||||
fn mutate(
|
||||
&mut self,
|
||||
|
@ -10,7 +10,7 @@ use libafl_bolts::{rands::Rand, Named};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
inputs::{HasMutatorBytes, UsesInput},
|
||||
inputs::HasMutatorBytes,
|
||||
mutators::{MutationResult, Mutator},
|
||||
random_corpus_id_with_disabled,
|
||||
state::{HasCorpus, HasMaxSize, HasRand},
|
||||
@ -1025,18 +1025,19 @@ impl BytesSwapMutator {
|
||||
|
||||
/// Crossover insert mutation for inputs with a bytes vector
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CrossoverInsertMutator<I> {
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
pub struct CrossoverInsertMutator;
|
||||
|
||||
impl<I: HasMutatorBytes> CrossoverInsertMutator<I> {
|
||||
pub(crate) fn crossover_insert(
|
||||
impl CrossoverInsertMutator {
|
||||
pub(crate) fn crossover_insert<I>(
|
||||
input: &mut I,
|
||||
size: usize,
|
||||
target: usize,
|
||||
range: Range<usize>,
|
||||
other: &[u8],
|
||||
) -> MutationResult {
|
||||
) -> MutationResult
|
||||
where
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
input.resize(size + range.len(), 0);
|
||||
unsafe {
|
||||
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
|
||||
S: HasCorpus + HasRand + HasMaxSize,
|
||||
S::Input: HasMutatorBytes,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
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> {
|
||||
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverInsertMutator");
|
||||
&NAME
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> CrossoverInsertMutator<I> {
|
||||
impl CrossoverInsertMutator {
|
||||
/// Creates a new [`CrossoverInsertMutator`].
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
}
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Crossover replace mutation for inputs with a bytes vector
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CrossoverReplaceMutator<I> {
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
pub struct CrossoverReplaceMutator;
|
||||
|
||||
impl<I: HasMutatorBytes> CrossoverReplaceMutator<I> {
|
||||
pub(crate) fn crossover_replace(
|
||||
impl CrossoverReplaceMutator {
|
||||
pub(crate) fn crossover_replace<I>(
|
||||
input: &mut I,
|
||||
target: usize,
|
||||
range: Range<usize>,
|
||||
other: &[u8],
|
||||
) -> MutationResult {
|
||||
) -> MutationResult
|
||||
where
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
unsafe {
|
||||
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
|
||||
S: HasCorpus + HasRand,
|
||||
S::Input: HasMutatorBytes,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
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> {
|
||||
static NAME: Cow<'static, str> = Cow::Borrowed("CrossoverReplaceMutator");
|
||||
&NAME
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> CrossoverReplaceMutator<I> {
|
||||
impl CrossoverReplaceMutator {
|
||||
/// Creates a new [`CrossoverReplaceMutator`].
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
}
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1244,11 +1242,11 @@ impl<F, O> MappedCrossoverInsertMutator<F, O> {
|
||||
|
||||
impl<S, F, I, O> Mutator<I, S> for MappedCrossoverInsertMutator<F, O>
|
||||
where
|
||||
S: HasCorpus + HasMaxSize + HasRand + UsesInput,
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: HasMutatorBytes,
|
||||
for<'a> O: 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> {
|
||||
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>
|
||||
where
|
||||
S: HasCorpus + HasMaxSize + HasRand + UsesInput,
|
||||
S: HasCorpus + HasMaxSize + HasRand,
|
||||
I: HasMutatorBytes,
|
||||
O: 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> {
|
||||
let size = input.bytes().len();
|
||||
@ -1404,13 +1402,14 @@ fn locate_diffs(this: &[u8], other: &[u8]) -> (i64, i64) {
|
||||
#[derive(Debug, Default)]
|
||||
pub struct SpliceMutator;
|
||||
|
||||
impl<S> Mutator<S::Input, S> for SpliceMutator
|
||||
impl<I, S> Mutator<I, S> for SpliceMutator
|
||||
where
|
||||
S: HasCorpus + HasRand,
|
||||
S::Input: HasMutatorBytes,
|
||||
<S::Corpus as Corpus>::Input: HasMutatorBytes,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
#[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());
|
||||
// We don't want to use the testcase we're already using for splicing
|
||||
if let Some(cur) = state.corpus().current() {
|
||||
|
@ -162,7 +162,7 @@ impl Debug for NautilusSpliceMutator<'_> {
|
||||
|
||||
impl<S> Mutator<NautilusInput, S> for NautilusSpliceMutator<'_>
|
||||
where
|
||||
S: HasCorpus<Input = NautilusInput> + HasMetadata + HasRand,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
fn mutate(
|
||||
&mut self,
|
||||
|
@ -2,14 +2,13 @@
|
||||
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::{
|
||||
fmt::{self, Debug},
|
||||
marker::PhantomData,
|
||||
fmt::Debug,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
rands::Rand,
|
||||
tuples::{tuple_list, tuple_list_type, NamedTuple},
|
||||
tuples::{tuple_list, tuple_list_type, HasConstLen, NamedTuple},
|
||||
Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -60,21 +59,20 @@ impl LogMutationMetadata {
|
||||
}
|
||||
|
||||
/// A [`Mutator`] that composes multiple mutations into one.
|
||||
pub trait ComposedByMutations<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
{
|
||||
pub trait ComposedByMutations {
|
||||
/// The mutations of this
|
||||
type Mutations;
|
||||
/// Get the mutations
|
||||
fn mutations(&self) -> &MT;
|
||||
fn mutations(&self) -> &Self::Mutations;
|
||||
|
||||
/// 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.
|
||||
pub trait ScheduledMutator<I, MT, S>: ComposedByMutations<I, MT, S> + Mutator<I, S>
|
||||
pub trait ScheduledMutator<I, S>: ComposedByMutations + Mutator<I, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
Self::Mutations: MutatorsTuple<I, S>,
|
||||
{
|
||||
/// Compute the number of iterations used to apply stacked mutations
|
||||
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.
|
||||
pub struct StdScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
{
|
||||
#[derive(Debug)]
|
||||
pub struct StdScheduledMutator<MT> {
|
||||
name: Cow<'static, str>,
|
||||
mutations: MT,
|
||||
max_stack_pow: usize,
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
impl<I, MT, S> Debug for StdScheduledMutator<I, MT, S>
|
||||
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,
|
||||
{
|
||||
impl<MT> Named for StdScheduledMutator<MT> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
@ -146,11 +121,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> ComposedByMutations<I, MT, S> for StdScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
{
|
||||
impl<MT> ComposedByMutations for StdScheduledMutator<MT> {
|
||||
type Mutations = MT;
|
||||
/// Get the mutations
|
||||
#[inline]
|
||||
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
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
@ -181,10 +153,9 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> StdScheduledMutator<I, MT, S>
|
||||
impl<MT> StdScheduledMutator<MT>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
MT: NamedTuple,
|
||||
{
|
||||
/// Create a new [`StdScheduledMutator`] instance specifying mutations
|
||||
pub fn new(mutations: MT) -> Self {
|
||||
@ -195,7 +166,6 @@ where
|
||||
)),
|
||||
mutations,
|
||||
max_stack_pow: 7,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,7 +178,6 @@ where
|
||||
)),
|
||||
mutations,
|
||||
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`].
|
||||
pub struct LoggerScheduledMutator<I, MT, S, SM>
|
||||
where
|
||||
MT: MutatorsTuple<I, S> + NamedTuple,
|
||||
S: HasRand + HasCorpus,
|
||||
SM: ScheduledMutator<I, MT, S>,
|
||||
{
|
||||
#[derive(Debug)]
|
||||
pub struct LoggerScheduledMutator<SM> {
|
||||
name: Cow<'static, str>,
|
||||
scheduled: SM,
|
||||
mutation_log: Vec<MutationId>,
|
||||
phantom: PhantomData<(I, MT, S)>,
|
||||
}
|
||||
|
||||
impl<I, MT, S, SM> Debug for LoggerScheduledMutator<I, MT, S, 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>,
|
||||
{
|
||||
impl<SM> Named for LoggerScheduledMutator<SM> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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
|
||||
MT: MutatorsTuple<I, S> + NamedTuple,
|
||||
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> {
|
||||
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
|
||||
MT: MutatorsTuple<I, S> + NamedTuple,
|
||||
S: HasRand + HasCorpus,
|
||||
SM: ScheduledMutator<I, MT, S>,
|
||||
SM: ComposedByMutations,
|
||||
{
|
||||
type Mutations = SM::Mutations;
|
||||
#[inline]
|
||||
fn mutations(&self) -> &MT {
|
||||
fn mutations(&self) -> &SM::Mutations {
|
||||
self.scheduled.mutations()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mutations_mut(&mut self) -> &mut MT {
|
||||
fn mutations_mut(&mut self) -> &mut SM::Mutations {
|
||||
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
|
||||
MT: MutatorsTuple<I, S> + NamedTuple,
|
||||
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
|
||||
fn iterations(&self, state: &mut S, _: &I) -> u64 {
|
||||
@ -316,8 +258,11 @@ where
|
||||
|
||||
/// Get the next mutation to apply
|
||||
fn schedule(&self, state: &mut S, _: &I) -> MutationId {
|
||||
debug_assert!(MT::LEN != 0);
|
||||
state.rand_mut().below(MT::LEN).into()
|
||||
debug_assert!(<SM::Mutations as HasConstLen>::LEN != 0);
|
||||
state
|
||||
.rand_mut()
|
||||
.below(<SM::Mutations as HasConstLen>::LEN)
|
||||
.into()
|
||||
}
|
||||
|
||||
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
|
||||
MT: MutatorsTuple<I, S> + NamedTuple,
|
||||
S: HasRand + HasCorpus,
|
||||
SM: ScheduledMutator<I, MT, S>,
|
||||
SM: Named,
|
||||
{
|
||||
/// Create a new [`LoggerScheduledMutator`] instance without mutations and corpus
|
||||
/// This mutator logs all mutators.
|
||||
@ -349,7 +292,6 @@ where
|
||||
name: Cow::from(format!("LoggerScheduledMutator[{}]", scheduled.name())),
|
||||
scheduled,
|
||||
mutation_log: vec![],
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::mutators::str_decode;
|
||||
use crate::{
|
||||
corpus::{CorpusId, HasCurrentCorpusId},
|
||||
inputs::{HasMutatorBytes, UsesInput},
|
||||
inputs::HasMutatorBytes,
|
||||
mutators::{
|
||||
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
|
||||
where
|
||||
S: UsesInput + HasMetadata + HasRand + HasMaxSize,
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
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
|
||||
where
|
||||
S: UsesInput + HasMetadata + HasRand + HasMaxSize,
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
#[allow(clippy::too_many_lines)]
|
||||
@ -621,7 +621,7 @@ where
|
||||
|
||||
impl<I, S> Mutator<I, S> for I2SRandReplaceBinonly
|
||||
where
|
||||
S: UsesInput + HasMetadata + HasRand + HasMaxSize,
|
||||
S: HasMetadata + HasRand + HasMaxSize,
|
||||
I: HasMutatorBytes,
|
||||
{
|
||||
#[allow(clippy::too_many_lines)]
|
||||
@ -1294,7 +1294,7 @@ impl AFLppRedQueen {
|
||||
|
||||
impl<I, S> MultiMutator<I, S> for AFLppRedQueen
|
||||
where
|
||||
S: UsesInput + HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId,
|
||||
S: HasMetadata + HasRand + HasMaxSize + HasCorpus + HasCurrentCorpusId,
|
||||
I: HasMutatorBytes + From<Vec<u8>>,
|
||||
{
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
|
@ -4,13 +4,11 @@
|
||||
//! a specific mutator for a specified amount of iterations
|
||||
|
||||
use alloc::{borrow::Cow, vec::Vec};
|
||||
use core::{
|
||||
fmt::{self, Debug},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
|
||||
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};
|
||||
|
||||
@ -81,33 +79,14 @@ impl TuneableScheduledMutatorMetadata {
|
||||
|
||||
/// A [`Mutator`] that schedules one of the embedded mutations on each call.
|
||||
/// The index of the next mutation can be set.
|
||||
pub struct TuneableScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
{
|
||||
#[derive(Debug)]
|
||||
pub struct TuneableScheduledMutator<MT> {
|
||||
name: Cow<'static, str>,
|
||||
mutations: MT,
|
||||
max_stack_pow: usize,
|
||||
phantom: PhantomData<(I, S)>,
|
||||
}
|
||||
|
||||
impl<I, MT, S> Debug for TuneableScheduledMutator<I, MT, S>
|
||||
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>
|
||||
impl<I, MT, S> Mutator<I, S> for TuneableScheduledMutator<MT>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata,
|
||||
@ -118,11 +97,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> ComposedByMutations<I, MT, S> for TuneableScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
{
|
||||
impl<MT> ComposedByMutations for TuneableScheduledMutator<MT> {
|
||||
type Mutations = MT;
|
||||
/// Get the mutations
|
||||
#[inline]
|
||||
fn mutations(&self) -> &MT {
|
||||
@ -136,17 +112,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> Named for TuneableScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand,
|
||||
{
|
||||
impl<MT> Named for TuneableScheduledMutator<MT> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
&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
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata,
|
||||
@ -228,13 +200,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, MT, S> TuneableScheduledMutator<I, MT, S>
|
||||
where
|
||||
MT: MutatorsTuple<I, S>,
|
||||
S: HasRand + HasMetadata,
|
||||
{
|
||||
impl<MT> TuneableScheduledMutator<MT> {
|
||||
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
|
||||
pub fn new(state: &mut S, mutations: MT) -> Self {
|
||||
pub fn new<S>(state: &mut S, mutations: MT) -> Self
|
||||
where
|
||||
MT: NamedTuple,
|
||||
S: HasRand + HasMetadata,
|
||||
{
|
||||
if !state.has_metadata::<TuneableScheduledMutatorMetadata>() {
|
||||
state.add_metadata(TuneableScheduledMutatorMetadata::default());
|
||||
}
|
||||
@ -242,36 +214,22 @@ where
|
||||
name: Cow::from(format!("TuneableMutator[{}]", mutations.names().join(", "))),
|
||||
mutations,
|
||||
max_stack_pow: 7,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> TuneableScheduledMutator<(), (), S>
|
||||
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()
|
||||
}
|
||||
|
||||
impl<MT> TuneableScheduledMutator<MT> {
|
||||
/// 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
|
||||
/// will be faster than setting them individually
|
||||
/// as it internally only needs a single metadata lookup
|
||||
pub fn set_iters(state: &mut S, iters: u64) {
|
||||
let metadata = Self::metadata_mut(state);
|
||||
pub fn set_iters<S>(&self, state: &mut S, iters: u64)
|
||||
where
|
||||
S: HasMetadata,
|
||||
{
|
||||
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
|
||||
|
||||
metadata.iters = Some(iters);
|
||||
metadata.iter_probabilities_pow_cumulative.clear();
|
||||
}
|
||||
@ -285,16 +243,20 @@ where
|
||||
/// These will be applied for each call of this `mutate` function.
|
||||
///
|
||||
/// 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,
|
||||
mut iter_probabilities_pow: Vec<f32>,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
S: HasMetadata,
|
||||
{
|
||||
if iter_probabilities_pow.len() >= 32 {
|
||||
return Err(Error::illegal_argument(
|
||||
"Cannot stack more than 2^32 mutations",
|
||||
));
|
||||
}
|
||||
let metadata = Self::metadata_mut(state);
|
||||
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
|
||||
metadata.iters = None;
|
||||
|
||||
// we precalculate the cumulative probability to be faster when sampling later.
|
||||
@ -305,13 +267,19 @@ where
|
||||
}
|
||||
|
||||
/// Gets the set amount of iterations
|
||||
pub fn get_iters(state: &S) -> Option<u64> {
|
||||
let metadata = Self::metadata(state);
|
||||
pub fn get_iters<S>(&self, state: &S) -> Option<u64>
|
||||
where
|
||||
S: HasMetadata,
|
||||
{
|
||||
let metadata = TuneableScheduledMutatorMetadata::get(state).unwrap();
|
||||
metadata.iters
|
||||
}
|
||||
|
||||
/// 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();
|
||||
metadata.mutation_ids = mutations;
|
||||
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
|
||||
/// up to 1.
|
||||
/// 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,
|
||||
mut mutation_probabilities: Vec<f32>,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
S: HasMetadata,
|
||||
{
|
||||
let metadata = TuneableScheduledMutatorMetadata::get_mut(state).unwrap();
|
||||
metadata.mutation_ids.clear();
|
||||
metadata.next_id = 0.into();
|
||||
@ -336,7 +308,14 @@ where
|
||||
}
|
||||
|
||||
/// 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();
|
||||
metadata.mutation_ids = mutations;
|
||||
metadata.next_id = 0.into();
|
||||
@ -344,14 +323,23 @@ where
|
||||
}
|
||||
|
||||
/// 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();
|
||||
metadata.mutation_ids.push(mutation_id);
|
||||
}
|
||||
|
||||
/// Resets this to a randomic mutational stage
|
||||
pub fn reset(state: &mut S) {
|
||||
let metadata = Self::metadata_mut(state);
|
||||
pub fn reset<S>(self, state: &mut S)
|
||||
where
|
||||
S: HasMetadata,
|
||||
{
|
||||
let metadata = state
|
||||
.metadata_map_mut()
|
||||
.get_mut::<TuneableScheduledMutatorMetadata>()
|
||||
.unwrap();
|
||||
metadata.mutation_ids.clear();
|
||||
metadata.next_id = 0.into();
|
||||
metadata.iters = None;
|
||||
@ -417,43 +405,35 @@ mod test {
|
||||
let input = BytesInput::new(vec![42]);
|
||||
|
||||
// Basic tests over the probability distribution.
|
||||
assert!(
|
||||
TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![0.0]).is_err()
|
||||
);
|
||||
assert!(
|
||||
TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![1.0; 3]).is_err()
|
||||
);
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(
|
||||
&mut state,
|
||||
vec![-1.0, 1.0, 1.0]
|
||||
)
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![0.0])
|
||||
.is_err());
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![1.0; 3])
|
||||
.is_err());
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![-1.0, 1.0, 1.0])
|
||||
.is_err());
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![])
|
||||
.is_err());
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(&mut state, vec![]).is_err());
|
||||
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(
|
||||
&mut state,
|
||||
vec![0.0, 0.0, 1.0]
|
||||
)
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![0.0, 0.0, 1.0])
|
||||
.is_ok());
|
||||
assert_eq!(tuneable.schedule(&mut state, &input), 2.into());
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(
|
||||
&mut state,
|
||||
vec![0.0, 1.0, 0.0]
|
||||
)
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![0.0, 1.0, 0.0])
|
||||
.is_ok());
|
||||
assert_eq!(tuneable.schedule(&mut state, &input), 1.into());
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(
|
||||
&mut state,
|
||||
vec![1.0, 0.0, 0.0]
|
||||
)
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![1.0, 0.0, 0.0])
|
||||
.is_ok());
|
||||
assert_eq!(tuneable.schedule(&mut state, &input), 0.into());
|
||||
|
||||
// We should not choose a mutation with p=0.
|
||||
assert!(TuneableScheduledMutator::set_mutation_probabilities(
|
||||
&mut state,
|
||||
vec![0.5, 0.0, 0.5]
|
||||
)
|
||||
assert!(tuneable
|
||||
.set_mutation_probabilities(&mut state, vec![0.5, 0.0, 0.5])
|
||||
.is_ok());
|
||||
assert!(tuneable.schedule(&mut state, &input) != 1.into());
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use core::{
|
||||
use libafl_bolts::{rands::Rand, Error, HasLen, Named};
|
||||
|
||||
use crate::{
|
||||
corpus::{CorpusId, HasTestcase, Testcase},
|
||||
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
||||
inputs::{BytesInput, HasMutatorBytes},
|
||||
mutators::{rand_range, MutationResult, Mutator, Tokens},
|
||||
stages::{
|
||||
@ -32,7 +32,8 @@ pub type UnicodeInput = (BytesInput, UnicodeIdentificationMetadata);
|
||||
|
||||
impl<S> MutatedTransform<BytesInput, S> for UnicodeInput
|
||||
where
|
||||
S: HasCorpus<Input = BytesInput> + HasTestcase,
|
||||
S: HasCorpus + HasTestcase,
|
||||
S::Corpus: Corpus<Input = BytesInput>,
|
||||
{
|
||||
type Post = UnicodeIdentificationMetadata;
|
||||
|
||||
|
@ -110,11 +110,12 @@ pub struct CoverageAccountingScheduler<'a, 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
|
||||
CS: Scheduler<I, S>,
|
||||
S: HasCorpus<Input = I> + HasMetadata + HasRand,
|
||||
I: HasLen,
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
<S::Corpus as Corpus>::Input: HasLen,
|
||||
O: CanTrack,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
@ -122,7 +123,12 @@ where
|
||||
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
|
||||
OT: MatchName,
|
||||
{
|
||||
|
@ -79,19 +79,21 @@ pub struct MinimizerScheduler<CS, 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
|
||||
CS: RemovableScheduler<I, S> + Scheduler<I, S>,
|
||||
F: TestcaseScore<I, S>,
|
||||
CS: RemovableScheduler<<S::Corpus as Corpus>::Input, S>
|
||||
+ Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
F: TestcaseScore<S>,
|
||||
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`]
|
||||
fn on_replace(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
id: CorpusId,
|
||||
testcase: &Testcase<I>,
|
||||
testcase: &Testcase<<S::Corpus as Corpus>::Input>,
|
||||
) -> Result<(), Error> {
|
||||
self.base.on_replace(state, id, testcase)?;
|
||||
self.update_score(state, id)
|
||||
@ -102,7 +104,7 @@ where
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
id: CorpusId,
|
||||
testcase: &Option<Testcase<I>>,
|
||||
testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
self.base.on_remove(state, id, testcase)?;
|
||||
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
|
||||
CS: Scheduler<I, S>,
|
||||
F: TestcaseScore<I, S>,
|
||||
CS: Scheduler<<S::Corpus as Corpus>::Input, S>,
|
||||
F: TestcaseScore<S>,
|
||||
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
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
@ -200,7 +202,12 @@ where
|
||||
}
|
||||
|
||||
/// 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
|
||||
OT: MatchName,
|
||||
{
|
||||
@ -243,10 +250,10 @@ where
|
||||
/// Update the [`Corpus`] score using the [`MinimizerScheduler`]
|
||||
#[allow(clippy::unused_self)]
|
||||
#[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
|
||||
F: TestcaseScore<I, S>,
|
||||
S: HasCorpus<Input = I> + HasMetadata,
|
||||
F: TestcaseScore<S>,
|
||||
S: HasCorpus + HasMetadata,
|
||||
{
|
||||
// Create a new top rated meta if not existing
|
||||
if state.metadata_map().get::<TopRatedsMetadata>().is_none() {
|
||||
|
@ -215,7 +215,7 @@ pub struct RandScheduler<S> {
|
||||
|
||||
impl<I, S> Scheduler<I, S> for RandScheduler<S>
|
||||
where
|
||||
S: HasCorpus + HasRand + HasTestcase,
|
||||
S: HasCorpus + HasRand,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
// Set parent id
|
||||
|
@ -10,7 +10,6 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
inputs::Input,
|
||||
schedulers::{RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasRand},
|
||||
Error, HasMetadata,
|
||||
@ -66,11 +65,10 @@ impl<F> ProbabilitySamplingScheduler<F> {
|
||||
/// Calculate the score and store in `ProbabilityMetadata`
|
||||
#[allow(clippy::cast_precision_loss)]
|
||||
#[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
|
||||
F: TestcaseScore<I, S>,
|
||||
I: Input,
|
||||
S: HasCorpus<Input = I> + HasMetadata + HasRand,
|
||||
F: TestcaseScore<S>,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
let prob = F::compute(state, &mut *state.corpus().get(id)?.borrow_mut())?;
|
||||
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
|
||||
F: TestcaseScore<I, S>,
|
||||
I: Input,
|
||||
S: HasCorpus<Input = I> + HasMetadata + HasRand,
|
||||
F: TestcaseScore<S>,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
fn on_remove(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
id: CorpusId,
|
||||
_testcase: &Option<Testcase<I>>,
|
||||
_testcase: &Option<Testcase<<S::Corpus as Corpus>::Input>>,
|
||||
) -> Result<(), Error> {
|
||||
let meta = state
|
||||
.metadata_map_mut()
|
||||
@ -113,7 +110,7 @@ where
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
id: CorpusId,
|
||||
_prev: &Testcase<I>,
|
||||
_prev: &Testcase<<S::Corpus as Corpus>::Input>,
|
||||
) -> Result<(), Error> {
|
||||
let meta = state
|
||||
.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
|
||||
F: TestcaseScore<I, S>,
|
||||
I: Input,
|
||||
S: HasCorpus<Input = I> + HasMetadata + HasRand,
|
||||
F: TestcaseScore<S>,
|
||||
S: HasCorpus + HasMetadata + HasRand,
|
||||
{
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
let current_id = *state.corpus().current();
|
||||
@ -209,11 +205,14 @@ mod tests {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UniformDistribution {}
|
||||
|
||||
impl<I, S> TestcaseScore<I, S> for UniformDistribution
|
||||
impl<S> TestcaseScore<S> for UniformDistribution
|
||||
where
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,13 @@ use crate::{
|
||||
};
|
||||
|
||||
/// 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.
|
||||
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.
|
||||
@ -25,13 +29,16 @@ pub trait TestcaseScore<I, S> {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LenTimeMulTestcaseScore {}
|
||||
|
||||
impl<I, S> TestcaseScore<I, S> for LenTimeMulTestcaseScore
|
||||
impl<S> TestcaseScore<S> for LenTimeMulTestcaseScore
|
||||
where
|
||||
S: HasCorpus<Input = I>,
|
||||
I: HasLen,
|
||||
S: HasCorpus,
|
||||
<S::Corpus as Corpus>::Input: HasLen,
|
||||
{
|
||||
#[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()
|
||||
Ok(entry.exec_time().map_or(1, |d| d.as_millis()) as f64
|
||||
* entry.load_len(state.corpus())? as f64)
|
||||
@ -48,7 +55,7 @@ const HAVOC_MAX_MULT: f64 = 64.0;
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CorpusPowerTestcaseScore {}
|
||||
|
||||
impl<I, S> TestcaseScore<I, S> for CorpusPowerTestcaseScore
|
||||
impl<S> TestcaseScore<S> for CorpusPowerTestcaseScore
|
||||
where
|
||||
S: HasCorpus + HasMetadata,
|
||||
{
|
||||
@ -59,7 +66,10 @@ where
|
||||
clippy::cast_sign_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 psmeta = state.metadata::<SchedulerMetadata>()?;
|
||||
|
||||
let fuzz_mu = if let Some(strat) = psmeta.strat() {
|
||||
@ -267,13 +277,16 @@ where
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CorpusWeightTestcaseScore {}
|
||||
|
||||
impl<I, S> TestcaseScore<I, S> for CorpusWeightTestcaseScore
|
||||
impl<S> TestcaseScore<S> for CorpusWeightTestcaseScore
|
||||
where
|
||||
S: HasCorpus + HasMetadata,
|
||||
{
|
||||
/// Compute the `weight` used in weighted corpus entry selection algo
|
||||
#[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 psmeta = state.metadata::<SchedulerMetadata>()?;
|
||||
|
||||
|
@ -16,7 +16,6 @@ use serde::{Deserialize, Serialize};
|
||||
use super::powersched::PowerSchedule;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasTestcase, Testcase},
|
||||
inputs::Input,
|
||||
observers::MapObserver,
|
||||
random_corpus_id,
|
||||
schedulers::{
|
||||
@ -163,11 +162,10 @@ where
|
||||
clippy::cast_precision_loss,
|
||||
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
|
||||
F: TestcaseScore<I, S>,
|
||||
I: Input,
|
||||
S: HasCorpus<Input = I> + HasMetadata,
|
||||
F: TestcaseScore<S>,
|
||||
S: HasCorpus + HasMetadata,
|
||||
{
|
||||
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
|
||||
C: AsRef<O> + Named,
|
||||
F: TestcaseScore<I, S>,
|
||||
I: Input,
|
||||
F: TestcaseScore<S>,
|
||||
O: MapObserver,
|
||||
S: HasCorpus<Input = I> + HasMetadata + HasRand + HasTestcase,
|
||||
S: HasCorpus + HasMetadata + HasRand + HasTestcase,
|
||||
{
|
||||
/// Called when a [`Testcase`] is added to the corpus
|
||||
fn on_add(&mut self, state: &mut S, id: CorpusId) -> Result<(), Error> {
|
||||
@ -327,7 +324,12 @@ where
|
||||
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
|
||||
OT: MatchName,
|
||||
{
|
||||
|
@ -100,8 +100,9 @@ where
|
||||
C: AsRef<O>,
|
||||
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
|
||||
OT: ObserversTuple<Self::State>,
|
||||
Self::State: HasCorpus + HasMetadata + HasNamedMetadata + HasExecutions,
|
||||
E::State: HasCorpus + HasMetadata + HasNamedMetadata + HasExecutions + HasCurrentTestcase,
|
||||
Z: Evaluator<E, EM, State = Self::State>,
|
||||
<<E as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(
|
||||
|
@ -14,6 +14,7 @@ use libafl_bolts::{
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
events::EventFirer,
|
||||
executors::{Executor, HasObservers},
|
||||
inputs::HasMutatorBytes,
|
||||
@ -87,11 +88,12 @@ impl<C, E, EM, O, Z> Stage<E, EM, Z> for ColorizationStage<C, E, EM, O, Z>
|
||||
where
|
||||
EM: UsesState<State = Self::State> + EventFirer,
|
||||
E: HasObservers + Executor<EM, Z>,
|
||||
Self::State: HasCorpus + HasMetadata + HasRand + HasNamedMetadata,
|
||||
E::State: HasCorpus + HasMetadata + HasRand + HasNamedMetadata,
|
||||
E::Input: HasMutatorBytes,
|
||||
O: MapObserver,
|
||||
C: AsRef<O> + Named,
|
||||
Z: UsesState<State = Self::State>,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
@ -165,9 +167,10 @@ where
|
||||
O: MapObserver,
|
||||
C: AsRef<O> + Named,
|
||||
E: HasObservers + Executor<EM, Z>,
|
||||
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,
|
||||
<E as UsesState>::State: HasCorpus + HasMetadata + HasRand,
|
||||
E::Input: HasMutatorBytes,
|
||||
Z: UsesState<State = <Self as UsesState>::State>,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = E::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
|
@ -17,6 +17,7 @@ use crate::monitors::PerfFeature;
|
||||
#[cfg(all(feature = "introspection", feature = "concolic_mutation"))]
|
||||
use crate::state::HasClientPerfMonitor;
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, HasObservers},
|
||||
observers::concolic::ConcolicObserver,
|
||||
stages::{RetryCountRestartHelper, Stage, TracingStage},
|
||||
@ -62,8 +63,9 @@ where
|
||||
E: UsesState<State = Self::State>,
|
||||
EM: UsesState<State = Self::State>,
|
||||
TE: Executor<EM, Z> + HasObservers,
|
||||
Self::State: HasExecutions + HasCorpus + HasNamedMetadata,
|
||||
TE::State: HasExecutions + HasCorpus + HasNamedMetadata + HasCurrentTestcase,
|
||||
Z: UsesState<State = Self::State>,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
fn perform(
|
||||
@ -395,7 +397,9 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
Z: Evaluator<E, EM>,
|
||||
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]
|
||||
fn perform(
|
||||
|
@ -9,7 +9,6 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId},
|
||||
inputs::UsesInput,
|
||||
stages::Stage,
|
||||
state::{HasCorpus, HasRand, HasSolutions, UsesState},
|
||||
Error, HasMetadata,
|
||||
@ -46,11 +45,13 @@ where
|
||||
|
||||
impl<CB, E, EM, Z> Stage<E, EM, Z> for DumpToDiskStage<CB, EM, Z>
|
||||
where
|
||||
CB: FnMut(&<Self::State as UsesInput>::Input, &Self::State) -> Vec<u8>,
|
||||
CB: FnMut(&Self::Input, &Self::State) -> Vec<u8>,
|
||||
EM: UsesState,
|
||||
E: 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]
|
||||
fn perform(
|
||||
|
@ -73,9 +73,10 @@ where
|
||||
O: MapObserver,
|
||||
C: CanTrack + AsRef<O> + Named,
|
||||
E: Executor<EM, Z, State = Self::State> + HasObservers,
|
||||
Self::State:
|
||||
EM::State:
|
||||
UsesInput<Input = BytesInput> + HasExecutions + HasMetadata + HasCorpus + HasNamedMetadata,
|
||||
EM: UsesState,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = BytesInput>, //delete me
|
||||
Z: UsesState<State = Self::State>,
|
||||
{
|
||||
#[inline]
|
||||
|
@ -60,7 +60,8 @@ where
|
||||
impl<I, S> MutatedTransform<I, S> for I
|
||||
where
|
||||
I: Input + Clone,
|
||||
S: HasCorpus<Input = I>,
|
||||
S: HasCorpus,
|
||||
S::Corpus: Corpus<Input = I>,
|
||||
{
|
||||
type Post = ();
|
||||
|
||||
@ -85,8 +86,9 @@ where
|
||||
M: Mutator<I, Self::State>,
|
||||
EM: UsesState<State = Self::State>,
|
||||
Z: Evaluator<E, EM, State = Self::State>,
|
||||
Self::State: HasCorpus,
|
||||
Self::State: HasCorpus + HasCurrentTestcase,
|
||||
I: MutatedTransform<Self::Input, Self::State> + Clone,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>,
|
||||
{
|
||||
/// The mutator registered for this stage
|
||||
fn mutator(&self) -> &M;
|
||||
@ -171,8 +173,9 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
M: Mutator<I, Self::State>,
|
||||
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,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
/// The mutator, added to this stage
|
||||
#[inline]
|
||||
@ -216,8 +219,9 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
M: Mutator<I, Self::State>,
|
||||
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,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
@ -329,8 +333,9 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
M: MultiMutator<I, Self::State>,
|
||||
Z: Evaluator<E, EM>,
|
||||
Self::State: HasCorpus + HasRand + HasNamedMetadata,
|
||||
Z::State: HasCorpus + HasRand + HasNamedMetadata + HasCurrentTestcase,
|
||||
I: MutatedTransform<Self::Input, Self::State> + Clone,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
fn should_restart(&mut self, state: &mut Self::State) -> Result<bool, Error> {
|
||||
|
@ -9,6 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
use libafl_bolts::Named;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, HasObservers},
|
||||
fuzzer::Evaluator,
|
||||
inputs::Input,
|
||||
@ -50,12 +51,14 @@ impl<E, F, EM, I, M, Z> MutationalStage<E, EM, I, M, Z> for PowerMutationalStage
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: UsesState<State = Self::State>,
|
||||
F: TestcaseScore<I, Self::State>,
|
||||
F: TestcaseScore<Self::State>,
|
||||
I: Input,
|
||||
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>,
|
||||
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
|
||||
#[inline]
|
||||
@ -84,11 +87,13 @@ impl<E, F, EM, I, M, Z> Stage<E, EM, Z> for PowerMutationalStage<E, F, EM, I, M,
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: UsesState<State = Self::State>,
|
||||
F: TestcaseScore<I, Self::State>,
|
||||
F: TestcaseScore<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>,
|
||||
I: MutatedTransform<Self::Input, Self::State> + Clone + Input,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
@ -117,7 +122,7 @@ impl<E, F, EM, I, M, Z> PowerMutationalStage<E, F, EM, I, M, Z>
|
||||
where
|
||||
E: Executor<EM, Z> + HasObservers,
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
F: TestcaseScore<I, <Self as UsesState>::State>,
|
||||
F: TestcaseScore<<Self as UsesState>::State>,
|
||||
I: Input,
|
||||
M: Mutator<I, <Self as UsesState>::State>,
|
||||
<Self as UsesState>::State: HasCorpus + HasMetadata + HasRand,
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
observers::ObserversTuple,
|
||||
schedulers::Scheduler,
|
||||
start_timer,
|
||||
state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand},
|
||||
state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand, UsesState},
|
||||
Error, EvaluatorObservers, ExecutionProcessor, HasMetadata, HasScheduler,
|
||||
};
|
||||
#[cfg(feature = "introspection")]
|
||||
@ -88,6 +88,7 @@ where
|
||||
OT: ObserversTuple<Z::State> + Serialize,
|
||||
Z::State: HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug,
|
||||
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
|
||||
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
fn push_stage_helper(&self) -> &PushStageHelper<CS, EM, OT, Z> {
|
||||
@ -196,6 +197,7 @@ where
|
||||
OT: ObserversTuple<Z::State> + Serialize,
|
||||
Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug,
|
||||
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>;
|
||||
|
||||
|
@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::state::HasClientPerfMonitor;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasTestcase},
|
||||
corpus::{Corpus, CorpusId},
|
||||
events::{llmp::LlmpEventConverter, Event, EventConfig, EventFirer},
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
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>
|
||||
where
|
||||
EM: UsesState<State = S> + EventFirer,
|
||||
S: State + HasExecutions + HasCorpus + HasRand + HasMetadata + HasTestcase,
|
||||
S: State + HasExecutions + HasCorpus + HasRand + HasMetadata,
|
||||
SP: ShMemProvider,
|
||||
E: HasObservers<State = S> + Executor<EM, Z>,
|
||||
for<'a> E::Observers: Deserialize<'a>,
|
||||
@ -257,6 +257,8 @@ where
|
||||
IC: InputConverter<From = S::Input, To = DI>,
|
||||
ICB: InputConverter<From = DI, To = S::Input>,
|
||||
DI: Input,
|
||||
<<S as HasCorpus>::Corpus as Corpus>::Input: Clone,
|
||||
S::Corpus: Corpus<Input = S::Input>, // delete me
|
||||
{
|
||||
#[inline]
|
||||
fn perform(
|
||||
|
@ -48,7 +48,7 @@ where
|
||||
<E as UsesObservers>::Observers: Serialize,
|
||||
EM: UsesState<State = Self::State> + EventFirer,
|
||||
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,
|
||||
IP: Clone + MutatedTransformPost<Self::State>,
|
||||
M: Mutator<Self::Input, Self::State>,
|
||||
@ -58,6 +58,7 @@ where
|
||||
+ ExecutesInput<E, EM>
|
||||
+ ExecutionProcessor,
|
||||
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>,
|
||||
{
|
||||
/// The mutator registered for this stage
|
||||
fn mutator(&self) -> &M;
|
||||
@ -246,10 +247,11 @@ where
|
||||
FF: FeedbackFactory<F, E::Observers>,
|
||||
F: Feedback<Self::State>,
|
||||
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
|
||||
Self::State:
|
||||
Z::State:
|
||||
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata,
|
||||
M: Mutator<Self::Input, Self::State>,
|
||||
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> {
|
||||
self.restart_helper.should_restart(state, &self.name)
|
||||
@ -308,10 +310,16 @@ where
|
||||
FF: FeedbackFactory<F, E::Observers>,
|
||||
F: Feedback<Self::State>,
|
||||
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
|
||||
Self::State:
|
||||
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata,
|
||||
Z::State: HasMetadata
|
||||
+ HasExecutions
|
||||
+ HasSolutions
|
||||
+ HasCorpus
|
||||
+ HasMaxSize
|
||||
+ HasNamedMetadata
|
||||
+ HasCurrentTestcase,
|
||||
M: Mutator<Self::Input, Self::State>,
|
||||
IP: MutatedTransformPost<Self::State> + Clone,
|
||||
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
|
||||
{
|
||||
/// The mutator, added to this stage
|
||||
#[inline]
|
||||
|
@ -9,6 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
use libafl_bolts::Named;
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, HasObservers, ShadowExecutor},
|
||||
mark_feature_time,
|
||||
observers::ObserversTuple,
|
||||
@ -39,9 +40,10 @@ where
|
||||
impl<EM, TE, Z> TracingStage<EM, TE, Z>
|
||||
where
|
||||
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>,
|
||||
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)]
|
||||
/// 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
|
||||
E: UsesState<State = <Self as UsesState>::State>,
|
||||
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>,
|
||||
Z: UsesState<State = <Self as UsesState>::State>,
|
||||
<<TE as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = TE::Input>, // delete me
|
||||
{
|
||||
#[inline]
|
||||
fn perform(
|
||||
@ -181,7 +184,9 @@ where
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
SOT: ObserversTuple<E::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]
|
||||
fn perform(
|
||||
|
@ -7,6 +7,7 @@ use libafl_bolts::{current_time, impl_serdeany, rands::Rand};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::Corpus,
|
||||
mark_feature_time,
|
||||
mutators::{MutationResult, Mutator},
|
||||
stages::{
|
||||
@ -164,8 +165,10 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
M: Mutator<I, Self::State>,
|
||||
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,
|
||||
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, // delete me
|
||||
{
|
||||
/// Runs this (mutational) stage for the given `testcase`
|
||||
/// Exactly the same functionality as [`MutationalStage::perform_mutational`], but with added timeout support.
|
||||
@ -263,8 +266,10 @@ where
|
||||
EM: UsesState<State = Self::State>,
|
||||
M: Mutator<I, Self::State>,
|
||||
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,
|
||||
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, // delete me
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::let_and_return)]
|
||||
@ -298,9 +303,10 @@ where
|
||||
EM: UsesState<State = <Self as UsesState>::State>,
|
||||
M: Mutator<I, <Self as UsesState>::State>,
|
||||
Z: Evaluator<E, EM>,
|
||||
<Self as UsesState>::State:
|
||||
HasCorpus + HasRand + HasNamedMetadata + HasExecutions + HasMetadata,
|
||||
<Z as UsesState>::State:
|
||||
HasCorpus + HasRand + HasNamedMetadata + HasExecutions + HasMetadata + HasCurrentTestcase,
|
||||
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(
|
||||
&mut self,
|
||||
|
@ -8,7 +8,7 @@ use libafl_bolts::{impl_serdeany, Error};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::HasTestcase,
|
||||
corpus::Corpus,
|
||||
inputs::{BytesInput, HasMutatorBytes},
|
||||
stages::Stage,
|
||||
state::{HasCorpus, HasCurrentTestcase, State, UsesState},
|
||||
@ -100,7 +100,8 @@ where
|
||||
|
||||
impl<S, E, EM, Z> Stage<E, EM, Z> for UnicodeIdentificationStage<S>
|
||||
where
|
||||
S: HasTestcase<Input = BytesInput> + HasCorpus + State,
|
||||
S: HasCorpus + State + HasCurrentTestcase,
|
||||
S::Corpus: Corpus<Input = BytesInput>,
|
||||
E: UsesState<State = S>,
|
||||
EM: UsesState<State = S>,
|
||||
Z: UsesState<State = S>,
|
||||
|
@ -74,9 +74,9 @@ where
|
||||
}
|
||||
|
||||
/// Trait for elements offering a corpus
|
||||
pub trait HasCorpus: UsesInput {
|
||||
pub trait HasCorpus {
|
||||
/// The associated type implementing [`Corpus`].
|
||||
type Corpus: Corpus<Input = <Self as UsesInput>::Input>;
|
||||
type Corpus: Corpus;
|
||||
|
||||
/// The testcase corpus
|
||||
fn corpus(&self) -> &Self::Corpus;
|
||||
@ -84,6 +84,22 @@ pub trait HasCorpus: UsesInput {
|
||||
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
|
||||
pub trait HasMaxSize {
|
||||
/// The maximum size hint for items and mutations returned
|
||||
@ -93,9 +109,9 @@ pub trait HasMaxSize {
|
||||
}
|
||||
|
||||
/// Trait for elements offering a corpus of solutions
|
||||
pub trait HasSolutions: UsesInput {
|
||||
pub trait HasSolutions {
|
||||
/// The associated type implementing [`Corpus`] for solutions
|
||||
type Solutions: Corpus<Input = <Self as UsesInput>::Input>;
|
||||
type Solutions: Corpus;
|
||||
|
||||
/// The solutions corpus
|
||||
fn solutions(&self) -> &Self::Solutions;
|
||||
@ -289,9 +305,9 @@ where
|
||||
|
||||
impl<I, C, R, SC> State for StdState<I, C, R, SC>
|
||||
where
|
||||
C: Corpus<Input = Self::Input>,
|
||||
C: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
|
||||
R: Rand,
|
||||
SC: Corpus<Input = Self::Input>,
|
||||
SC: Corpus<Input = Self::Input> + Serialize + DeserializeOwned,
|
||||
Self: UsesInput,
|
||||
{
|
||||
}
|
||||
@ -317,9 +333,7 @@ where
|
||||
|
||||
impl<I, C, R, SC> HasCorpus for StdState<I, C, R, SC>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<Input = <Self as UsesInput>::Input>,
|
||||
R: Rand,
|
||||
C: Corpus,
|
||||
{
|
||||
type Corpus = C;
|
||||
|
||||
@ -338,23 +352,15 @@ where
|
||||
|
||||
impl<I, C, R, SC> HasTestcase for StdState<I, C, R, SC>
|
||||
where
|
||||
I: Input,
|
||||
C: Corpus<Input = <Self as UsesInput>::Input>,
|
||||
R: Rand,
|
||||
C: Corpus,
|
||||
{
|
||||
/// To get the testcase
|
||||
fn testcase(
|
||||
&self,
|
||||
id: CorpusId,
|
||||
) -> Result<Ref<'_, Testcase<<Self as UsesInput>::Input>>, Error> {
|
||||
fn testcase(&self, id: CorpusId) -> Result<Ref<'_, Testcase<C::Input>>, Error> {
|
||||
Ok(self.corpus().get(id)?.borrow())
|
||||
}
|
||||
|
||||
/// To get mutable testcase
|
||||
fn testcase_mut(
|
||||
&self,
|
||||
id: CorpusId,
|
||||
) -> Result<RefMut<'_, Testcase<<Self as UsesInput>::Input>>, Error> {
|
||||
fn testcase_mut(&self, id: CorpusId) -> Result<RefMut<'_, Testcase<C::Input>>, Error> {
|
||||
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
|
||||
pub trait HasCurrentTestcase<I>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
pub trait HasCurrentTestcase: HasCorpus {
|
||||
/// Gets the current [`Testcase`] we are fuzzing
|
||||
///
|
||||
/// 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>;
|
||||
|
||||
/// Gets the current [`Testcase`] we are fuzzing (mut)
|
||||
///
|
||||
/// 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>;
|
||||
|
||||
/// Gets a cloned representation of the current [`Testcase`].
|
||||
@ -527,15 +533,17 @@ where
|
||||
/// # Note
|
||||
/// This allocates memory and copies the contents!
|
||||
/// 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
|
||||
I: Input,
|
||||
T: HasCorpus + HasCurrentCorpusId + UsesInput<Input = I>,
|
||||
T: HasCorpus + HasCurrentCorpusId,
|
||||
<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 {
|
||||
return Err(Error::key_not_found(
|
||||
"We are not currently processing a testcase",
|
||||
@ -545,7 +553,9 @@ where
|
||||
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 {
|
||||
return Err(Error::illegal_state(
|
||||
"We are not currently processing a testcase",
|
||||
@ -555,7 +565,7 @@ where
|
||||
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()?;
|
||||
Ok(testcase.borrow_mut().load_input(self.corpus())?.clone())
|
||||
}
|
||||
@ -1153,6 +1163,8 @@ where
|
||||
where
|
||||
F: Feedback<Self>,
|
||||
O: Feedback<Self>,
|
||||
C: Serialize + DeserializeOwned,
|
||||
SC: Serialize + DeserializeOwned,
|
||||
{
|
||||
let mut state = Self {
|
||||
rand,
|
||||
|
@ -417,6 +417,9 @@ where
|
||||
pub trait NamedTuple: HasConstLen {
|
||||
/// Gets the name of this tuple
|
||||
fn name(&self, index: usize) -> Option<&Cow<'static, str>>;
|
||||
|
||||
/// Gets all the names
|
||||
fn names(&self) -> Vec<Cow<'static, str>>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
@ -424,6 +427,10 @@ impl NamedTuple for () {
|
||||
fn name(&self, _index: usize) -> Option<&Cow<'static, str>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn names(&self) -> Vec<Cow<'static, str>> {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
@ -448,6 +455,13 @@ where
|
||||
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
|
||||
@ -596,7 +610,6 @@ pub struct RefIndexable<RM, M>(RM, PhantomData<M>);
|
||||
impl<RM, M> From<RM> for RefIndexable<RM, M>
|
||||
where
|
||||
RM: Deref<Target = M>,
|
||||
M: MatchName,
|
||||
{
|
||||
fn from(value: RM) -> Self {
|
||||
RefIndexable(value, PhantomData)
|
||||
|
@ -9,6 +9,7 @@ use frida_gum::{
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{hooks::inprocess::InProcessHooks, inprocess::HasInProcessHooks},
|
||||
state::{HasCorpus, HasSolutions},
|
||||
};
|
||||
@ -242,6 +243,8 @@ where
|
||||
S::Input: HasTargetBytes,
|
||||
OT: ObserversTuple<S>,
|
||||
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
|
||||
#[inline]
|
||||
|
@ -12,7 +12,7 @@ use libafl::{
|
||||
inmemory::{TestcaseStorage, TestcaseStorageMap},
|
||||
Corpus, CorpusId, Testcase,
|
||||
},
|
||||
inputs::{Input, UsesInput},
|
||||
inputs::Input,
|
||||
};
|
||||
use libafl_bolts::Error;
|
||||
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>
|
||||
where
|
||||
I: Input + Serialize + for<'de> Deserialize<'de>,
|
||||
{
|
||||
type Input = I;
|
||||
|
||||
#[inline]
|
||||
fn count(&self) -> usize {
|
||||
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>
|
||||
where
|
||||
I: Input + Serialize + for<'de> Deserialize<'de>,
|
||||
{
|
||||
type Input = I;
|
||||
|
||||
fn count(&self) -> usize {
|
||||
self.count
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ macro_rules! fuzz_with {
|
||||
// TODO configure with mutation stacking options from libfuzzer
|
||||
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, ()));
|
||||
|
||||
// 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 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_std_power = StdMutationalStage::new(std_mutator_no_mutate);
|
||||
let cm_std_power =
|
||||
@ -395,7 +395,7 @@ macro_rules! fuzz_with {
|
||||
|
||||
let cc_power = StdMutationalStage::new(custom_crossover);
|
||||
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 =
|
||||
IfStage::new(|_, _, _, _| Ok(mutator_status.std_no_crossover.into()), (cc_std_power, ()));
|
||||
|
||||
|
@ -7,11 +7,8 @@ use core::{
|
||||
#[cfg(emulation_mode = "usermode")]
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl::{
|
||||
events::EventManager, executors::InProcessForkExecutor, state::HasLastReportTime, HasMetadata,
|
||||
};
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::inprocess::InProcessExecutorHandlerData,
|
||||
@ -26,6 +23,10 @@ use libafl::{
|
||||
Error, ExecutionProcessor, HasScheduler,
|
||||
};
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl::{
|
||||
events::EventManager, executors::InProcessForkExecutor, state::HasLastReportTime, HasMetadata,
|
||||
};
|
||||
#[cfg(feature = "fork")]
|
||||
use libafl_bolts::shmem::ShMemProvider;
|
||||
use libafl_bolts::{
|
||||
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>,
|
||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||
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 {
|
||||
libafl_exit_request_timeout();
|
||||
@ -133,6 +136,8 @@ where
|
||||
OF: Feedback<S>,
|
||||
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
|
||||
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(
|
||||
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,
|
||||
|
@ -2,6 +2,7 @@ use alloc::borrow::{Cow, ToOwned};
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
executors::{Executor, HasObservers},
|
||||
inputs::{BytesInput, UsesInput},
|
||||
observers::ObserversTuple,
|
||||
@ -51,10 +52,15 @@ impl<E, EM, TE, Z> Stage<E, EM, Z> for AFLppCmplogTracingStage<'_, EM, TE, Z>
|
||||
where
|
||||
E: UsesState<State = Self::State>,
|
||||
TE: Executor<EM, Z> + HasObservers,
|
||||
Self::State:
|
||||
HasExecutions + HasCorpus + HasMetadata + UsesInput<Input = BytesInput> + HasNamedMetadata,
|
||||
TE::State: HasExecutions
|
||||
+ HasCorpus
|
||||
+ HasMetadata
|
||||
+ UsesInput<Input = BytesInput>
|
||||
+ HasNamedMetadata
|
||||
+ HasCurrentTestcase,
|
||||
EM: UsesState<State = Self::State>,
|
||||
Z: UsesState<State = Self::State>,
|
||||
<Self::State as HasCorpus>::Corpus: Corpus<Input = BytesInput>, //delete me
|
||||
{
|
||||
#[inline]
|
||||
fn perform(
|
||||
|
@ -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
|
||||
/// 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
|
||||
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
|
||||
@ -90,10 +90,10 @@ struct MutatorProxy<'a, M, MT, S> {
|
||||
/// The result of mutation, to be propagated to the mutational stage
|
||||
result: Rc<RefCell<Result<MutationResult, Error>>>,
|
||||
/// 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
|
||||
fn new(
|
||||
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
|
||||
/// is no longer permitted to be executed.
|
||||
fn weak(
|
||||
&self,
|
||||
) -> WeakMutatorProxy<impl Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool, M, MT, S> {
|
||||
fn weak(&self) -> WeakMutatorProxy<impl Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool, M, S> {
|
||||
let state = Rc::downgrade(&self.state);
|
||||
WeakMutatorProxy {
|
||||
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
|
||||
/// mutator is no longer accessible by the custom mutator.
|
||||
#[derive(Clone)]
|
||||
struct WeakMutatorProxy<F, M, MT, S> {
|
||||
struct WeakMutatorProxy<F, M, S> {
|
||||
/// Function which will perform the access to the state.
|
||||
accessor: F,
|
||||
|
||||
@ -145,14 +143,14 @@ struct WeakMutatorProxy<F, M, MT, S> {
|
||||
|
||||
/// The result of mutation, to be propagated to the mutational stage
|
||||
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
|
||||
F: Fn(&mut dyn for<'b> FnMut(&'b mut S)) -> bool,
|
||||
M: ScheduledMutator<BytesInput, MT, S>,
|
||||
MT: MutatorsTuple<BytesInput, S>,
|
||||
M: ScheduledMutator<BytesInput, S>,
|
||||
M::Mutations: MutatorsTuple<BytesInput, S>,
|
||||
S: HasMaxSize + UsesInput<Input = BytesInput>,
|
||||
{
|
||||
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
|
||||
/// injection of some input portions to another in ways which violate structure.
|
||||
#[derive(Debug)]
|
||||
pub struct LLVMCustomMutator<MT, SM, const CROSSOVER: bool> {
|
||||
pub struct LLVMCustomMutator<S, SM, const CROSSOVER: bool> {
|
||||
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
|
||||
///
|
||||
/// # 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
|
||||
///
|
||||
/// # Safety
|
||||
@ -267,34 +265,33 @@ impl<MT, SM> LLVMCustomMutator<MT, SM, true> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<MT, S, SM, const CROSSOVER: bool> ComposedByMutations<BytesInput, MT, S>
|
||||
for LLVMCustomMutator<MT, SM, CROSSOVER>
|
||||
impl<S, SM, const CROSSOVER: bool> ComposedByMutations for LLVMCustomMutator<S, SM, CROSSOVER>
|
||||
where
|
||||
MT: MutatorsTuple<BytesInput, S>,
|
||||
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize,
|
||||
SM: ScheduledMutator<BytesInput, MT, S>,
|
||||
SM: ScheduledMutator<BytesInput, S>,
|
||||
SM::Mutations: MutatorsTuple<BytesInput, 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.")
|
||||
}
|
||||
|
||||
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.")
|
||||
}
|
||||
}
|
||||
|
||||
impl<MT, SM> Named for LLVMCustomMutator<MT, SM, false> {
|
||||
impl<S, SM> Named for LLVMCustomMutator<S, SM, false> {
|
||||
fn name(&self) -> &Cow<'static, str> {
|
||||
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator");
|
||||
&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
|
||||
MT: MutatorsTuple<BytesInput, S> + '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]
|
||||
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
|
||||
SM: ScheduledMutator<BytesInput, MT, S> + 'static,
|
||||
MT: MutatorsTuple<BytesInput, S> + 'static,
|
||||
SM: ScheduledMutator<BytesInput, S> + 'static,
|
||||
S: UsesInput<Input = BytesInput> + HasRand + HasMaxSize + 'static,
|
||||
SM::Mutations: MutatorsTuple<BytesInput, S>,
|
||||
{
|
||||
fn iterations(&self, state: &mut S, input: &S::Input) -> u64 {
|
||||
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> {
|
||||
static NAME: Cow<'static, str> = Cow::Borrowed("LLVMCustomMutator");
|
||||
&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
|
||||
MT: MutatorsTuple<BytesInput, S> + '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]
|
||||
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
|
||||
SM: ScheduledMutator<BytesInput, MT, S> + 'static,
|
||||
MT: MutatorsTuple<BytesInput, S> + 'static,
|
||||
SM: ScheduledMutator<BytesInput, S> + '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 {
|
||||
let mutator = self.mutator.deref().borrow();
|
||||
|
@ -1,10 +1,11 @@
|
||||
//! Setup asan death callbback
|
||||
|
||||
use libafl::{
|
||||
corpus::Corpus,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{hooks::windows::windows_asan_handler::asan_death_handler, Executor, HasObservers},
|
||||
feedbacks::Feedback,
|
||||
state::{HasCorpus, HasExecutions, HasSolutions},
|
||||
state::{HasCorpus, HasExecutions, HasSolutions, UsesState},
|
||||
HasObjective,
|
||||
};
|
||||
|
||||
@ -34,6 +35,8 @@ where
|
||||
OF: Feedback<E::State>,
|
||||
E::State: HasSolutions + HasCorpus + HasExecutions,
|
||||
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>));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user