No Uses* for Feedbacks (#2578)

* add from addison's change

* fixing

* one left

* adding

* 444444

* okoko

* no prelude

* i hate rust

* stuff

* no std/win

* getting closer

* a

* a

* aa

* a

* a

* libafl_fuzz

* toml

* tutorial

* libafl_libfuzzer
This commit is contained in:
Dongjia "toka" Zhang 2024-10-02 14:07:08 +02:00 committed by GitHub
parent a212d66afe
commit cbce7ffdfd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 1029 additions and 1638 deletions

View File

@ -2,12 +2,10 @@ use std::borrow::Cow;
use libafl::{
corpus::{Corpus, Testcase},
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, MapIndexesMetadata},
observers::ObserversTuple,
feedbacks::{Feedback, MapIndexesMetadata, StateInitializer},
schedulers::{MinimizerScheduler, TestcaseScore},
state::{HasCorpus, State},
state::HasCorpus,
Error, HasMetadata,
};
use libafl_bolts::{Named, SerdeAny};
@ -45,29 +43,24 @@ pub struct PacketLenFeedback {
len: u64,
}
impl<S> Feedback<S> for PacketLenFeedback
where
S: State<Input = PacketData>,
{
impl<S> StateInitializer<S> for PacketLenFeedback {}
impl<EM, OT, S> Feedback<EM, PacketData, OT, S> for PacketLenFeedback {
#[inline]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
input: &PacketData,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<PacketData, S>,
{
) -> Result<bool, Error> {
self.len = input.length;
Ok(false)
}
#[inline]
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,

View File

@ -1,18 +1,13 @@
use std::{
borrow::Cow,
fmt::{Debug, Formatter},
marker::PhantomData,
path::{Path, PathBuf},
};
use libafl::{
corpus::Testcase,
events::EventFirer,
corpus::{Corpus, Testcase},
executors::ExitKind,
feedbacks::{Feedback, FeedbackFactory},
inputs::Input,
observers::ObserversTuple,
state::State,
feedbacks::{Feedback, FeedbackFactory, StateInitializer},
state::HasCorpus,
};
use libafl_bolts::{Error, Named};
use serde::{Deserialize, Serialize};
@ -22,108 +17,68 @@ use serde::{Deserialize, Serialize};
/// Note: If used as part of the `Objective` chain, then it will only apply to testcases which are
/// `Objectives`, vice versa for `Feedback`.
#[derive(Serialize, Deserialize)]
pub struct CustomFilepathToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>, &Path) -> Result<(), Error>,
{
pub struct CustomFilepathToTestcaseFeedback<F> {
/// Closure that returns the filename.
func: F,
/// The root output directory
out_dir: PathBuf,
phantomm: PhantomData<(I, S)>,
}
impl<F, I, S> CustomFilepathToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>, &Path) -> Result<(), Error>,
{
impl<F> CustomFilepathToTestcaseFeedback<F> {
/// Create a new [`CustomFilepathToTestcaseFeedback`].
pub fn new(func: F, out_dir: PathBuf) -> Self {
Self {
func,
out_dir,
phantomm: PhantomData,
}
Self { func, out_dir }
}
}
impl<F, I, S, T> FeedbackFactory<CustomFilepathToTestcaseFeedback<F, I, S>, T>
for CustomFilepathToTestcaseFeedback<F, I, S>
impl<F, T> FeedbackFactory<CustomFilepathToTestcaseFeedback<F>, T>
for CustomFilepathToTestcaseFeedback<F>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>, &Path) -> Result<(), Error> + Clone,
F: Clone,
{
fn create_feedback(&self, _ctx: &T) -> CustomFilepathToTestcaseFeedback<F, I, S> {
fn create_feedback(&self, _ctx: &T) -> CustomFilepathToTestcaseFeedback<F> {
Self {
func: self.func.clone(),
phantomm: self.phantomm,
out_dir: self.out_dir.clone(),
}
}
}
impl<F, I, S> Named for CustomFilepathToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>, &Path) -> Result<(), Error>,
{
impl<F> Named for CustomFilepathToTestcaseFeedback<F> {
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CustomFilepathToTestcaseFeedback");
&NAME
}
}
impl<F, I, S> Debug for CustomFilepathToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>, &Path) -> Result<(), Error>,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CustomFilepathToTestcaseFeedback")
.finish_non_exhaustive()
}
}
impl<F, S> StateInitializer<S> for CustomFilepathToTestcaseFeedback<F> {}
impl<F, I, S> Feedback<S> for CustomFilepathToTestcaseFeedback<F, I, S>
impl<F, EM, OT, S> Feedback<EM, <S::Corpus as Corpus>::Input, OT, S>
for CustomFilepathToTestcaseFeedback<F>
where
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<S::Input>, &Path) -> Result<(), Error>,
I: Input,
S: HasCorpus,
F: FnMut(&mut S, &mut Testcase<<S::Corpus as Corpus>::Input>, &Path) -> Result<(), Error>,
{
#[allow(clippy::wrong_self_convention)]
#[inline]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &I,
_input: &<S::Corpus as Corpus>::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
{
) -> Result<bool, Error> {
Ok(false)
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<<S::Corpus as Corpus>::Input>,
) -> Result<(), Error> {
(self.func)(state, testcase, &self.out_dir)?;
Ok(())
}

View File

@ -1,18 +1,12 @@
use std::{
borrow::Cow,
collections::VecDeque,
fmt::{Debug, Formatter},
marker::PhantomData,
};
use std::{borrow::Cow, collections::VecDeque};
use libafl::{
corpus::{Corpus, Testcase},
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, FeedbackFactory},
inputs::Input,
observers::ObserversTuple,
state::{HasCorpus, State},
prelude::StateInitializer,
state::HasCorpus,
};
use libafl_bolts::{Error, Named};
use serde::{Deserialize, Serialize};
@ -20,85 +14,59 @@ use serde::{Deserialize, Serialize};
/// A [`PersitentRecordFeedback`] tracks the last N inputs that the fuzzer has run.
/// TODO: Kept in memory for now but should write to disk.
#[derive(Serialize, Deserialize)]
pub struct PersitentRecordFeedback<I, S>
where
S: State<Input = I>,
{
pub struct PersitentRecordFeedback<I> {
/// Vec that tracks the last `record_size` [`Input`]
record: VecDeque<I>,
record_size: usize,
phantomm: PhantomData<(I, S)>,
}
impl<I, S> PersitentRecordFeedback<I, S>
where
I: Input,
S: State<Input = I>,
{
impl<I> PersitentRecordFeedback<I> {
/// Create a new [`PersitentRecordFeedback`].
pub fn new(record_size: usize) -> Self {
Self {
record_size,
record: VecDeque::default(),
phantomm: PhantomData,
}
}
}
impl<I, S, T> FeedbackFactory<PersitentRecordFeedback<I, S>, T> for PersitentRecordFeedback<I, S>
impl<I, T> FeedbackFactory<PersitentRecordFeedback<I>, T> for PersitentRecordFeedback<I>
where
I: Input,
S: State<Input = I>,
I: Clone,
{
fn create_feedback(&self, _ctx: &T) -> PersitentRecordFeedback<I, S> {
fn create_feedback(&self, _ctx: &T) -> PersitentRecordFeedback<I> {
Self {
record_size: self.record_size,
record: self.record.clone(),
phantomm: self.phantomm,
}
}
}
impl<I, S> Named for PersitentRecordFeedback<I, S>
where
I: Input,
S: State<Input = I>,
{
impl<I> Named for PersitentRecordFeedback<I> {
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("PersitentRecordFeedback");
&NAME
}
}
impl<I, S> Debug for PersitentRecordFeedback<I, S>
where
I: Input,
S: State<Input = I>,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PersitentRecordFeedback")
.finish_non_exhaustive()
}
}
impl<I, S> StateInitializer<S> for PersitentRecordFeedback<I> {}
impl<I, S> Feedback<S> for PersitentRecordFeedback<I, S>
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for PersitentRecordFeedback<I>
where
S: State<Input = I> + HasCorpus,
S: HasCorpus,
S::Corpus: Corpus<Input = I>,
I: Input,
{
#[allow(clippy::wrong_self_convention)]
#[inline]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
{
) -> Result<bool, Error> {
if self.should_run() {
self.record.push_back(input.clone());
if self.record.len() == self.record_size {
@ -108,17 +76,13 @@ where
Ok(false)
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
if self.should_run() {
let file_path = testcase
.file_path()
@ -150,11 +114,7 @@ where
}
}
impl<I, S> PersitentRecordFeedback<I, S>
where
I: Input,
S: State<Input = I>,
{
impl<I> PersitentRecordFeedback<I> {
fn should_run(&self) -> bool {
self.record_size > 0
}

View File

@ -1,8 +1,7 @@
use std::{borrow::Cow, marker::PhantomData};
use libafl::{
corpus::Testcase, events::EventFirer, executors::ExitKind, feedbacks::Feedback,
observers::ObserversTuple, state::State, Error,
corpus::Testcase, executors::ExitKind, feedbacks::Feedback, prelude::StateInitializer, Error,
};
use libafl_bolts::Named;
@ -13,57 +12,50 @@ use crate::Opt;
/// then, essentially becomes benign
#[allow(clippy::module_name_repetitions, clippy::struct_excessive_bools)]
#[derive(Debug)]
pub struct SeedFeedback<A, S>
where
A: Feedback<S>,
S: State,
{
pub struct SeedFeedback<A, S> {
/// Inner [`Feedback`]
pub inner: A,
ignore_timeouts: bool,
ignore_seed_issues: bool,
exit_on_seed_issues: bool,
phantom: PhantomData<S>,
done_loading_seeds: bool,
phantom: PhantomData<S>,
}
impl<A, S> SeedFeedback<A, S>
where
A: Feedback<S>,
S: State,
{
impl<A, S> SeedFeedback<A, S> {
pub fn new(inner: A, opt: &Opt) -> Self {
Self {
inner,
ignore_timeouts: opt.ignore_timeouts,
ignore_seed_issues: opt.ignore_seed_issues,
exit_on_seed_issues: opt.exit_on_seed_issues,
phantom: PhantomData,
done_loading_seeds: false,
phantom: PhantomData,
}
}
}
impl<A, S> Feedback<S> for SeedFeedback<A, S>
impl<A, S> StateInitializer<S> for SeedFeedback<A, S>
where
A: Feedback<S>,
S: State,
A: StateInitializer<S>,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
self.inner.init_state(state)?;
Ok(())
}
fn is_interesting<EM, OT>(
}
impl<A, EM, I, OT, S> Feedback<EM, I, OT, S> for SeedFeedback<A, S>
where
A: Feedback<EM, I, OT, S>,
{
fn is_interesting(
&mut self,
state: &mut S,
manager: &mut EM,
input: &S::Input,
input: &I,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
if !self.done_loading_seeds {
match exit_kind {
ExitKind::Timeout => {
@ -93,17 +85,13 @@ where
}
/// Append to the testcase the generated metadata in case of a new corpus item
#[inline]
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
state: &mut S,
manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
self.inner
.append_metadata(state, manager, observers, testcase)?;
Ok(())
@ -111,7 +99,7 @@ where
/// Discard the stored metadata in case that the testcase is not added to the corpus
#[inline]
fn discard_metadata(&mut self, state: &mut S, input: &S::Input) -> Result<(), Error> {
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.inner.discard_metadata(state, input)?;
Ok(())
}
@ -128,11 +116,7 @@ where
}
}
impl<S, A> Named for SeedFeedback<A, S>
where
A: Feedback<S>,
S: State,
{
impl<A, S> Named for SeedFeedback<A, S> {
#[inline]
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("SeedFeedback");
@ -140,11 +124,7 @@ where
}
}
impl<S, A> SeedFeedback<A, S>
where
A: Feedback<S>,
S: State,
{
impl<A, S> SeedFeedback<A, S> {
pub fn done_loading_seeds(&mut self) {
self.done_loading_seeds = true;
}

View File

@ -8,8 +8,8 @@ use std::{
use libafl::{
corpus::{CachedOnDiskCorpus, Corpus, OnDiskCorpus},
events::{
CentralizedEventManager, EventManagerHooksTuple, EventProcessor,
LlmpRestartingEventManager, ProgressReporter,
CentralizedEventManager, EventManagerHooksTuple, LlmpRestartingEventManager,
ProgressReporter,
},
executors::forkserver::{ForkserverExecutor, ForkserverExecutorBuilder},
feedback_and, feedback_or, feedback_or_fast,
@ -530,7 +530,7 @@ pub fn run_fuzzer_with_stages<Z, ST, E, EM>(
where
Z: Fuzzer<E, EM, ST>,
E: UsesState<State = Z::State>,
EM: ProgressReporter<State = Z::State> + EventProcessor<E, Z>,
EM: ProgressReporter<State = Z::State>,
ST: StagesTuple<E, EM, Z::State, Z>,
<Z as UsesState>::State: HasLastReportTime + HasExecutions + HasMetadata,
{

View File

@ -377,8 +377,8 @@ where
S: State,
Self::State: HasExecutions + HasMetadata,
SP: ShMemProvider,
Z: EvaluatorObservers<E::Observers, State = Self::State>
+ ExecutionProcessor<State = Self::State>,
Z: EvaluatorObservers<Self, E::Observers, State = Self::State>
+ ExecutionProcessor<Self, E::Observers, State = Self::State>,
{
fn process(
&mut self,
@ -413,8 +413,8 @@ where
EMH: EventManagerHooksTuple<EM::State>,
S: State,
SP: ShMemProvider,
Z: EvaluatorObservers<E::Observers, State = Self::State>
+ ExecutionProcessor<State = Self::State>,
Z: EvaluatorObservers<Self, E::Observers, State = Self::State>
+ ExecutionProcessor<Self, E::Observers, State = Self::State>,
{
}
@ -535,8 +535,8 @@ where
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
<Self as UsesState>::State: UsesInput + HasExecutions + HasMetadata,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = <Self as UsesState>::State>
+ EvaluatorObservers<E::Observers>,
Z: ExecutionProcessor<Self, E::Observers, State = <Self as UsesState>::State>
+ EvaluatorObservers<Self, E::Observers>,
{
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.client.sender().id();
@ -585,8 +585,8 @@ where
ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State> + Serialize,
<Self as UsesState>::State: UsesInput + HasExecutions + HasMetadata,
for<'a> E::Observers: Deserialize<'a> + Serialize,
Z: ExecutionProcessor<State = <Self as UsesState>::State>
+ EvaluatorObservers<E::Observers>,
Z: ExecutionProcessor<Self, E::Observers, State = <Self as UsesState>::State>
+ EvaluatorObservers<Self, E::Observers>,
{
log::debug!("handle_in_main!");
@ -641,7 +641,7 @@ where
process::id(),
event_name
);
fuzzer.evaluate_input_with_observers::<E, Self>(
fuzzer.evaluate_input_with_observers::<E>(
state,
executor,
self,

View File

@ -406,7 +406,9 @@ where
E: Executor<Self, Z, State = S> + HasObservers,
E::Observers: ObserversTuple<S::Input, S> + Serialize,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers> + Evaluator<E, Self>,
Z: ExecutionProcessor<Self, E::Observers, State = S>
+ EvaluatorObservers<Self, E::Observers>
+ Evaluator<E, Self>,
{
if !self.hooks.pre_exec_all(state, client_id, &event)? {
return Ok(());
@ -449,7 +451,7 @@ where
{
state.scalability_monitor_mut().testcase_without_observers += 1;
}
fuzzer.evaluate_input_with_observers::<E, Self>(
fuzzer.evaluate_input_with_observers::<E>(
state, executor, self, input, false,
)?
};
@ -590,7 +592,9 @@ where
E: HasObservers + Executor<Self, Z, State = S>,
E::Observers: ObserversTuple<S::Input, S> + Serialize,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers> + Evaluator<E, Self>,
Z: ExecutionProcessor<Self, E::Observers, State = S>
+ EvaluatorObservers<Self, E::Observers>
+ Evaluator<E, Self>,
{
fn process(
&mut self,
@ -642,7 +646,9 @@ where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported,
SP: ShMemProvider,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers> + Evaluator<E, Self>,
Z: ExecutionProcessor<Self, E::Observers, State = S>
+ EvaluatorObservers<Self, E::Observers>
+ Evaluator<E, Self>,
{
}

View File

@ -296,7 +296,7 @@ where
E: Executor<EM, Z, State = S> + HasObservers,
EM: UsesState<State = S> + EventFirer,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers>,
Z: ExecutionProcessor<EM, E::Observers, State = S> + EvaluatorObservers<EM, E::Observers>,
{
match event {
Event::NewTestcase {
@ -308,7 +308,7 @@ where
return Ok(());
};
let res = fuzzer.evaluate_input_with_observers::<E, EM>(
let res = fuzzer.evaluate_input_with_observers::<E>(
state,
executor,
manager,
@ -350,7 +350,7 @@ where
E: Executor<EM, Z, State = S> + HasObservers,
EM: UsesState<State = S> + EventFirer,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers>,
Z: ExecutionProcessor<EM, E::Observers, State = S> + EvaluatorObservers<EM, E::Observers>,
{
// TODO: Get around local event copy by moving handle_in_client
let self_id = self.llmp.sender().id();

View File

@ -210,8 +210,8 @@ where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported,
SP: ShMemProvider,
Z: ExecutionProcessor<State = S>
+ EvaluatorObservers<E::Observers>
Z: ExecutionProcessor<LlmpEventManager<EMH, S, SP>, E::Observers, State = S>
+ EvaluatorObservers<LlmpEventManager<EMH, S, SP>, E::Observers>
+ Evaluator<E, LlmpEventManager<EMH, S, SP>>,
{
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
@ -234,8 +234,8 @@ where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported,
SP: ShMemProvider,
Z: ExecutionProcessor<State = S>
+ EvaluatorObservers<E::Observers>
Z: ExecutionProcessor<LlmpEventManager<EMH, S, SP>, E::Observers, State = S>
+ EvaluatorObservers<LlmpEventManager<EMH, S, SP>, E::Observers>
+ Evaluator<E, LlmpEventManager<EMH, S, SP>>,
{
}

View File

@ -614,7 +614,8 @@ where
E: Executor<Self, Z, State = S> + HasObservers,
E::Observers: Serialize + ObserversTuple<S::Input, S>,
for<'a> E::Observers: Deserialize<'a>,
Z: ExecutionProcessor<State = S> + EvaluatorObservers<E::Observers>,
Z: ExecutionProcessor<Self, E::Observers, State = S>
+ EvaluatorObservers<Self, E::Observers>,
{
if !self.hooks.pre_exec_all(state, client_id, &event)? {
return Ok(());
@ -645,9 +646,8 @@ where
{
state.scalability_monitor_mut().testcase_without_observers += 1;
}
fuzzer.evaluate_input_with_observers::<E, Self>(
state, executor, self, input, false,
)?
fuzzer
.evaluate_input_with_observers::<E>(state, executor, self, input, false)?
};
if let Some(item) = _res.1 {
*state.imported_mut() += 1;
@ -756,7 +756,8 @@ where
for<'a> E::Observers: Deserialize<'a>,
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<State = S>,
Z: EvaluatorObservers<Self, E::Observers, State = S>
+ ExecutionProcessor<Self, E::Observers, State = S>,
{
fn process(
&mut self,
@ -830,7 +831,8 @@ where
for<'a> E::Observers: Deserialize<'a>,
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<State = S>,
Z: EvaluatorObservers<Self, E::Observers, State = S>
+ ExecutionProcessor<Self, E::Observers, State = S>,
{
}
@ -976,7 +978,8 @@ where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasImported,
SP: ShMemProvider + 'static,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor, //CE: CustomEvent<I>,
Z: EvaluatorObservers<TcpEventManager<EMH, S>, E::Observers, State = S>
+ ExecutionProcessor<TcpEventManager<EMH, S>, E::Observers>, //CE: CustomEvent<I>,
{
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
self.tcp_mgr.process(fuzzer, state, executor)
@ -996,7 +999,8 @@ where
EMH: EventManagerHooksTuple<S>,
S: State + HasExecutions + HasMetadata + HasLastReportTime + HasImported,
SP: ShMemProvider + 'static,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor, //CE: CustomEvent<I>,
Z: EvaluatorObservers<TcpEventManager<EMH, S>, E::Observers, State = S>
+ ExecutionProcessor<TcpEventManager<EMH, S>, E::Observers>, //CE: CustomEvent<I>,
{
}

View File

@ -239,7 +239,7 @@ where
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -282,7 +282,7 @@ where
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -339,7 +339,7 @@ where
where
E: Executor<EM, Z> + HasObservers + HasInProcessHooks<E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus,
Z: HasObjective<Objective = OF, State = E::State>,
{

View File

@ -80,7 +80,7 @@ pub mod unix_signal_handler {
E: Executor<EM, Z> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -130,7 +130,7 @@ pub mod unix_signal_handler {
E: Executor<EM, Z> + HasInProcessHooks<E::State> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -188,7 +188,7 @@ pub mod unix_signal_handler {
E: Executor<EM, Z> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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

View File

@ -31,7 +31,7 @@ pub mod windows_asan_handler {
where
E: Executor<EM, Z> + HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
Z: HasObjective<Objective = OF, State = E::State>,
@ -184,7 +184,7 @@ pub mod windows_exception_handler {
where
E: HasObservers + Executor<EM, Z>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
Z: HasObjective<Objective = OF, State = E::State>,
@ -248,7 +248,7 @@ pub mod windows_exception_handler {
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -321,7 +321,7 @@ pub mod windows_exception_handler {
E: Executor<EM, Z> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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

View File

@ -170,7 +170,7 @@ where
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, E::Input, E::Observers, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
@ -200,7 +200,7 @@ where
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, E::Input, E::Observers, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
@ -233,7 +233,7 @@ where
E: Executor<EM, Z, State = S> + HasObservers + HasInProcessHooks<S>,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, E::Input, E::Observers, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me

View File

@ -173,7 +173,7 @@ where
where
Self: Executor<EM, Z, State = S> + HasObservers,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
{
@ -201,7 +201,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -242,7 +242,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -287,7 +287,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
{
@ -316,7 +316,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -353,7 +353,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -442,7 +442,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
E: Executor<EM, Z> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
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
@ -505,11 +505,11 @@ where
E: Executor<EM, Z> + HasObservers,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
E::State: HasExecutions + HasSolutions + HasCorpus + HasCurrentTestcase,
Z: HasObjective<Objective = OF, State = E::State>
+ HasScheduler<State = E::State>
+ ExecutionProcessor,
+ ExecutionProcessor<EM, E::Observers>,
<<E as UsesState>::State as HasSolutions>::Solutions: Corpus<Input = E::Input>, //delete me
{
let data = addr_of_mut!(GLOBAL_STATE);

View File

@ -163,7 +163,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
{
@ -193,7 +193,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -236,7 +236,7 @@ where
where
Self: Executor<EM, Z, State = S>,
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -301,7 +301,7 @@ where
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
{
@ -332,7 +332,7 @@ where
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me
@ -371,7 +371,7 @@ where
) -> Result<Self, Error>
where
EM: EventFirer<State = S> + EventRestarter,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State,
Z: HasObjective<Objective = OF, State = S>,
<S as HasSolutions>::Solutions: Corpus<Input = S::Input>, //delete me

View File

@ -53,7 +53,7 @@ where
OT: ObserversTuple<S::Input, S>,
SP: ShMemProvider,
EM: EventFirer<State = S> + EventRestarter<State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: HasSolutions,
Z: HasObjective<Objective = OF, State = S>,
{
@ -190,7 +190,7 @@ where
OT: ObserversTuple<S::Input, S>,
SP: ShMemProvider,
EM: EventFirer<State = S> + EventRestarter<State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State + HasSolutions,
Z: HasObjective<Objective = OF, State = S>,
{

View File

@ -38,7 +38,7 @@ where
OT: ObserversTuple<S::Input, S>,
SP: ShMemProvider,
EM: EventFirer<State = S> + EventRestarter<State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State + HasSolutions,
Z: HasObjective<Objective = OF, State = S>,
{
@ -137,7 +137,7 @@ where
HT: ExecutorHooksTuple<S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
Z: HasObjective<Objective = OF, State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
{
#[allow(unreachable_code)]
#[inline]
@ -179,7 +179,7 @@ where
SP: ShMemProvider,
Z: UsesState<State = S>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: State + HasSolutions,
Z: HasObjective<Objective = OF, State = S>,
{

View File

@ -5,21 +5,17 @@
//! to be not interesting.
//! Requires a [`ConcolicObserver`] to observe the concolic trace.
use alloc::borrow::Cow;
use core::{fmt::Debug, marker::PhantomData};
use core::fmt::Debug;
use libafl_bolts::{
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named,
};
use crate::{
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
inputs::UsesInput,
observers::{concolic::ConcolicObserver, ObserversTuple},
state::State,
feedbacks::{Feedback, StateInitializer},
observers::concolic::ConcolicObserver,
Error, HasMetadata,
};
@ -29,60 +25,45 @@ use crate::{
/// to be not interesting.
/// Requires a [`ConcolicObserver`] to observe the concolic trace.
#[derive(Debug)]
pub struct ConcolicFeedback<'map, S> {
pub struct ConcolicFeedback<'map> {
observer_handle: Handle<ConcolicObserver<'map>>,
phantom: PhantomData<S>,
}
impl<'map, S> ConcolicFeedback<'map, S> {
impl<'map> ConcolicFeedback<'map> {
/// Creates a concolic feedback from an observer
#[allow(unused)]
#[must_use]
pub fn from_observer(observer: &ConcolicObserver<'map>) -> Self {
Self {
observer_handle: observer.handle(),
phantom: PhantomData,
}
}
}
impl<S> Named for ConcolicFeedback<'_, S> {
impl Named for ConcolicFeedback<'_> {
fn name(&self) -> &Cow<'static, str> {
self.observer_handle.name()
}
}
impl<S> Feedback<S> for ConcolicFeedback<'_, S>
impl<S> StateInitializer<S> for ConcolicFeedback<'_> {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ConcolicFeedback<'_>
where
S: State,
OT: MatchName,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &<S as UsesInput>::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
if let Some(metadata) = observers
.get(&self.observer_handle)
.map(ConcolicObserver::create_metadata_from_current_map)
@ -91,17 +72,4 @@ where
}
Ok(())
}
fn discard_metadata(
&mut self,
_state: &mut S,
_input: &<S as UsesInput>::Input,
) -> Result<(), Error> {
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
}

View File

@ -1,135 +1,97 @@
use alloc::{borrow::Cow, string::String};
use core::{
fmt::{self, Debug, Formatter},
marker::PhantomData,
};
use core::fmt::{self, Debug, Formatter};
use libafl_bolts::Named;
use serde::{Deserialize, Serialize};
use crate::{
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, FeedbackFactory},
inputs::Input,
observers::ObserversTuple,
state::State,
feedbacks::{Feedback, FeedbackFactory, StateInitializer},
Error,
};
/// A [`CustomFilenameToTestcaseFeedback`] takes a closure which returns a filename for the testcase.
///
/// Type which can generate a custom filename for a given input/state pair
pub trait CustomFilenameGenerator<I, S> {
/// Sets the name of the provided [`Testcase`] based on the state and input
fn set_name(&mut self, state: &mut S, testcase: &mut Testcase<I>) -> Result<String, Error>;
}
// maintain compatibility with old impls
impl<I, F, S> CustomFilenameGenerator<I, S> for F
where
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error>,
{
fn set_name(&mut self, state: &mut S, testcase: &mut Testcase<I>) -> Result<String, Error> {
self(state, testcase)
}
}
/// A [`CustomFilenameToTestcaseFeedback`] takes a [`CustomFilenameGenerator`] which returns a
/// filename for the testcase.
/// Is never interesting (use with an Eager OR).
///
/// Note: Use only in conjunction with a `Corpus` type that writes to disk.
/// Note: If used as part of the `Objective` chain, then it will only apply to testcases which are
/// `Objectives`, vice versa for `Feedback`.
#[derive(Serialize, Deserialize)]
pub struct CustomFilenameToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error>,
{
/// Closure that returns the filename.
func: F,
phantomm: PhantomData<(I, S)>,
pub struct CustomFilenameToTestcaseFeedback<N> {
/// Generator that returns the filename.
generator: N,
}
impl<F, I, S> CustomFilenameToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error>,
{
impl<N> CustomFilenameToTestcaseFeedback<N> {
/// Create a new [`CustomFilenameToTestcaseFeedback`].
pub fn new(func: F) -> Self {
pub fn new(generator: N) -> Self {
Self { generator }
}
}
impl<N, T> FeedbackFactory<CustomFilenameToTestcaseFeedback<N>, T>
for CustomFilenameToTestcaseFeedback<N>
where
N: Clone,
{
fn create_feedback(&self, _ctx: &T) -> CustomFilenameToTestcaseFeedback<N> {
Self {
func,
phantomm: PhantomData,
generator: self.generator.clone(),
}
}
}
impl<F, I, S, T> FeedbackFactory<CustomFilenameToTestcaseFeedback<F, I, S>, T>
for CustomFilenameToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error> + Clone,
{
fn create_feedback(&self, _ctx: &T) -> CustomFilenameToTestcaseFeedback<F, I, S> {
Self {
func: self.func.clone(),
phantomm: self.phantomm,
}
}
}
impl<F, I, S> Named for CustomFilenameToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error>,
{
impl<N> Named for CustomFilenameToTestcaseFeedback<N> {
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("CustomFilenameToTestcaseFeedback");
&NAME
}
}
impl<F, I, S> Debug for CustomFilenameToTestcaseFeedback<F, I, S>
where
I: Input,
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<I>) -> Result<String, Error>,
{
impl<N> Debug for CustomFilenameToTestcaseFeedback<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("CustomFilenameToTestcaseFeedback")
.finish_non_exhaustive()
}
}
impl<F, I, S> Feedback<S> for CustomFilenameToTestcaseFeedback<F, I, S>
impl<N, S> StateInitializer<S> for CustomFilenameToTestcaseFeedback<N> {}
impl<EM, I, OT, N, S> Feedback<EM, I, OT, S> for CustomFilenameToTestcaseFeedback<N>
where
S: State<Input = I>,
F: FnMut(&mut S, &mut Testcase<S::Input>) -> Result<String, Error>,
I: Input,
N: CustomFilenameGenerator<I, S>,
{
#[allow(clippy::wrong_self_convention)]
#[inline]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
{
Ok(false)
}
fn append_metadata<EM, OT>(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<<S>::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
*testcase.filename_mut() = Some((self.func)(state, testcase)?);
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
#[inline]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
fn append_metadata(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
*testcase.filename_mut() = Some(self.generator.set_name(state, testcase)?);
Ok(())
}
}

View File

@ -2,10 +2,7 @@
//!
use alloc::borrow::Cow;
use core::{
fmt::{self, Debug, Formatter},
marker::PhantomData,
};
use core::fmt::{self, Debug, Formatter};
use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
@ -16,13 +13,9 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err;
use crate::{
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, FeedbackFactory},
inputs::Input,
observers::{Observer, ObserversTuple},
state::State,
Error, HasMetadata,
feedbacks::{Feedback, FeedbackFactory, StateInitializer},
Error,
};
/// The result of a differential test between two observers.
@ -51,12 +44,24 @@ impl DiffResult {
}
}
/// A [`DiffFeedback`] compares the content of two [`Observer`]s using the given compare function.
#[derive(Serialize, Deserialize)]
pub struct DiffFeedback<F, I, O1, O2, S>
/// Compares two [`crate::observers::Observer`]s to see if the result should be denoted as equal
pub trait DiffComparator<O1, O2> {
/// Performs the comparison between two [`crate::observers::Observer`]s
fn compare(&mut self, first: &O1, second: &O2) -> DiffResult;
}
impl<F, O1, O2> DiffComparator<O1, O2> for F
where
F: FnMut(&O1, &O2) -> DiffResult,
F: Fn(&O1, &O2) -> DiffResult,
{
fn compare(&mut self, first: &O1, second: &O2) -> DiffResult {
self(first, second)
}
}
/// A [`DiffFeedback`] compares the content of two observers using the given compare function.
#[derive(Serialize, Deserialize)]
pub struct DiffFeedback<C, O1, O2> {
/// This feedback's name
name: Cow<'static, str>,
/// The first observer to compare against
@ -66,19 +71,17 @@ where
// The previous run's result of `Self::is_interesting`
#[cfg(feature = "track_hit_feedbacks")]
last_result: Option<bool>,
/// The function used to compare the two observers
compare_fn: F,
phantomm: PhantomData<(I, S)>,
/// The comparator used to compare the two observers
comparator: C,
}
impl<F, I, O1, O2, S> DiffFeedback<F, I, O1, O2, S>
impl<C, O1, O2> DiffFeedback<C, O1, O2>
where
F: FnMut(&O1, &O2) -> DiffResult,
O1: Named,
O2: Named,
{
/// Create a new [`DiffFeedback`] using two observers and a test function.
pub fn new(name: &'static str, o1: &O1, o2: &O2, compare_fn: F) -> Result<Self, Error> {
pub fn new(name: &'static str, o1: &O1, o2: &O2, comparator: C) -> Result<Self, Error> {
let o1_ref = o1.handle();
let o2_ref = o2.handle();
if o1_ref.name() == o2_ref.name() {
@ -93,51 +96,38 @@ where
name: Cow::from(name),
#[cfg(feature = "track_hit_feedbacks")]
last_result: None,
compare_fn,
phantomm: PhantomData,
comparator,
})
}
}
}
impl<F, I, O1, O2, S, T> FeedbackFactory<DiffFeedback<F, I, O1, O2, S>, T>
for DiffFeedback<F, I, O1, O2, S>
impl<C, O1, O2, T> FeedbackFactory<DiffFeedback<C, O1, O2>, T> for DiffFeedback<C, O1, O2>
where
F: FnMut(&O1, &O2) -> DiffResult + Clone,
I: Input,
O1: Observer<S::Input, S> + Named,
O2: Observer<S::Input, S> + Named,
S: HasMetadata + State<Input = I>,
C: Clone,
{
fn create_feedback(&self, _ctx: &T) -> DiffFeedback<F, I, O1, O2, S> {
fn create_feedback(&self, _ctx: &T) -> DiffFeedback<C, O1, O2> {
Self {
name: self.name.clone(),
o1_ref: self.o1_ref.clone(),
o2_ref: self.o2_ref.clone(),
compare_fn: self.compare_fn.clone(),
comparator: self.comparator.clone(),
#[cfg(feature = "track_hit_feedbacks")]
last_result: None,
phantomm: self.phantomm,
}
}
}
impl<F, I, O1, O2, S> Named for DiffFeedback<F, I, O1, O2, S>
where
F: FnMut(&O1, &O2) -> DiffResult,
O1: Named,
O2: Named,
{
impl<C, O1, O2> Named for DiffFeedback<C, O1, O2> {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<F, I, O1, O2, S> Debug for DiffFeedback<F, I, O1, O2, S>
impl<C, O1, O2> Debug for DiffFeedback<C, O1, O2>
where
F: FnMut(&O1, &O2) -> DiffResult,
O1: Named,
O2: Named,
O1: Debug,
O2: Debug,
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("DiffFeedback")
@ -148,27 +138,22 @@ where
}
}
impl<F, I, O1, O2, S> Feedback<S> for DiffFeedback<F, I, O1, O2, S>
impl<C, O1, O2, S> StateInitializer<S> for DiffFeedback<C, O1, O2> {}
impl<C, EM, I, O1, O2, OT, S> Feedback<EM, I, OT, S> for DiffFeedback<C, O1, O2>
where
F: FnMut(&O1, &O2) -> DiffResult,
I: Input,
S: HasMetadata + State<Input = I>,
O1: Observer<S::Input, S>,
O2: Observer<S::Input, S>,
OT: MatchName,
C: DiffComparator<O1, O2>,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S> + MatchName,
{
) -> Result<bool, Error> {
fn err(name: &str) -> Error {
Error::illegal_argument(format!("DiffFeedback: observer {name} not found"))
}
@ -178,7 +163,7 @@ where
let o2: &O2 = observers
.get(&self.o2_ref)
.ok_or_else(|| err(self.o2_ref.name()))?;
let res = (self.compare_fn)(o1, o2) == DiffResult::Diff;
let res = self.comparator.compare(o1, o2) == DiffResult::Diff;
#[cfg(feature = "track_hit_feedbacks")]
{
self.last_result = Some(res);
@ -195,25 +180,24 @@ where
#[cfg(test)]
mod tests {
use alloc::borrow::Cow;
use core::marker::PhantomData;
use libafl_bolts::{tuples::tuple_list, Named};
use crate::{
events::EventFirer,
events::NopEventManager,
executors::ExitKind,
feedbacks::{differential::DiffResult, DiffFeedback, Feedback},
inputs::BytesInput,
observers::Observer,
state::{NopState, State, UsesState},
state::NopState,
};
#[derive(Debug)]
struct NopObserver {
struct DummyObserver {
name: Cow<'static, str>,
value: bool,
}
impl NopObserver {
impl DummyObserver {
fn new(name: &'static str, value: bool) -> Self {
Self {
name: Cow::from(name),
@ -221,72 +205,45 @@ mod tests {
}
}
}
impl<I, S> Observer<I, S> for NopObserver {}
impl PartialEq for NopObserver {
impl<I, S> Observer<I, S> for DummyObserver {}
impl PartialEq for DummyObserver {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl Named for NopObserver {
impl Named for DummyObserver {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
struct NopEventFirer<S> {
phantom: PhantomData<S>,
}
impl<S> UsesState for NopEventFirer<S>
where
S: State,
{
type State = S;
}
impl<S> EventFirer for NopEventFirer<S>
where
S: State,
{
fn should_send(&self) -> bool {
true
}
fn fire(
&mut self,
_state: &mut S,
_event: crate::events::Event<S::Input>,
) -> Result<(), crate::Error> {
Ok(())
fn comparator(o1: &DummyObserver, o2: &DummyObserver) -> DiffResult {
if o1 == o2 {
DiffResult::Equal
} else {
DiffResult::Diff
}
}
fn test_diff(should_equal: bool) {
let mut nop_state = NopState::new();
let mut nop_state: NopState<BytesInput> = NopState::new();
let o1 = NopObserver::new("o1", true);
let o2 = NopObserver::new("o2", should_equal);
let o1 = DummyObserver::new("o1", true);
let o2 = DummyObserver::new("o2", should_equal);
let mut diff_feedback = DiffFeedback::new("diff_feedback", &o1, &o2, |o1, o2| {
if o1 == o2 {
DiffResult::Equal
} else {
DiffResult::Diff
}
})
.unwrap();
let mut diff_feedback = DiffFeedback::new("diff_feedback", &o1, &o2, comparator).unwrap();
let observers = tuple_list![o1, o2];
assert_eq!(
!should_equal,
diff_feedback
.is_interesting(
&mut nop_state,
&mut NopEventFirer {
phantom: PhantomData
},
&BytesInput::new(vec![0]),
&observers,
&ExitKind::Ok
)
.unwrap()
DiffFeedback::<_, _, _>::is_interesting(
&mut diff_feedback,
&mut nop_state,
&mut NopEventManager::<NopState<BytesInput>>::default(),
&BytesInput::new(vec![0]),
&observers,
&ExitKind::Ok
)
.unwrap()
);
}

View File

@ -3,46 +3,34 @@ use core::{fmt::Debug, hash::Hash};
use hashbrown::HashSet;
use libafl_bolts::{
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
Error, HasRefCnt, Named,
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
observers::{ListObserver, ObserversTuple},
state::State,
feedbacks::{Feedback, StateInitializer},
observers::ListObserver,
HasNamedMetadata,
};
/// The metadata to remember past observed value
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: DeserializeOwned")]
#[cfg_attr(
any(not(feature = "serdeany_autoreg"), miri),
allow(clippy::unsafe_derive_deserialize)
)]
pub struct ListFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize + Eq + Hash,
{
#[serde(bound = "T: Eq + Hash + for<'a> Deserialize<'a> + Serialize")]
pub struct ListFeedbackMetadata<T> {
/// Contains the information of past observed set of values.
pub set: HashSet<T>,
/// A refcount used to know when we can remove this metadata
pub tcref: isize,
}
impl<T> ListFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize + Eq + Hash,
{
impl<T> ListFeedbackMetadata<T> {
/// The constructor
#[must_use]
pub fn new() -> Self {
Self {
set: HashSet::<T>::new(),
set: HashSet::new(),
tcref: 0,
}
}
@ -54,10 +42,7 @@ where
}
}
impl<T> HasRefCnt for ListFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize + Eq + Hash,
{
impl<T> HasRefCnt for ListFeedbackMetadata<T> {
fn refcnt(&self) -> isize {
self.tcref
}
@ -69,10 +54,7 @@ where
/// Consider interesting a testcase if the list in `ListObserver` is not empty.
#[derive(Clone, Debug)]
pub struct ListFeedback<T>
where
T: Hash + Eq,
{
pub struct ListFeedback<T> {
observer_handle: Handle<ListObserver<T>>,
novelty: HashSet<T>,
}
@ -82,30 +64,32 @@ libafl_bolts::impl_serdeany!(
<u8>,<u16>,<u32>,<u64>,<i8>,<i16>,<i32>,<i64>,<bool>,<char>,<usize>
);
impl<S, T> Feedback<S> for ListFeedback<T>
impl<S, T> StateInitializer<S> for ListFeedback<T>
where
S: State + HasNamedMetadata,
S: HasNamedMetadata,
T: Debug + Serialize + Hash + Eq + DeserializeOwned + Default + Copy + 'static,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
// eprintln!("self.name {:#?}", &self.name);
state.add_named_metadata(self.name(), ListFeedbackMetadata::<T>::default());
Ok(())
}
}
impl<EM, I, OT, S, T> Feedback<EM, I, OT, S> for ListFeedback<T>
where
OT: MatchName,
S: HasNamedMetadata,
T: Debug + Serialize + Hash + Eq + DeserializeOwned + Default + Copy + 'static,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
// TODO Replace with match_name_type when stable
) -> Result<bool, Error> {
let observer = observers.get(&self.observer_handle).unwrap();
// TODO register the list content in a testcase metadata
self.novelty.clear();
@ -122,17 +106,18 @@ where
Ok(!self.novelty.is_empty())
}
fn append_metadata<EM, OT>(
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(!self.novelty.is_empty())
}
fn append_metadata(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
_testcase: &mut crate::corpus::Testcase<<S>::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
_testcase: &mut crate::corpus::Testcase<I>,
) -> Result<(), Error> {
let history_set = state
.named_metadata_map_mut()
.get_mut::<ListFeedbackMetadata<T>>(self.name())
@ -143,32 +128,22 @@ where
}
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(!self.novelty.is_empty())
}
}
impl<T> Named for ListFeedback<T>
where
T: Debug + Serialize + Hash + Eq + DeserializeOwned,
{
impl<T> Named for ListFeedback<T> {
#[inline]
fn name(&self) -> &Cow<'static, str> {
self.observer_handle.name()
}
}
impl<T> ListFeedback<T>
where
T: Debug + Serialize + Hash + Eq + DeserializeOwned,
{
impl<T> ListFeedback<T> {
/// Creates a new [`ListFeedback`], deciding if the given [`ListObserver`] value of a run is interesting.
#[must_use]
pub fn new(observer: &ListObserver<T>) -> Self {
Self {
observer_handle: observer.handle(),
novelty: HashSet::<T>::new(),
novelty: HashSet::new(),
}
}
}

View File

@ -12,7 +12,7 @@ use core::{
#[rustversion::nightly]
use libafl_bolts::AsSlice;
use libafl_bolts::{
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
AsIter, HasRefCnt, Named,
};
use num_traits::PrimInt;
@ -24,37 +24,33 @@ use crate::{
corpus::Testcase,
events::{Event, EventFirer},
executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle},
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
inputs::UsesInput,
monitors::{AggregatorOps, UserStats, UserStatsValue},
observers::{CanTrack, MapObserver, Observer, ObserversTuple},
state::State,
observers::{CanTrack, MapObserver},
Error, HasMetadata, HasNamedMetadata,
};
/// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from (`HitcountsMapObserver`)[`crate::observers::HitcountsMapObserver`].
pub type AflMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, OrReducer, T>;
pub type AflMapFeedback<C, O> = MapFeedback<C, DifferentIsNovel, O, OrReducer>;
/// A [`MapFeedback`] that strives to maximize the map contents.
pub type MaxMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, MaxReducer, T>;
pub type MaxMapFeedback<C, O> = MapFeedback<C, DifferentIsNovel, O, MaxReducer>;
/// A [`MapFeedback`] that strives to minimize the map contents.
pub type MinMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, MinReducer, T>;
pub type MinMapFeedback<C, O> = MapFeedback<C, DifferentIsNovel, O, MinReducer>;
/// A [`MapFeedback`] that always returns `true` for `is_interesting`. Useful for tracing all executions.
pub type AlwaysInterestingMapFeedback<C, O, T> = MapFeedback<C, AllIsNovel, O, NopReducer, T>;
pub type AlwaysInterestingMapFeedback<C, O> = MapFeedback<C, AllIsNovel, O, NopReducer>;
/// A [`MapFeedback`] that strives to maximize the map contents,
/// but only, if a value is larger than `pow2` of the previous.
pub type MaxMapPow2Feedback<C, O, T> = MapFeedback<C, NextPow2IsNovel, O, MaxReducer, T>;
pub type MaxMapPow2Feedback<C, O> = MapFeedback<C, NextPow2IsNovel, O, MaxReducer>;
/// A [`MapFeedback`] that strives to maximize the map contents,
/// but only, if a value is either `T::one()` or `T::max_value()`.
pub type MaxMapOneOrFilledFeedback<C, O, T> = MapFeedback<C, OneOrFilledIsNovel, O, MaxReducer, T>;
pub type MaxMapOneOrFilledFeedback<C, O> = MapFeedback<C, OneOrFilledIsNovel, O, MaxReducer>;
/// A `Reducer` function is used to aggregate values for the novelty search
pub trait Reducer<T>: 'static
where
T: Default + Copy + 'static,
{
pub trait Reducer<T> {
/// Reduce two values to one value, with the current [`Reducer`].
fn reduce(first: T, second: T) -> T;
}
@ -65,7 +61,7 @@ pub struct OrReducer {}
impl<T> Reducer<T> for OrReducer
where
T: BitOr<Output = T> + Default + Copy + 'static + PartialOrd,
T: BitOr<Output = T>,
{
#[inline]
fn reduce(history: T, new: T) -> T {
@ -79,7 +75,7 @@ pub struct AndReducer {}
impl<T> Reducer<T> for AndReducer
where
T: BitAnd<Output = T> + Default + Copy + 'static + PartialOrd,
T: BitAnd<Output = T>,
{
#[inline]
fn reduce(history: T, new: T) -> T {
@ -91,10 +87,7 @@ where
#[derive(Clone, Debug)]
pub struct NopReducer {}
impl<T> Reducer<T> for NopReducer
where
T: Default + Copy + 'static,
{
impl<T> Reducer<T> for NopReducer {
#[inline]
fn reduce(_history: T, new: T) -> T {
new
@ -107,7 +100,7 @@ pub struct MaxReducer {}
impl<T> Reducer<T> for MaxReducer
where
T: Default + Copy + 'static + PartialOrd,
T: PartialOrd,
{
#[inline]
fn reduce(first: T, second: T) -> T {
@ -125,7 +118,7 @@ pub struct MinReducer {}
impl<T> Reducer<T> for MinReducer
where
T: Default + Copy + 'static + PartialOrd,
T: PartialOrd,
{
#[inline]
fn reduce(first: T, second: T) -> T {
@ -138,10 +131,7 @@ where
}
/// A `IsNovel` function is used to discriminate if a reduced value is considered novel.
pub trait IsNovel<T>: 'static
where
T: Default + Copy + 'static,
{
pub trait IsNovel<T> {
/// If a new value in the [`MapFeedback`] was found,
/// this filter can decide if the result is considered novel or not.
fn is_novel(old: T, new: T) -> bool;
@ -225,11 +215,8 @@ where
}
/// A testcase metadata holding a list of indexes of a map
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(
any(not(feature = "serdeany_autoreg"), miri),
allow(clippy::unsafe_derive_deserialize)
)] // for SerdeAny
#[derive(Debug, Serialize, Deserialize)]
#[allow(clippy::unsafe_derive_deserialize)] // for SerdeAny
pub struct MapIndexesMetadata {
/// The list of indexes.
pub list: Vec<usize>,
@ -274,10 +261,7 @@ impl MapIndexesMetadata {
/// A testcase metadata holding a list of indexes of a map
#[derive(Debug, Serialize, Deserialize)]
#[cfg_attr(
any(not(feature = "serdeany_autoreg"), miri),
allow(clippy::unsafe_derive_deserialize)
)] // for SerdeAny
#[allow(clippy::unsafe_derive_deserialize)] // for SerdeAny
pub struct MapNoveltiesMetadata {
/// A `list` of novelties.
pub list: Vec<usize>,
@ -312,15 +296,8 @@ impl MapNoveltiesMetadata {
/// The state of [`MapFeedback`]
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: DeserializeOwned")]
#[cfg_attr(
any(not(feature = "serdeany_autoreg"), miri),
allow(clippy::unsafe_derive_deserialize)
)] // for SerdeAny
pub struct MapFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize,
{
#[allow(clippy::unsafe_derive_deserialize)] // for SerdeAny
pub struct MapFeedbackMetadata<T> {
/// Contains information about untouched entries
pub history_map: Vec<T>,
/// Tells us how many non-initial entries there are in `history_map`
@ -328,7 +305,7 @@ where
}
libafl_bolts::impl_serdeany!(
MapFeedbackMetadata<T: Debug + Default + Copy + 'static + Serialize + DeserializeOwned>,
MapFeedbackMetadata<T: 'static + Debug + Serialize + DeserializeOwned>,
<u8>,<u16>,<u32>,<u64>,<i8>,<i16>,<i32>,<i64>,<f32>,<f64>,<bool>,<char>,<usize>
);
@ -384,7 +361,7 @@ where
/// The most common AFL-like feedback type
#[derive(Clone, Debug)]
pub struct MapFeedback<C, N, O, R, T> {
pub struct MapFeedback<C, N, O, R> {
/// New indexes observed in the last observation
novelties: Option<Vec<usize>>,
/// Name identifier of this instance
@ -397,38 +374,44 @@ pub struct MapFeedback<C, N, O, R, T> {
#[cfg(feature = "track_hit_feedbacks")]
last_result: Option<bool>,
/// Phantom Data of Reducer
phantom: PhantomData<(C, N, O, R, T)>,
#[allow(clippy::type_complexity)]
phantom: PhantomData<fn() -> (N, O, R)>,
}
impl<C, N, O, R, S, T> Feedback<S> for MapFeedback<C, N, O, R, T>
impl<C, N, O, R, S> StateInitializer<S> for MapFeedback<C, N, O, R>
where
N: IsNovel<T>,
O: MapObserver<Entry = T> + for<'it> AsIter<'it, Item = T>,
R: Reducer<T>,
S: State + HasNamedMetadata,
T: Default + Copy + Serialize + for<'de> Deserialize<'de> + PartialEq + Debug + 'static,
C: CanTrack + AsRef<O> + Named,
O: MapObserver,
O::Entry: 'static + Default + Debug + DeserializeOwned + Serialize,
S: HasNamedMetadata,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
// Initialize `MapFeedbackMetadata` with an empty vector and add it to the state.
// The `MapFeedbackMetadata` would be resized on-demand in `is_interesting`
state.add_named_metadata(&self.name, MapFeedbackMetadata::<T>::default());
state.add_named_metadata(&self.name, MapFeedbackMetadata::<O::Entry>::default());
Ok(())
}
}
impl<C, EM, I, N, O, OT, R, S> Feedback<EM, I, OT, S> for MapFeedback<C, N, O, R>
where
C: CanTrack + AsRef<O>,
EM: EventFirer<State = S>,
N: IsNovel<O::Entry>,
O: MapObserver + for<'it> AsIter<'it, Item = O::Entry>,
O::Entry: 'static + Default + Debug + DeserializeOwned + Serialize,
OT: MatchName,
R: Reducer<O::Entry>,
S: HasNamedMetadata + UsesInput, // delete me
{
#[rustversion::nightly]
default fn is_interesting<EM, OT>(
default fn is_interesting(
&mut self,
state: &mut S,
manager: &mut EM,
input: &S::Input,
input: &I,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
let res = self.is_interesting_default(state, manager, input, observers, exit_kind);
#[cfg(feature = "track_hit_feedbacks")]
{
@ -438,18 +421,14 @@ where
}
#[rustversion::not(nightly)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
state: &mut S,
manager: &mut EM,
input: &<S as UsesInput>::Input,
input: &I,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<<S as UsesInput>::Input, S>,
{
) -> Result<bool, Error> {
let res = self.is_interesting_default(state, manager, input, observers, exit_kind);
#[cfg(feature = "track_hit_feedbacks")]
@ -459,17 +438,18 @@ where
Ok(res)
}
fn append_metadata<EM, OT>(
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
self.last_result.ok_or(premature_last_result_err())
}
fn append_metadata(
&mut self,
state: &mut S,
manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
if let Some(novelties) = self.novelties.as_mut().map(core::mem::take) {
let meta = MapNoveltiesMetadata::new(novelties);
testcase.add_metadata(meta);
@ -478,7 +458,7 @@ where
let initial = observer.initial();
let map_state = state
.named_metadata_map_mut()
.get_mut::<MapFeedbackMetadata<T>>(&self.name)
.get_mut::<MapFeedbackMetadata<O::Entry>>(&self.name)
.unwrap();
let len = observer.len();
if map_state.history_map.len() < len {
@ -551,35 +531,28 @@ where
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
self.last_result.ok_or(premature_last_result_err())
}
}
/// Specialize for the common coverage map size, maximization of u8s
#[rustversion::nightly]
impl<C, O, S> Feedback<S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer, u8>
impl<C, O, EM, I, OT, S> Feedback<EM, I, OT, S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer>
where
C: CanTrack + AsRef<O>,
EM: EventFirer<State = S>,
O: MapObserver<Entry = u8> + for<'a> AsSlice<'a, Entry = u8> + for<'a> AsIter<'a, Item = u8>,
S: State + HasNamedMetadata,
C: CanTrack + AsRef<O> + Observer<S::Input, S>,
OT: MatchName,
S: HasNamedMetadata + UsesInput,
{
#[allow(clippy::wrong_self_convention)]
#[allow(clippy::needless_range_loop)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
// 128 bits vectors
type VectorType = core::simd::u8x16;
@ -679,18 +652,14 @@ where
}
}
impl<C, N, O, R, T> Named for MapFeedback<C, N, O, R, T> {
impl<C, N, O, R> Named for MapFeedback<C, N, O, R> {
#[inline]
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<C, N, O, R, T> HasObserverHandle for MapFeedback<C, N, O, R, T>
where
O: Named,
C: AsRef<O>,
{
impl<C, N, O, R> HasObserverHandle for MapFeedback<C, N, O, R> {
type Observer = C;
#[inline]
@ -708,14 +677,9 @@ fn create_stats_name(name: &Cow<'static, str>) -> Cow<'static, str> {
}
}
impl<C, N, O, R, T> MapFeedback<C, N, O, R, T>
impl<C, N, O, R> MapFeedback<C, N, O, R>
where
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsIter<'it, Item = T>,
N: IsNovel<T>,
C: CanTrack + AsRef<O> + Named,
C: CanTrack + Named + AsRef<O>,
{
/// Create new `MapFeedback`
#[must_use]
@ -747,22 +711,30 @@ where
phantom: PhantomData,
}
}
}
impl<C, N, O, R> MapFeedback<C, N, O, R>
where
R: Reducer<O::Entry>,
O: MapObserver + for<'it> AsIter<'it, Item = O::Entry>,
O::Entry: 'static + Debug + Serialize + DeserializeOwned,
N: IsNovel<O::Entry>,
C: AsRef<O>,
{
#[allow(clippy::wrong_self_convention)]
#[allow(clippy::needless_range_loop)]
#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_interesting_default<EM, S, OT>(
fn is_interesting_default<EM, I, OT, S>(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> bool
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
S: UsesInput + HasNamedMetadata,
S: HasNamedMetadata,
OT: MatchName,
{
let mut interesting = false;
// TODO Replace with match_name_type when stable
@ -770,7 +742,7 @@ where
let map_state = state
.named_metadata_map_mut()
.get_mut::<MapFeedbackMetadata<T>>(&self.name)
.get_mut::<MapFeedbackMetadata<O::Entry>>(&self.name)
.unwrap();
let len = observer.len();
if map_state.history_map.len() < len {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
//! Nautilus grammar mutator, see <https://github.com/nautilus-fuzz/nautilus>
use alloc::{borrow::Cow, string::String};
use core::{fmt::Debug, marker::PhantomData};
use core::fmt::Debug;
use std::fs::create_dir_all;
use libafl_bolts::Named;
@ -9,13 +9,11 @@ use serde::{Deserialize, Serialize};
use crate::{
common::nautilus::grammartec::{chunkstore::ChunkStore, context::Context},
corpus::{Corpus, Testcase},
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
feedbacks::{Feedback, StateInitializer},
generators::NautilusContext,
inputs::NautilusInput,
observers::ObserversTuple,
state::{HasCorpus, State},
state::HasCorpus,
Error, HasMetadata,
};
@ -51,66 +49,52 @@ impl NautilusChunksMetadata {
}
/// A nautilus feedback for grammar fuzzing
pub struct NautilusFeedback<'a, S> {
#[derive(Debug)]
pub struct NautilusFeedback<'a> {
ctx: &'a Context,
phantom: PhantomData<S>,
}
impl<S> Debug for NautilusFeedback<'_, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "NautilusFeedback {{}}")
}
}
impl<'a, S> NautilusFeedback<'a, S> {
impl<'a> NautilusFeedback<'a> {
/// Create a new [`NautilusFeedback`]
#[must_use]
pub fn new(context: &'a NautilusContext) -> Self {
Self {
ctx: &context.ctx,
phantom: PhantomData,
}
Self { ctx: &context.ctx }
}
}
impl<'a, S> Named for NautilusFeedback<'a, S> {
impl<'a> Named for NautilusFeedback<'a> {
fn name(&self) -> &Cow<'static, str> {
static NAME: Cow<'static, str> = Cow::Borrowed("NautilusFeedback");
&NAME
}
}
impl<'a, S> Feedback<S> for NautilusFeedback<'a, S>
impl<'a, S> StateInitializer<S> for NautilusFeedback<'a> {}
impl<'a, EM, OT, S> Feedback<EM, NautilusInput, OT, S> for NautilusFeedback<'a>
where
S: HasMetadata + HasCorpus + State<Input = NautilusInput>,
S: HasMetadata + HasCorpus,
S::Corpus: Corpus<Input = NautilusInput>,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &NautilusInput,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<NautilusInput, S>,
{
) -> Result<bool, Error> {
Ok(false)
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<NautilusInput, S>,
{
testcase: &mut Testcase<NautilusInput>,
) -> Result<(), Error> {
state.corpus().load_input_into(testcase)?;
let input = testcase.input().as_ref().unwrap().clone();
let meta = state

View File

@ -1,11 +1,11 @@
//! The ``NewHashFeedback`` uses the backtrace hash and a hashset to only keep novel cases
use alloc::{borrow::Cow, string::ToString};
use std::{fmt::Debug, marker::PhantomData};
use std::fmt::Debug;
use hashbrown::HashSet;
use libafl_bolts::{
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named,
};
use serde::{Deserialize, Serialize};
@ -13,12 +13,9 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err;
use crate::{
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle},
inputs::UsesInput,
observers::{ObserverWithHashField, ObserversTuple},
state::State,
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
observers::ObserverWithHashField,
Error, HasNamedMetadata,
};
@ -38,7 +35,7 @@ pub trait HashSetState<T> {
#[allow(clippy::unsafe_derive_deserialize)]
pub struct NewHashFeedbackMetadata {
/// Contains information about untouched entries
pub hash_set: HashSet<u64>,
hash_set: HashSet<u64>,
}
#[rustfmt::skip]
@ -64,6 +61,17 @@ impl NewHashFeedbackMetadata {
self.hash_set.clear();
Ok(())
}
/// Gets the associated [`HashSet`] being used to track hashes
#[must_use]
pub fn hash_set(&self) -> &HashSet<u64> {
&self.hash_set
}
/// Gets the associated [`HashSet`] being used to track hashes, mutably
pub fn hash_set_mut(&mut self) -> &mut HashSet<u64> {
&mut self.hash_set
}
}
impl HashSetState<u64> for NewHashFeedbackMetadata {
@ -82,7 +90,7 @@ impl HashSetState<u64> for NewHashFeedbackMetadata {
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NewHashFeedback<O, S> {
pub struct NewHashFeedback<O> {
name: Cow<'static, str>,
o_ref: Handle<O>,
/// Initial capacity of hash set
@ -90,13 +98,11 @@ pub struct NewHashFeedback<O, S> {
#[cfg(feature = "track_hit_feedbacks")]
// The previous run's result of `Self::is_interesting`
last_result: Option<bool>,
phantom: PhantomData<S>,
}
impl<O, S> Feedback<S> for NewHashFeedback<O, S>
impl<O, S> StateInitializer<S> for NewHashFeedback<O>
where
O: ObserverWithHashField + Named,
S: State + HasNamedMetadata,
S: HasNamedMetadata,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_named_metadata(
@ -105,20 +111,23 @@ where
);
Ok(())
}
}
impl<O, EM, I, OT, S> Feedback<EM, I, OT, S> for NewHashFeedback<O>
where
O: ObserverWithHashField,
OT: MatchName,
S: HasNamedMetadata,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &<S as UsesInput>::Input,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
let observer = observers
.get(&self.o_ref)
.expect("A NewHashFeedback needs a BacktraceObserver");
@ -147,14 +156,14 @@ where
}
}
impl<O, S> Named for NewHashFeedback<O, S> {
impl<O> Named for NewHashFeedback<O> {
#[inline]
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<O, S> HasObserverHandle for NewHashFeedback<O, S> {
impl<O> HasObserverHandle for NewHashFeedback<O> {
type Observer = O;
#[inline]
@ -169,9 +178,9 @@ impl<O, S> HasObserverHandle for NewHashFeedback<O, S> {
/// runs of the target, producing many different feedbacks.
const DEFAULT_CAPACITY: usize = 4096;
impl<O, S> NewHashFeedback<O, S>
impl<O> NewHashFeedback<O>
where
O: ObserverWithHashField + Named,
O: Named,
{
/// Returns a new [`NewHashFeedback`].
#[must_use]
@ -189,7 +198,6 @@ where
capacity,
#[cfg(feature = "track_hit_feedbacks")]
last_result: None,
phantom: PhantomData,
}
}
}

View File

@ -4,18 +4,15 @@ use alloc::{borrow::Cow, string::String};
use libafl_bolts::{
impl_serdeany,
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named,
};
use serde::{Deserialize, Serialize};
use crate::{
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
observers::{ObserversTuple, StdErrObserver, StdOutObserver},
state::State,
feedbacks::{Feedback, StateInitializer},
observers::{StdErrObserver, StdOutObserver},
Error, HasMetadata,
};
@ -35,40 +32,26 @@ pub struct StdOutToMetadataFeedback {
o_ref: Handle<StdOutObserver>,
}
impl<S> Feedback<S> for StdOutToMetadataFeedback
impl<S> StateInitializer<S> for StdOutToMetadataFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for StdOutToMetadataFeedback
where
S: State,
OT: MatchName,
{
#[allow(clippy::wrong_self_convention)]
#[inline]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
/// Append to the testcase the generated metadata in case of a new corpus item.
#[inline]
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
let observer = observers
.get(&self.o_ref)
.ok_or(Error::illegal_state("StdOutObserver is missing"))?;
@ -84,17 +67,6 @@ where
Ok(())
}
/// Discard the stored metadata in case that the testcase is not added to the corpus.
#[inline]
fn discard_metadata(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
}
impl Named for StdOutToMetadataFeedback {
@ -130,40 +102,26 @@ pub struct StdErrToMetadataFeedback {
o_ref: Handle<StdErrObserver>,
}
impl<S> Feedback<S> for StdErrToMetadataFeedback
impl<S> StateInitializer<S> for StdErrToMetadataFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for StdErrToMetadataFeedback
where
S: State,
OT: MatchName,
{
#[allow(clippy::wrong_self_convention)]
#[inline]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
/// Append to the testcase the generated metadata in case of a new corpus item.
#[inline]
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,
observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
EM: EventFirer<State = S>,
{
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
let observer = observers
.get(&self.o_ref)
.ok_or(Error::illegal_state("StdErrObserver is missing"))?;
@ -179,16 +137,6 @@ where
Ok(())
}
/// Discard the stored metadata in case that the testcase is not added to the corpus.
#[inline]
fn discard_metadata(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
Ok(false)
}
}
impl Named for StdErrToMetadataFeedback {

View File

@ -9,17 +9,18 @@ use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err;
use crate::{
events::EventFirer, executors::ExitKind, feedbacks::Feedback, observers::ObserversTuple,
state::State, HasMetadata,
executors::ExitKind,
feedbacks::{Feedback, StateInitializer},
HasMetadata,
};
/// Constant name of the [`TransferringMetadata`].
pub const TRANSFERRED_FEEDBACK_NAME: Cow<'static, str> =
Cow::Borrowed("transferred_feedback_internal");
/// Metadata which denotes whether we are currently transferring an input.
///
/// Implementors of
/// multi-node communication systems (like [`crate::events::LlmpEventManager`]) should wrap any
/// Implementors of multi-node communication systems (like [`crate::events::LlmpEventManager`]) should wrap any
/// [`crate::EvaluatorObservers::evaluate_input_with_observers`] or
/// [`crate::ExecutionProcessor::process_execution`] calls with setting this metadata to true/false
/// before and after.
@ -52,27 +53,28 @@ impl Named for TransferredFeedback {
}
}
impl<S> Feedback<S> for TransferredFeedback
impl<S> StateInitializer<S> for TransferredFeedback
where
S: HasMetadata + State,
S: HasMetadata,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_metadata(TransferringMetadata { transferring: true });
Ok(())
}
}
fn is_interesting<EM, OT>(
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for TransferredFeedback
where
S: HasMetadata,
{
fn is_interesting(
&mut self,
state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
let res = state.metadata::<TransferringMetadata>()?.transferring;
#[cfg(feature = "track_hit_feedbacks")]
{
@ -80,6 +82,7 @@ where
}
Ok(res)
}
#[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> {
self.last_result.ok_or(premature_last_result_err())

View File

@ -47,7 +47,7 @@ where
/// Holds an feedback
pub trait HasFeedback: UsesState {
/// The feedback type
type Feedback: Feedback<Self::State>;
type Feedback;
/// The feedback
fn feedback(&self) -> &Self::Feedback;
@ -59,7 +59,7 @@ pub trait HasFeedback: UsesState {
/// Holds an objective feedback
pub trait HasObjective: UsesState {
/// The type of the [`Feedback`] used to find objectives for this fuzzer
type Objective: Feedback<Self::State>;
type Objective;
/// The objective feedback
fn objective(&self) -> &Self::Objective;
@ -69,9 +69,9 @@ pub trait HasObjective: UsesState {
}
/// Evaluates if an input is interesting using the feedback
pub trait ExecutionProcessor: UsesState {
pub trait ExecutionProcessor<EM, OT>: UsesState {
/// Check the outcome of the execution, find if it is worth for corpus or objectives
fn check_results<EM, OT>(
fn check_results(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -85,7 +85,7 @@ pub trait ExecutionProcessor: UsesState {
/// Process `ExecuteInputResult`. Add to corpus, solution or ignore
#[allow(clippy::too_many_arguments)]
fn process_execution<EM, OT>(
fn process_execution(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -98,7 +98,7 @@ pub trait ExecutionProcessor: UsesState {
OT: ObserversTuple<<Self as UsesInput>::Input, Self::State>;
/// serialize and send event via manager
fn serialize_and_dispatch<EM, OT>(
fn serialize_and_dispatch(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -112,7 +112,7 @@ pub trait ExecutionProcessor: UsesState {
OT: ObserversTuple<<Self as UsesInput>::Input, Self::State> + Serialize;
/// send event via manager
fn dispatch_event<EM>(
fn dispatch_event(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -125,7 +125,7 @@ pub trait ExecutionProcessor: UsesState {
EM: EventFirer<State = Self::State>;
/// Evaluate if a set of observation channels has an interesting state
fn evaluate_execution<EM, OT>(
fn evaluate_execution(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -140,11 +140,11 @@ pub trait ExecutionProcessor: UsesState {
}
/// Evaluates an input modifying the state of the fuzzer
pub trait EvaluatorObservers<OT>: UsesState + Sized {
pub trait EvaluatorObservers<EM, OT>: UsesState + Sized {
/// Runs the input and triggers observers and feedback,
/// returns if is interesting an (option) the index of the new
/// [`crate::corpus::Testcase`] in the [`crate::corpus::Corpus`]
fn evaluate_input_with_observers<E, EM>(
fn evaluate_input_with_observers<E>(
&mut self,
state: &mut Self::State,
executor: &mut E,
@ -336,8 +336,6 @@ where
impl<CS, F, OF, S> HasFeedback for StdFuzzer<CS, F, OF, S>
where
S: State,
F: Feedback<S>,
OF: Feedback<S>,
{
type Feedback = F;
@ -353,8 +351,6 @@ where
impl<CS, F, OF, S> HasObjective for StdFuzzer<CS, F, OF, S>
where
S: State,
F: Feedback<S>,
OF: Feedback<S>,
{
type Objective = OF;
@ -367,16 +363,16 @@ where
}
}
impl<CS, F, OF, S> ExecutionProcessor for StdFuzzer<CS, F, OF, S>
impl<CS, EM, F, OF, OT, S> ExecutionProcessor<EM, OT> for StdFuzzer<CS, F, OF, S>
where
CS: Scheduler<S::Input, S>,
F: Feedback<S>,
OF: Feedback<S>,
F: Feedback<EM, S::Input, OT, S>,
OF: Feedback<EM, S::Input, OT, S>,
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>(
fn check_results(
&mut self,
state: &mut S,
manager: &mut EM,
@ -420,7 +416,7 @@ where
Ok(res)
}
fn evaluate_execution<EM, OT>(
fn evaluate_execution(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -441,7 +437,7 @@ where
Ok((exec_res, corpus_id))
}
fn serialize_and_dispatch<EM, OT>(
fn serialize_and_dispatch(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -475,7 +471,7 @@ where
Ok(())
}
fn dispatch_event<EM>(
fn dispatch_event(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -527,7 +523,7 @@ where
}
/// Evaluate if a set of observation channels has an interesting state
fn process_execution<EM, OT>(
fn process_execution(
&mut self,
state: &mut Self::State,
manager: &mut EM,
@ -585,19 +581,19 @@ where
}
}
impl<CS, F, OF, OT, S> EvaluatorObservers<OT> for StdFuzzer<CS, F, OF, S>
impl<CS, EM, F, OF, OT, S> EvaluatorObservers<EM, OT> for StdFuzzer<CS, F, OF, S>
where
CS: Scheduler<S::Input, S>,
OT: ObserversTuple<S::Input, S> + Serialize + DeserializeOwned,
F: Feedback<S>,
OF: Feedback<S>,
F: Feedback<EM, S::Input, OT, S>,
OF: Feedback<EM, S::Input, OT, 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]
fn evaluate_input_with_observers<E, EM>(
fn evaluate_input_with_observers<E>(
&mut self,
state: &mut S,
executor: &mut E,
@ -624,8 +620,8 @@ where
E: HasObservers + Executor<EM, Self, State = S>,
E::Observers: ObserversTuple<S::Input, S> + Serialize + DeserializeOwned,
EM: EventFirer<State = S>,
F: Feedback<S>,
OF: Feedback<S>,
F: Feedback<EM, S::Input, E::Observers, S>,
OF: Feedback<EM, S::Input, E::Observers, S>,
S: HasCorpus + HasSolutions + HasExecutions + HasLastFoundTime + State,
S::Corpus: Corpus<Input = S::Input>, //delete me
S::Solutions: Corpus<Input = S::Input>, //delete me
@ -760,8 +756,6 @@ where
CS: Scheduler<S::Input, S>,
E: UsesState<State = S>,
EM: ProgressReporter + EventProcessor<E, Self, State = S>,
F: Feedback<S>,
OF: Feedback<S>,
S: HasExecutions
+ HasMetadata
+ HasCorpus
@ -837,8 +831,6 @@ where
impl<CS, F, OF, S> StdFuzzer<CS, F, OF, S>
where
CS: Scheduler<S::Input, S>,
F: Feedback<<Self as UsesState>::State>,
OF: Feedback<<Self as UsesState>::State>,
S: UsesInput + HasExecutions + HasCorpus + State,
{
/// Create a new `StdFuzzer` with standard behavior.
@ -901,8 +893,6 @@ where
impl<CS, E, EM, F, OF, S> ExecutesInput<E, EM> for StdFuzzer<CS, F, OF, S>
where
CS: Scheduler<S::Input, S>,
F: Feedback<<Self as UsesState>::State>,
OF: Feedback<<Self as UsesState>::State>,
E: Executor<EM, Self, State = S> + HasObservers,
E::Observers: ObserversTuple<<Self as UsesInput>::Input, <Self as UsesState>::State>,
EM: UsesState<State = Self::State>,

View File

@ -48,7 +48,7 @@ pub use owned_map::*;
/// ```
/// # use libafl::corpus::InMemoryCorpus;
/// # use libafl::feedbacks::{Feedback, MapFeedbackMetadata};
/// use libafl::feedbacks::MaxMapFeedback;
/// use libafl::feedbacks::{MaxMapFeedback, StateInitializer};
/// # use libafl::inputs::BytesInput;
/// use libafl::observers::{StdMapObserver, CanTrack};
/// use libafl::schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler};

View File

@ -27,7 +27,7 @@ use crate::{observers::Observer, Error};
/// corpus::{Corpus, InMemoryCorpus, Testcase},
/// events::{EventFirer, NopEventManager},
/// executors::{CommandExecutor, ExitKind},
/// feedbacks::Feedback,
/// feedbacks::{Feedback, StateInitializer},
/// inputs::{BytesInput, UsesInput},
/// mutators::{MutationResult, NopMutator},
/// observers::{ObserversTuple, StdErrObserver, StdOutObserver},
@ -53,21 +53,22 @@ use crate::{observers::Observer, Error};
/// stderr_observer: Handle<StdErrObserver>,
/// }
///
/// impl<S> Feedback<S> for ExportStdXObserver
/// impl<S> StateInitializer<S> for ExportStdXObserver {}
///
///
/// impl<EM, I, OT, S> Feedback<EM, I, OT, S> for ExportStdXObserver
/// where
/// S: State
/// S: State,
/// OT: MatchNameRef
/// {
/// fn is_interesting<EM, OT>(
/// fn is_interesting(
/// &mut self,
/// _state: &mut S,
/// _manager: &mut EM,
/// _input: &<S>::Input,
/// _input: &I,
/// observers: &OT,
/// _exit_kind: &ExitKind,
/// ) -> Result<bool, Error>
/// where
/// EM: EventFirer<State = S>,
/// OT: ObserversTuple<S::Input, S>,
/// {
/// unsafe {
/// STDOUT = observers.get(&self.stdout_observer).unwrap().stdout.clone();

View File

@ -447,8 +447,8 @@ where
OT: ObserversTuple<Self::Input, Self::State>,
PS: PushStage<CS, EM, OT, Z>,
Z: ExecutesInput<E, EM>
+ ExecutionProcessor
+ EvaluatorObservers<OT>
+ ExecutionProcessor<EM, OT>
+ EvaluatorObservers<EM, OT>
+ HasScheduler<Scheduler = CS>,
{
fn perform(

View File

@ -40,7 +40,7 @@ where
EM: EventFirer<State = Z::State> + EventRestarter + HasEventManagerId,
OT: ObserversTuple<Z::Input, Z::State>,
Z::State: HasRand + HasCorpus,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// The [`crate::state::State`]
pub state: Z::State,
@ -59,7 +59,7 @@ where
EM: EventFirer<State = Z::State> + EventRestarter + HasEventManagerId,
OT: ObserversTuple<Z::Input, Z::State>,
Z::State: HasRand + HasCorpus,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// Create a new `PushStageSharedState` that can be used by all [`PushStage`]s
#[must_use]
@ -82,7 +82,7 @@ where
EM: EventFirer<State = Z::State> + EventRestarter + HasEventManagerId,
OT: ObserversTuple<Z::Input, Z::State>,
Z::State: HasRand + HasCorpus,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// If this stage has already been initalized.
/// This gets reset to `false` after one iteration of the stage is done.
@ -110,7 +110,7 @@ where
EM: EventFirer<State = Z::State> + EventRestarter + HasEventManagerId,
OT: ObserversTuple<Z::Input, Z::State>,
Z::State: HasRand + HasCorpus,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// Create a new [`PushStageHelper`]
#[must_use]
@ -177,7 +177,7 @@ where
Z::State: HasRand + HasExecutions + HasMetadata + HasCorpus + HasLastReportTime,
EM: EventFirer<State = Z::State> + EventRestarter + HasEventManagerId + ProgressReporter,
OT: ObserversTuple<Z::Input, Z::State>,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// Gets the [`PushStageHelper`]
fn push_stage_helper(&self) -> &PushStageHelper<CS, EM, OT, Z>;

View File

@ -48,7 +48,7 @@ where
M: Mutator<Z::Input, Z::State>,
OT: ObserversTuple<Z::Input, Z::State> + Serialize,
Z::State: HasRand + HasCorpus + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
current_corpus_id: Option<CorpusId>,
testcases_to_do: usize,
@ -66,7 +66,7 @@ where
M: Mutator<Z::Input, Z::State>,
OT: ObserversTuple<Z::Input, Z::State> + Serialize,
Z::State: HasCorpus + HasRand + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// Gets the number of iterations as a random number
#[allow(clippy::unused_self, clippy::unnecessary_wraps)] // TODO: we should put this function into a trait later
@ -87,7 +87,7 @@ where
M: Mutator<Z::Input, Z::State>,
OT: ObserversTuple<Z::Input, Z::State> + Serialize,
Z::State: HasCorpus + HasRand + HasExecutions + HasLastReportTime + HasMetadata + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
<<Z as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Z::Input>, //delete me
{
#[inline]
@ -196,7 +196,7 @@ where
M: Mutator<Z::Input, Z::State>,
OT: ObserversTuple<Z::Input, Z::State> + Serialize,
Z::State: HasCorpus + HasRand + HasExecutions + HasMetadata + HasLastReportTime + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, 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>;
@ -213,7 +213,7 @@ where
M: Mutator<Z::Input, Z::State>,
OT: ObserversTuple<Z::Input, Z::State> + Serialize,
Z::State: HasCorpus + HasRand + Clone + Debug,
Z: ExecutionProcessor + EvaluatorObservers<OT> + HasScheduler<Scheduler = CS>,
Z: ExecutionProcessor<EM, OT> + EvaluatorObservers<EM, OT> + HasScheduler<Scheduler = CS>,
{
/// Creates a new default mutational stage
#[must_use]

View File

@ -253,7 +253,8 @@ where
SP: ShMemProvider,
E: HasObservers + Executor<EM, Z, State = S>,
for<'a> E::Observers: Deserialize<'a>,
Z: EvaluatorObservers<E::Observers, State = S> + ExecutionProcessor<State = S>,
Z: EvaluatorObservers<EM, E::Observers, State = S>
+ ExecutionProcessor<EM, E::Observers, State = S>,
IC: InputConverter<From = S::Input, To = DI>,
ICB: InputConverter<From = DI, To = S::Input>,
DI: Input,

View File

@ -8,7 +8,7 @@ use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData};
use ahash::RandomState;
use libafl_bolts::{
tuples::{Handle, Handled, MatchNameRef},
tuples::{Handle, Handled, MatchName, MatchNameRef},
HasLen, Named,
};
use serde::Serialize;
@ -19,7 +19,7 @@ use crate::{
corpus::{Corpus, HasCurrentCorpusId, Testcase},
events::EventFirer,
executors::{ExitKind, HasObservers},
feedbacks::{Feedback, FeedbackFactory, HasObserverHandle},
feedbacks::{Feedback, FeedbackFactory, HasObserverHandle, StateInitializer},
inputs::UsesInput,
mark_feature_time,
mutators::{MutationResult, Mutator},
@ -47,7 +47,7 @@ where
E: UsesState<State = Self::State> + HasObservers,
E::Observers: ObserversTuple<Self::Input, Self::State> + Serialize,
EM: UsesState<State = Self::State> + EventFirer,
F: Feedback<Self::State>,
F: Feedback<EM, Self::Input, E::Observers, Self::State>,
Self::State: HasMaxSize + HasCorpus + HasSolutions + HasExecutions + HasCurrentTestcase,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + Hash + HasLen,
IP: Clone + MutatedTransformPost<Self::State>,
@ -56,7 +56,8 @@ where
+ HasScheduler
+ HasFeedback
+ ExecutesInput<E, EM>
+ ExecutionProcessor,
+ ExecutionProcessor<EM, E::Observers>,
Z::Feedback: Feedback<EM, Self::Input, E::Observers, Self::State>,
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>,
{
@ -239,16 +240,17 @@ where
impl<E, EM, F, FF, IP, M, Z> Stage<E, EM, Z> for StdTMinMutationalStage<E, EM, F, FF, IP, M, Z>
where
Z: HasScheduler + ExecutionProcessor + ExecutesInput<E, EM> + HasFeedback,
Z: HasScheduler + ExecutionProcessor<EM, E::Observers> + ExecutesInput<E, EM> + HasFeedback,
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
E: HasObservers + UsesState<State = Z::State>,
E::Observers: ObserversTuple<Self::Input, Self::State> + Serialize,
EM: EventFirer<State = Self::State>,
FF: FeedbackFactory<F, E::Observers>,
F: Feedback<Self::State>,
F: Feedback<EM, Self::Input, E::Observers, Self::State>,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
Z::State:
HasMetadata + HasExecutions + HasSolutions + HasCorpus + HasMaxSize + HasNamedMetadata,
Z::Feedback: Feedback<EM, Self::Input, E::Observers, Self::State>,
M: Mutator<Self::Input, Self::State>,
IP: MutatedTransformPost<Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
@ -302,13 +304,13 @@ pub static TMIN_STAGE_NAME: &str = "tmin";
impl<E, EM, F, FF, IP, M, Z> TMinMutationalStage<E, EM, F, IP, M, Z>
for StdTMinMutationalStage<E, EM, F, FF, IP, M, Z>
where
Z: HasScheduler + ExecutionProcessor + ExecutesInput<E, EM> + HasFeedback,
Z: HasScheduler + ExecutionProcessor<EM, E::Observers> + ExecutesInput<E, EM> + HasFeedback,
Z::Scheduler: RemovableScheduler<Self::Input, Self::State>,
E: HasObservers + UsesState<State = Z::State>,
E::Observers: ObserversTuple<Self::Input, Self::State> + Serialize,
EM: EventFirer<State = Self::State>,
FF: FeedbackFactory<F, E::Observers>,
F: Feedback<Self::State>,
F: Feedback<EM, Self::Input, E::Observers, Self::State>,
Self::Input: MutatedTransform<Self::Input, Self::State, Post = IP> + Clone + HasLen + Hash,
Z::State: HasMetadata
+ HasExecutions
@ -317,6 +319,7 @@ where
+ HasMaxSize
+ HasNamedMetadata
+ HasCurrentTestcase,
Z::Feedback: Feedback<EM, Self::Input, E::Observers, Self::State>,
M: Mutator<Self::Input, Self::State>,
IP: MutatedTransformPost<Self::State> + Clone,
<<Self as UsesState>::State as HasCorpus>::Corpus: Corpus<Input = Self::Input>, // delete me
@ -391,24 +394,23 @@ impl<C, M, S> HasObserverHandle for MapEqualityFeedback<C, M, S> {
}
}
impl<C, M, S> Feedback<S> for MapEqualityFeedback<C, M, S>
impl<C, M, S> StateInitializer<S> for MapEqualityFeedback<C, M, S> {}
impl<C, EM, I, M, OT, S> Feedback<EM, I, OT, S> for MapEqualityFeedback<C, M, S>
where
M: MapObserver,
C: AsRef<M>,
S: State,
OT: MatchName,
{
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
let obs = observers
.get(self.observer_handle())
.expect("Should have been provided valid observer name.");

View File

@ -33,7 +33,7 @@ use crate::monitors::ScalabilityMonitor;
use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase},
events::{Event, EventFirer, LogSeverity},
feedbacks::Feedback,
feedbacks::StateInitializer,
fuzzer::{Evaluator, ExecuteInputResult},
generators::Generator,
inputs::{Input, NopInput, UsesInput},
@ -1161,8 +1161,8 @@ where
objective: &mut O,
) -> Result<Self, Error>
where
F: Feedback<Self>,
O: Feedback<Self>,
F: StateInitializer<Self>,
O: StateInitializer<Self>,
C: Serialize + DeserializeOwned,
SC: Serialize + DeserializeOwned,
{

View File

@ -14,11 +14,10 @@ use frida_gum::interceptor::Interceptor;
use frida_gum::ModuleDetails;
use libafl::{
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
feedbacks::Feedback,
feedbacks::{Feedback, StateInitializer},
inputs::HasTargetBytes,
observers::{Observer, ObserversTuple},
observers::Observer,
state::State,
Error, HasMetadata,
};
@ -647,24 +646,23 @@ pub struct AsanErrorsFeedback<S> {
phantom: PhantomData<S>,
}
impl<S> Feedback<S> for AsanErrorsFeedback<S>
impl<S> StateInitializer<S> for AsanErrorsFeedback<S> {}
impl<EM, OT, S> Feedback<EM, S::Input, OT, S> for AsanErrorsFeedback<S>
where
S: State + Debug,
S::Input: HasTargetBytes,
OT: MatchNameRef,
{
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
let observer = observers
.get(&self.observer_handle)
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
@ -677,16 +675,13 @@ where
}
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
{
) -> Result<(), Error> {
if let Some(errors) = &self.errors {
testcase.add_metadata(errors.clone());
}

View File

@ -5,15 +5,13 @@ use std::borrow::Cow;
use libafl::{
alloc,
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, MinMapFeedback},
feedbacks::{Feedback, MinMapFeedback, StateInitializer},
inputs::{BytesInput, Input},
observers::ObserversTuple,
state::State,
Error, HasMetadata,
};
use libafl_bolts::{impl_serdeany, Named};
use libafl_bolts::{impl_serdeany, tuples::MatchNameRef, Named};
use libafl_targets::OomFeedback;
use serde::{Deserialize, Serialize};
@ -43,22 +41,20 @@ impl Named for LibfuzzerKeepFeedback {
}
}
impl<S> Feedback<S> for LibfuzzerKeepFeedback
impl<S> StateInitializer<S> for LibfuzzerKeepFeedback {}
impl<EM, OT, S> Feedback<EM, S::Input, OT, S> for LibfuzzerKeepFeedback
where
S: State,
{
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
Ok(*self.keep.borrow())
}
@ -119,22 +115,21 @@ impl LibfuzzerCrashCauseFeedback {
}
}
impl<S> Feedback<S> for LibfuzzerCrashCauseFeedback
impl<S> StateInitializer<S> for LibfuzzerCrashCauseFeedback {}
impl<EM, OT, S> Feedback<EM, BytesInput, OT, S> for LibfuzzerCrashCauseFeedback
where
S: State<Input = BytesInput>,
OT: MatchNameRef,
{
fn is_interesting<EM, OT>(
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &BytesInput,
_observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<State = S>,
OT: ObserversTuple<S::Input, S>,
{
) -> Result<bool, Error> {
self.exit_kind = *exit_kind;
Ok(false)
}
@ -143,16 +138,13 @@ where
Ok(false)
}
fn append_metadata<EM, OT>(
fn append_metadata(
&mut self,
_state: &mut S,
_manager: &mut EM,
_observers: &OT,
testcase: &mut Testcase<S::Input>,
) -> Result<(), Error>
where
OT: ObserversTuple<S::Input, S>,
{
testcase: &mut Testcase<BytesInput>,
) -> Result<(), Error> {
match self.exit_kind {
ExitKind::Crash | ExitKind::Oom if OomFeedback::oomed() => {
self.set_filename("oom", testcase);
@ -183,4 +175,4 @@ where
}
}
pub type ShrinkMapFeedback<C, O, T> = MinMapFeedback<C, MappedEdgeMapObserver<O, T>, usize>;
pub type ShrinkMapFeedback<C, O, T> = MinMapFeedback<C, MappedEdgeMapObserver<O, T>>;

View File

@ -89,7 +89,7 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, OF, Z>(
E: HasObservers + HasInProcessHooks<E::State> + Executor<EM, Z>,
E::Observers: ObserversTuple<E::Input, E::State>,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, 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
@ -139,9 +139,11 @@ where
where
ED: EmulatorDriver<CM, ET, S, SM>,
EM: EventFirer<State = S> + EventRestarter<State = S>,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
S: Unpin + State + HasExecutions + HasCorpus + HasSolutions,
Z: HasObjective<Objective = OF, State = S> + HasScheduler<State = S> + ExecutionProcessor,
Z: HasObjective<Objective = OF, State = S>
+ HasScheduler<State = S>
+ ExecutionProcessor<EM, OT>,
S::Solutions: Corpus<Input = S::Input>, //delete me
<S::Corpus as Corpus>::Input: Clone, //delete me
{
@ -328,6 +330,7 @@ where
S: State + HasSolutions,
SP: ShMemProvider,
Z: HasObjective<State = S>,
Z::Objective: Feedback<EM, S::Input, OT, S>,
{
pub fn new(
emulator: Emulator<CM, ED, ET, S, SM>,
@ -383,7 +386,7 @@ where
OT: ObserversTuple<S::Input, S> + Debug,
ET: EmulatorModuleTuple<S>,
SP: ShMemProvider,
OF: Feedback<S>,
OF: Feedback<EM, S::Input, OT, S>,
Z: HasObjective<Objective = OF, State = S>,
{
fn run_target(

View File

@ -2,7 +2,12 @@ use alloc::borrow::Cow;
use core::{ffi::c_void, fmt::Debug};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use libafl::{executors::ExitKind, feedbacks::Feedback, observers::Observer, state::State, Error};
use libafl::{
executors::ExitKind,
feedbacks::{Feedback, StateInitializer},
observers::Observer,
Error,
};
use libafl_bolts::Named;
use libc::SIGABRT;
use serde::{Deserialize, Serialize};
@ -138,15 +143,14 @@ impl Named for OomFeedback {
}
}
impl<S> Feedback<S> for OomFeedback
where
S: State,
{
fn is_interesting<EM, OT>(
impl<S> StateInitializer<S> for OomFeedback {}
impl<EM, I, OT, S> Feedback<EM, I, OT, S> for OomFeedback {
fn is_interesting(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &S::Input,
_input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error> {

View File

@ -34,7 +34,7 @@ pub unsafe fn setup_asan_callback<E, EM, OF, Z>(_executor: &E, _event_mgr: &EM,
where
E: Executor<EM, Z> + HasObservers,
EM: EventFirer<State = E::State> + EventRestarter<State = E::State>,
OF: Feedback<E::State>,
OF: Feedback<EM, E::Input, E::Observers, E::State>,
E::State: HasSolutions + HasCorpus + HasExecutions,
E::Observers: ObserversTuple<<E::State as UsesInput>::Input, E::State>,
Z: HasObjective<Objective = OF, State = E::State>,