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:
parent
a212d66afe
commit
cbce7ffdfd
@ -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,
|
||||
|
@ -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(())
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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>,
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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>>,
|
||||
{
|
||||
}
|
||||
|
@ -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>,
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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())
|
||||
|
@ -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>,
|
||||
|
@ -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};
|
||||
|
@ -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();
|
||||
|
@ -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(
|
||||
|
@ -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>;
|
||||
|
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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.");
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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>>;
|
||||
|
@ -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(
|
||||
|
@ -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> {
|
||||
|
@ -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>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user