No Uses* for Corpus, Mutators (#2547)

* wip

* this shit is crazy

* from windows

* fmt

* fuck

* fmt

* aa

* reduce generics for generator

* do stuff for mutators, too

* aa

* a

* fmt

* idk

* getting things compiling

* fix merge

* idk

* fuzzers

* nire

* more

* a

* frida win

* cmin

* mm

* qemu?

* del ubuntu dep

---------

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

View File

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

View File

@ -94,8 +94,8 @@ pub fn main() -> Result<(), Error> {
.expect("Failed to generate the initial corpus");
// 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(),

View File

@ -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(

View File

@ -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(

View File

@ -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);

View File

@ -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(

View File

@ -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(

View File

@ -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,

View File

@ -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,
{

View File

@ -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)]

View File

@ -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(

View File

@ -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(

View File

@ -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(

View File

@ -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!(

View File

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

View File

@ -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);

View File

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

View File

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

View File

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

View File

@ -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>()

View File

@ -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

View File

@ -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]

View File

@ -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))

View File

@ -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,

View File

@ -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())
}

View File

@ -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 {

View File

@ -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.

View File

@ -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

View File

@ -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")]

View File

@ -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| {

View File

@ -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() {

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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>(

View File

@ -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,

View File

@ -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>,
}

View File

@ -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 {

View File

@ -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();

View File

@ -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();

View File

@ -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,

View File

@ -49,8 +49,7 @@ pub type HavocMutationsNoCrossoverType = tuple_list_type!(
);
/// Tuple type of the mutations that compose the Havoc mutator's crossover mutations
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())
}

View File

@ -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>>> {

View File

@ -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,

View File

@ -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,

View File

@ -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() {

View File

@ -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,

View File

@ -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,
}
}
}

View File

@ -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)]

View File

@ -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>
impl<MT> TuneableScheduledMutator<MT> {
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
pub fn new<S>(state: &mut S, mutations: MT) -> Self
where
MT: MutatorsTuple<I, S>,
MT: NamedTuple,
S: HasRand + HasMetadata,
{
/// Create a new [`TuneableScheduledMutator`] instance specifying mutations
pub fn new(state: &mut S, mutations: MT) -> Self {
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());
}

View File

@ -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;

View File

@ -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,
{

View File

@ -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() {

View File

@ -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

View File

@ -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)
}
}

View File

@ -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>()?;

View File

@ -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,
{

View File

@ -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(

View File

@ -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)]

View File

@ -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(

View File

@ -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(

View File

@ -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]

View File

@ -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> {

View File

@ -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,

View File

@ -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>;

View File

@ -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(

View File

@ -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]

View File

@ -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(

View File

@ -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,

View File

@ -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>,

View File

@ -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,

View File

@ -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)

View File

@ -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]

View File

@ -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
}

View File

@ -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, ()));

View File

@ -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,

View File

@ -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(

View File

@ -82,7 +82,7 @@ pub extern "C" fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize)
/// A proxy which wraps a targeted mutator. This is used to provide dynamic access to a global
/// 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();

View File

@ -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>));
}