Match by Ref fix (#2105)
* match by ref fix * impl Named for Reference * rename * magic indexing * whoops * docs, clippy * some additional CI complaints * other libafl_qemu fixes * missed an alloc feature * a smattering of fixes * use from not direct construction * tinyinst fix * horrible double-mutability things * fixup nyx * from not new * forkserver_simple fixes * dogfood: forkserver * mmmm yummy dogfood * round one CI fixes * clippy appeasement * deref generic impl to simplify usage * adaptive serialization (ouch) * remaining clippy items * I am tired * new not with * fixup: aflpp tracing was not actually constructable * fix tmin * reduce complexity of map feedback now that we do not need to constrain * frida fixes * fix concolic * type_ref => reference
This commit is contained in:
parent
084b9b5878
commit
28c43b332f
@ -36,7 +36,7 @@ pub fn main() -> Result<(), Error> {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) };
|
let observer = unsafe { StdMapObserver::from_mut_ptr("signals", SIGNALS_PTR, SIGNALS.len()) };
|
||||||
|
|
||||||
let factory = MapEqualityFactory::with_observer(&observer);
|
let factory = MapEqualityFactory::new(&observer);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
let mut feedback = MaxMapFeedback::new(&observer);
|
let mut feedback = MaxMapFeedback::new(&observer);
|
||||||
|
@ -116,7 +116,7 @@ pub fn main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -167,7 +167,7 @@ pub fn main() {
|
|||||||
// Create the executor for the forkserver
|
// Create the executor for the forkserver
|
||||||
let args = opt.arguments;
|
let args = opt.arguments;
|
||||||
|
|
||||||
let observer_ref = edges_observer.type_ref();
|
let observer_ref = edges_observer.reference();
|
||||||
|
|
||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
let mut executor = ForkserverExecutor::builder()
|
let mut executor = ForkserverExecutor::builder()
|
||||||
@ -183,10 +183,7 @@ pub fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if let Some(dynamic_map_size) = executor.coverage_map_size() {
|
if let Some(dynamic_map_size) = executor.coverage_map_size() {
|
||||||
executor
|
executor.observers_mut()[&observer_ref]
|
||||||
.observers_mut()
|
|
||||||
.match_by_ref_mut(observer_ref)
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.truncate(dynamic_map_size);
|
.truncate(dynamic_map_size);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ use libafl::{
|
|||||||
inputs::BytesInput,
|
inputs::BytesInput,
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
|
mutators::{scheduled::havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
|
||||||
observers::{CanTrack, ExplicitTracking, HitcountsMapObserver, StdMapObserver, TimeObserver},
|
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
|
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
|
||||||
stages::mutational::StdMutationalStage,
|
stages::mutational::StdMutationalStage,
|
||||||
state::{HasCorpus, StdState},
|
state::{HasCorpus, StdState},
|
||||||
@ -22,7 +22,7 @@ use libafl_bolts::{
|
|||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||||
tuples::{tuple_list, MatchName, Merge},
|
tuples::{tuple_list, Merge, Referenceable},
|
||||||
AsSliceMut, Truncate,
|
AsSliceMut, Truncate,
|
||||||
};
|
};
|
||||||
use nix::sys::signal::Signal;
|
use nix::sys::signal::Signal;
|
||||||
@ -114,7 +114,7 @@ pub fn main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -163,6 +163,8 @@ pub fn main() {
|
|||||||
// Create the executor for the forkserver
|
// Create the executor for the forkserver
|
||||||
let args = opt.arguments;
|
let args = opt.arguments;
|
||||||
|
|
||||||
|
let observer_ref = edges_observer.reference();
|
||||||
|
|
||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
let mut executor = ForkserverExecutor::builder()
|
let mut executor = ForkserverExecutor::builder()
|
||||||
.program(opt.executable)
|
.program(opt.executable)
|
||||||
@ -177,10 +179,7 @@ pub fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if let Some(dynamic_map_size) = executor.coverage_map_size() {
|
if let Some(dynamic_map_size) = executor.coverage_map_size() {
|
||||||
executor
|
executor.observers_mut()[&observer_ref]
|
||||||
.observers_mut()
|
|
||||||
.match_name_mut::<ExplicitTracking<HitcountsMapObserver<StdMapObserver<'_, u8, false>>, true, false>>("shared_mem")
|
|
||||||
.unwrap()
|
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.truncate(dynamic_map_size);
|
.truncate(dynamic_map_size);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ use libafl_bolts::{
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libafl_frida::asan::{
|
use libafl_frida::asan::{
|
||||||
asan_rt::AsanRuntime,
|
asan_rt::AsanRuntime,
|
||||||
errors::{AsanErrorsFeedback, AsanErrorsObserver, ASAN_ERRORS},
|
errors::{AsanErrorsFeedback, AsanErrorsObserver},
|
||||||
};
|
};
|
||||||
use libafl_frida::{
|
use libafl_frida::{
|
||||||
cmplog_rt::CmpLogRuntime,
|
cmplog_rt::CmpLogRuntime,
|
||||||
@ -123,6 +123,8 @@ unsafe fn fuzz(
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -130,7 +132,7 @@ unsafe fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
@ -139,7 +141,10 @@ unsafe fn fuzz(
|
|||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
// true enables the AsanErrorFeedback
|
// true enables the AsanErrorFeedback
|
||||||
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(true),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -185,9 +190,7 @@ unsafe fn fuzz(
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
@ -240,6 +243,8 @@ unsafe fn fuzz(
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -247,14 +252,17 @@ unsafe fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -300,11 +308,9 @@ unsafe fn fuzz(
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
@ -370,6 +376,8 @@ unsafe fn fuzz(
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -377,14 +385,17 @@ unsafe fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -430,11 +441,9 @@ unsafe fn fuzz(
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
|
@ -99,7 +99,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
let coverage = CoverageRuntime::new();
|
let coverage = CoverageRuntime::new();
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let asan = AsanRuntime::new(&options);
|
let asan = AsanRuntime::new(options);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut frida_helper =
|
let mut frida_helper =
|
||||||
@ -119,13 +119,16 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
@ -134,7 +137,10 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
// true enables the AsanErrorFeedback
|
// true enables the AsanErrorFeedback
|
||||||
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(true),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -179,9 +185,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
@ -234,6 +238,8 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -241,14 +247,17 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -294,9 +303,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer,);
|
||||||
|
|
||||||
@ -366,20 +373,26 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -425,11 +438,9 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
|
@ -35,7 +35,7 @@ use libafl_bolts::{
|
|||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libafl_frida::asan::{
|
use libafl_frida::asan::{
|
||||||
asan_rt::AsanRuntime,
|
asan_rt::AsanRuntime,
|
||||||
errors::{AsanErrorsFeedback, AsanErrorsObserver, ASAN_ERRORS},
|
errors::{AsanErrorsFeedback, AsanErrorsObserver},
|
||||||
};
|
};
|
||||||
use libafl_frida::{
|
use libafl_frida::{
|
||||||
cmplog_rt::CmpLogRuntime,
|
cmplog_rt::CmpLogRuntime,
|
||||||
@ -113,6 +113,8 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -120,7 +122,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
@ -129,7 +131,10 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
// true enables the AsanErrorFeedback
|
// true enables the AsanErrorFeedback
|
||||||
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(true),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -175,9 +180,7 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
@ -231,6 +234,8 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -238,14 +243,17 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -291,11 +299,9 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer, unsafe {
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
});
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
@ -361,6 +367,8 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
#[cfg(unix)]
|
||||||
|
let asan_observer = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
@ -368,14 +376,17 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(false),
|
||||||
|
AsanErrorsFeedback::new(&asan_observer)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||||
@ -421,13 +432,9 @@ unsafe fn fuzz(options: &FuzzerOptions) -> Result<(), Error> {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let observers = tuple_list!(
|
let observers = tuple_list!(edges_observer, time_observer, asan_observer);
|
||||||
edges_observer,
|
|
||||||
time_observer,
|
|
||||||
AsanErrorsObserver::from_static_asan_errors()
|
|
||||||
);
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let observers = tuple_list!(edges_observer, time_observer,);
|
let observers = tuple_list!(edges_observer, time_observer);
|
||||||
|
|
||||||
// Create the executor for an in-process function with just one observer for edge coverage
|
// Create the executor for an in-process function with just one observer for edge coverage
|
||||||
let mut executor = FridaInProcessExecutor::new(
|
let mut executor = FridaInProcessExecutor::new(
|
||||||
|
@ -260,7 +260,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -270,7 +270,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -258,7 +258,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -267,7 +267,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -37,7 +37,7 @@ use libafl_bolts::{
|
|||||||
ownedref::OwnedRefMut,
|
ownedref::OwnedRefMut,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge, Referenceable},
|
||||||
AsSliceMut,
|
AsSliceMut,
|
||||||
};
|
};
|
||||||
use libafl_targets::{
|
use libafl_targets::{
|
||||||
@ -268,7 +268,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -355,6 +355,7 @@ fn fuzz(
|
|||||||
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
|
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
|
||||||
|
|
||||||
let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true);
|
let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true);
|
||||||
|
let cmplog_ref = cmplog_observer.reference();
|
||||||
|
|
||||||
let cmplog_executor = ForkserverExecutor::builder()
|
let cmplog_executor = ForkserverExecutor::builder()
|
||||||
.program(exec)
|
.program(exec)
|
||||||
@ -367,7 +368,7 @@ fn fuzz(
|
|||||||
.build(tuple_list!(cmplog_observer))
|
.build(tuple_list!(cmplog_observer))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let tracing = AFLppCmplogTracingStage::with_cmplog_observer_name(cmplog_executor, "cmplog");
|
let tracing = AFLppCmplogTracingStage::with_cmplog_observer(cmplog_executor, cmplog_ref);
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let rq = MultiMutationalStage::new(AFLppRedQueen::with_cmplog_options(true, true));
|
let rq = MultiMutationalStage::new(AFLppRedQueen::with_cmplog_options(true, true));
|
||||||
|
@ -279,7 +279,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -328,7 +328,7 @@ fn fuzz_binary(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
let mut objective = CrashFeedback::new();
|
let mut objective = CrashFeedback::new();
|
||||||
@ -539,7 +539,7 @@ fn fuzz_text(
|
|||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -151,7 +151,7 @@ pub extern "C" fn LLVMFuzzerRunDriver(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -101,7 +101,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -152,7 +152,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -115,7 +115,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -150,7 +150,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -100,7 +100,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -151,7 +151,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -176,7 +176,7 @@ pub extern "C" fn libafl_main() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -99,7 +99,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -81,7 +81,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -42,8 +42,8 @@ use libafl_bolts::{
|
|||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
||||||
tuples::tuple_list,
|
tuples::{tuple_list, Referenceable},
|
||||||
AsSliceMut, AsSlice, Named,
|
AsSliceMut, AsSlice
|
||||||
};
|
};
|
||||||
use libafl_targets::{
|
use libafl_targets::{
|
||||||
libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver,
|
libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver,
|
||||||
@ -119,7 +119,7 @@ fn fuzz(
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -207,8 +207,7 @@ fn fuzz(
|
|||||||
|
|
||||||
// The concolic observer observers the concolic shared memory map.
|
// The concolic observer observers the concolic shared memory map.
|
||||||
let concolic_observer = ConcolicObserver::new("concolic", concolic_shmem.as_slice_mut());
|
let concolic_observer = ConcolicObserver::new("concolic", concolic_shmem.as_slice_mut());
|
||||||
|
let concolic_ref = concolic_observer.reference();
|
||||||
let concolic_observer_name = concolic_observer.name().to_string();
|
|
||||||
|
|
||||||
// The order of the stages matter!
|
// The order of the stages matter!
|
||||||
let mut stages = tuple_list!(
|
let mut stages = tuple_list!(
|
||||||
@ -217,7 +216,7 @@ fn fuzz(
|
|||||||
TracingStage::new(
|
TracingStage::new(
|
||||||
MyCommandConfigurator.into_executor(tuple_list!(concolic_observer))
|
MyCommandConfigurator.into_executor(tuple_list!(concolic_observer))
|
||||||
),
|
),
|
||||||
concolic_observer_name,
|
concolic_ref,
|
||||||
),
|
),
|
||||||
// Use the concolic trace for z3-based solving
|
// Use the concolic trace for z3-based solving
|
||||||
SimpleConcolicMutationalStage::default(),
|
SimpleConcolicMutationalStage::default(),
|
||||||
|
@ -77,7 +77,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -97,7 +97,7 @@ impl<'a, M: Monitor> Instance<'a, M> {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -169,7 +169,7 @@ pub fn fuzz() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -176,7 +176,7 @@ pub fn fuzz() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -110,7 +110,7 @@ pub fn fuzz() {
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
|
@ -97,7 +97,7 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
map_feedback,
|
map_feedback,
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer),
|
TimeFeedback::new(&time_observer),
|
||||||
PacketLenFeedback::new()
|
PacketLenFeedback::new()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
//! Whole corpus minimizers, for reducing the number of samples/the total size/the average runtime
|
//! Whole corpus minimizers, for reducing the number of samples/the total size/the average runtime
|
||||||
//! of your corpus.
|
//! of your corpus.
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{borrow::Cow, string::ToString, vec::Vec};
|
||||||
borrow::Cow,
|
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::{hash::Hash, marker::PhantomData};
|
use core::{hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use libafl_bolts::{current_time, tuples::MatchName, AsIter, Named};
|
use libafl_bolts::{
|
||||||
|
current_time,
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
AsIter, Named,
|
||||||
|
};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use z3::{ast::Bool, Config, Context, Optimize};
|
use z3::{ast::Bool, Config, Context, Optimize};
|
||||||
|
|
||||||
@ -51,8 +51,8 @@ where
|
|||||||
/// Algorithm based on WMOPT: <https://hexhive.epfl.ch/publications/files/21ISSTA2.pdf>
|
/// Algorithm based on WMOPT: <https://hexhive.epfl.ch/publications/files/21ISSTA2.pdf>
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MapCorpusMinimizer<C, E, O, T, TS> {
|
pub struct MapCorpusMinimizer<C, E, O, T, TS> {
|
||||||
obs_name: String,
|
obs_ref: Reference<C>,
|
||||||
phantom: PhantomData<(C, E, O, T, TS)>,
|
phantom: PhantomData<(E, O, T, TS)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Standard corpus minimizer, which weights inputs by length and time.
|
/// Standard corpus minimizer, which weights inputs by length and time.
|
||||||
@ -70,7 +70,7 @@ where
|
|||||||
/// in the future to get observed maps from an executed input.
|
/// in the future to get observed maps from an executed input.
|
||||||
pub fn new(obs: &C) -> Self {
|
pub fn new(obs: &C) -> Self {
|
||||||
Self {
|
Self {
|
||||||
obs_name: obs.name().to_string(),
|
obs_ref: obs.reference(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,11 +160,8 @@ where
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
let seed_expr = Bool::fresh_const(&ctx, "seed");
|
let seed_expr = Bool::fresh_const(&ctx, "seed");
|
||||||
let obs = executor
|
let observers = executor.observers();
|
||||||
.observers()
|
let obs = observers[&self.obs_ref].as_ref();
|
||||||
.match_name::<C>(&self.obs_name)
|
|
||||||
.expect("Observer must be present.")
|
|
||||||
.as_ref();
|
|
||||||
|
|
||||||
// Store coverage, mapping coverage map indices to hit counts (if present) and the
|
// Store coverage, mapping coverage map indices to hit counts (if present) and the
|
||||||
// associated seeds for the map indices with those hit counts.
|
// associated seeds for the map indices with those hit counts.
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
use core::{marker::PhantomData, num::NonZeroUsize, time::Duration};
|
use core::{marker::PhantomData, num::NonZeroUsize, time::Duration};
|
||||||
|
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use libafl_bolts::tuples::{Reference, Referenceable};
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
compress::GzipCompressor,
|
compress::GzipCompressor,
|
||||||
@ -24,6 +26,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
use crate::events::llmp::COMPRESS_THRESHOLD;
|
use crate::events::llmp::COMPRESS_THRESHOLD;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use crate::observers::TimeObserver;
|
||||||
#[cfg(feature = "scalability_introspection")]
|
#[cfg(feature = "scalability_introspection")]
|
||||||
use crate::state::HasScalabilityMonitor;
|
use crate::state::HasScalabilityMonitor;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -221,6 +225,8 @@ where
|
|||||||
client: LlmpClient<SP>,
|
client: LlmpClient<SP>,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
is_main: bool,
|
is_main: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,6 +269,10 @@ where
|
|||||||
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
||||||
self.inner.should_serialize_cnt_mut()
|
self.inner.should_serialize_cnt_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn time_ref(&self) -> &Reference<TimeObserver> {
|
||||||
|
&self.time_ref
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "adaptive_serialization"))]
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
@ -275,7 +285,7 @@ where
|
|||||||
|
|
||||||
impl<EM, SP> EventFirer for CentralizedEventManager<EM, SP>
|
impl<EM, SP> EventFirer for CentralizedEventManager<EM, SP>
|
||||||
where
|
where
|
||||||
EM: AdaptiveSerializer + EventFirer + HasEventManagerId + AdaptiveSerializer,
|
EM: AdaptiveSerializer + EventFirer + HasEventManagerId,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
fn fire(
|
fn fire(
|
||||||
@ -459,6 +469,7 @@ where
|
|||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Creates a new [`CentralizedEventManager`].
|
/// Creates a new [`CentralizedEventManager`].
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
pub fn new(inner: EM, client: LlmpClient<SP>, is_main: bool) -> Result<Self, Error> {
|
pub fn new(inner: EM, client: LlmpClient<SP>, is_main: bool) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
@ -469,25 +480,66 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new [`CentralizedEventManager`].
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn new(
|
||||||
|
inner: EM,
|
||||||
|
client: LlmpClient<SP>,
|
||||||
|
is_main: bool,
|
||||||
|
time_obs: &TimeObserver,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
inner,
|
||||||
|
client,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
time_ref: time_obs.reference(),
|
||||||
|
is_main,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a centralized event manager on a port
|
||||||
|
///
|
||||||
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
|
/// will act as a client.
|
||||||
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
|
pub fn on_port(inner: EM, shmem_provider: SP, port: u16, is_main: bool) -> Result<Self, Error> {
|
||||||
|
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
|
Ok(Self {
|
||||||
|
inner,
|
||||||
|
client,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
is_main,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a centralized event manager on a port
|
/// Create a centralized event manager on a port
|
||||||
///
|
///
|
||||||
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
/// will act as a client.
|
/// will act as a client.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
pub fn on_port(inner: EM, shmem_provider: SP, port: u16, is_main: bool) -> Result<Self, Error> {
|
pub fn on_port(
|
||||||
|
inner: EM,
|
||||||
|
shmem_provider: SP,
|
||||||
|
port: u16,
|
||||||
|
is_main: bool,
|
||||||
|
time_obs: &TimeObserver,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
let client = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner,
|
inner,
|
||||||
client,
|
client,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
time_ref: time_obs.reference(),
|
||||||
is_main,
|
is_main,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
/// stored by [`LlmpClient::to_env()`].
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
pub fn existing_client_from_env(
|
pub fn existing_client_from_env(
|
||||||
inner: EM,
|
inner: EM,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
@ -503,12 +555,28 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describe the client event manager's LLMP parts in a restorable fashion
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
self.client.describe()
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
pub fn existing_client_from_env(
|
||||||
|
inner: EM,
|
||||||
|
shmem_provider: SP,
|
||||||
|
env_name: &str,
|
||||||
|
is_main: bool,
|
||||||
|
time_obs: &TimeObserver,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
inner,
|
||||||
|
client: LlmpClient::on_existing_from_env(shmem_provider, env_name)?,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
time_ref: time_obs.reference(),
|
||||||
|
is_main,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an existing client from description
|
/// Create an existing client from description
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
pub fn existing_client_from_description(
|
pub fn existing_client_from_description(
|
||||||
inner: EM,
|
inner: EM,
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
@ -524,6 +592,30 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create an existing client from description
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn existing_client_from_description(
|
||||||
|
inner: EM,
|
||||||
|
shmem_provider: SP,
|
||||||
|
description: &LlmpClientDescription,
|
||||||
|
is_main: bool,
|
||||||
|
time_obs: &TimeObserver,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
inner,
|
||||||
|
client: LlmpClient::existing_client_from_description(shmem_provider, description)?,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
time_ref: time_obs.reference(),
|
||||||
|
is_main,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Describe the client event manager's LLMP parts in a restorable fashion
|
||||||
|
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
||||||
|
self.client.describe()
|
||||||
|
}
|
||||||
|
|
||||||
/// Write the config for a client [`EventManager`] to env vars, a new
|
/// Write the config for a client [`EventManager`] to env vars, a new
|
||||||
/// client can reattach using [`CentralizedEventManager::existing_client_from_env()`].
|
/// client can reattach using [`CentralizedEventManager::existing_client_from_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -30,6 +30,8 @@ use std::{fs::File, os::unix::io::AsRawFd};
|
|||||||
|
|
||||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||||
use libafl_bolts::os::startable_self;
|
use libafl_bolts::os::startable_self;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use libafl_bolts::tuples::{Reference, Referenceable};
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
core_affinity::get_core_ids,
|
core_affinity::get_core_ids,
|
||||||
@ -46,6 +48,8 @@ use typed_builder::TypedBuilder;
|
|||||||
use super::hooks::EventManagerHooksTuple;
|
use super::hooks::EventManagerHooksTuple;
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
use crate::events::{CentralizedEventManager, CentralizedLlmpEventBroker};
|
use crate::events::{CentralizedEventManager, CentralizedLlmpEventBroker};
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use crate::observers::TimeObserver;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{
|
events::{
|
||||||
@ -116,6 +120,8 @@ where
|
|||||||
/// clusters.
|
/// clusters.
|
||||||
#[builder(default = None)]
|
#[builder(default = None)]
|
||||||
remote_broker_addr: Option<SocketAddr>,
|
remote_broker_addr: Option<SocketAddr>,
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
/// If this launcher should spawn a new `broker` on `[Self::broker_port]` (default).
|
/// If this launcher should spawn a new `broker` on `[Self::broker_port]` (default).
|
||||||
/// The reason you may not want this is, if you already have a [`Launcher`]
|
/// The reason you may not want this is, if you already have a [`Launcher`]
|
||||||
/// with a different configuration (for the same target) running on this machine.
|
/// with a different configuration (for the same target) running on this machine.
|
||||||
@ -250,7 +256,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fuzzer client. keeps retrying the connection to broker till the broker starts
|
// Fuzzer client. keeps retrying the connection to broker till the broker starts
|
||||||
let (state, mgr) = RestartingMgr::<EMH, MT, S, SP>::builder()
|
let builder = RestartingMgr::<EMH, MT, S, SP>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.kind(ManagerKind::Client {
|
.kind(ManagerKind::Client {
|
||||||
@ -258,9 +264,10 @@ where
|
|||||||
})
|
})
|
||||||
.configuration(self.configuration)
|
.configuration(self.configuration)
|
||||||
.serialize_state(self.serialize_state)
|
.serialize_state(self.serialize_state)
|
||||||
.hooks(hooks)
|
.hooks(hooks);
|
||||||
.build()
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
.launch()?;
|
let builder = builder.time_ref(self.time_ref.clone());
|
||||||
|
let (state, mgr) = builder.build().launch()?;
|
||||||
|
|
||||||
return (self.run_client.take().unwrap())(state, mgr, *bind_to);
|
return (self.run_client.take().unwrap())(state, mgr, *bind_to);
|
||||||
}
|
}
|
||||||
@ -273,7 +280,7 @@ where
|
|||||||
log::info!("I am broker!!.");
|
log::info!("I am broker!!.");
|
||||||
|
|
||||||
// TODO we don't want always a broker here, think about using different laucher process to spawn different configurations
|
// TODO we don't want always a broker here, think about using different laucher process to spawn different configurations
|
||||||
RestartingMgr::<EMH, MT, S, SP>::builder()
|
let builder = RestartingMgr::<EMH, MT, S, SP>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
.monitor(Some(self.monitor.clone()))
|
.monitor(Some(self.monitor.clone()))
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
@ -282,9 +289,12 @@ where
|
|||||||
.exit_cleanly_after(Some(NonZeroUsize::try_from(self.cores.ids.len()).unwrap()))
|
.exit_cleanly_after(Some(NonZeroUsize::try_from(self.cores.ids.len()).unwrap()))
|
||||||
.configuration(self.configuration)
|
.configuration(self.configuration)
|
||||||
.serialize_state(self.serialize_state)
|
.serialize_state(self.serialize_state)
|
||||||
.hooks(hooks)
|
.hooks(hooks);
|
||||||
.build()
|
|
||||||
.launch()?;
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let builder = builder.time_ref(self.time_ref.clone());
|
||||||
|
|
||||||
|
builder.build().launch()?;
|
||||||
|
|
||||||
// Broker exited. kill all clients.
|
// Broker exited. kill all clients.
|
||||||
for handle in &handles {
|
for handle in &handles {
|
||||||
@ -457,6 +467,9 @@ where
|
|||||||
/// The centralized broker port to use (or to attach to, in case [`Self::spawn_broker`] is `false`)
|
/// The centralized broker port to use (or to attach to, in case [`Self::spawn_broker`] is `false`)
|
||||||
#[builder(default = 1338_u16)]
|
#[builder(default = 1338_u16)]
|
||||||
centralized_broker_port: u16,
|
centralized_broker_port: u16,
|
||||||
|
/// The time observer by which to adaptively serialize
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
time_obs: &'a TimeObserver,
|
||||||
/// The list of cores to run on
|
/// The list of cores to run on
|
||||||
cores: &'a Cores,
|
cores: &'a Cores,
|
||||||
/// A file name to write all client output to
|
/// A file name to write all client output to
|
||||||
@ -617,7 +630,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fuzzer client. keeps retrying the connection to broker till the broker starts
|
// Fuzzer client. keeps retrying the connection to broker till the broker starts
|
||||||
let (state, mgr) = RestartingMgr::<(), MT, S, SP>::builder()
|
let builder = RestartingMgr::<(), MT, S, SP>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.kind(ManagerKind::Client {
|
.kind(ManagerKind::Client {
|
||||||
@ -625,16 +638,26 @@ where
|
|||||||
})
|
})
|
||||||
.configuration(self.configuration)
|
.configuration(self.configuration)
|
||||||
.serialize_state(self.serialize_state)
|
.serialize_state(self.serialize_state)
|
||||||
.hooks(tuple_list!())
|
.hooks(tuple_list!());
|
||||||
.build()
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
.launch()?;
|
let builder = builder.time_ref(self.time_obs.reference());
|
||||||
|
let (state, mgr) = builder.build().launch()?;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let c_mgr = CentralizedEventManager::on_port(
|
let c_mgr = CentralizedEventManager::on_port(
|
||||||
mgr,
|
mgr,
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
self.centralized_broker_port,
|
self.centralized_broker_port,
|
||||||
index == 1,
|
index == 1,
|
||||||
)?;
|
)?;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let c_mgr = CentralizedEventManager::on_port(
|
||||||
|
mgr,
|
||||||
|
self.shmem_provider.clone(),
|
||||||
|
self.centralized_broker_port,
|
||||||
|
index == 1,
|
||||||
|
self.time_obs,
|
||||||
|
)?;
|
||||||
|
|
||||||
return (self.run_client.take().unwrap())(state, c_mgr, *bind_to);
|
return (self.run_client.take().unwrap())(state, c_mgr, *bind_to);
|
||||||
}
|
}
|
||||||
@ -646,7 +669,7 @@ where
|
|||||||
log::info!("I am broker!!.");
|
log::info!("I am broker!!.");
|
||||||
|
|
||||||
// TODO we don't want always a broker here, think about using different laucher process to spawn different configurations
|
// TODO we don't want always a broker here, think about using different laucher process to spawn different configurations
|
||||||
RestartingMgr::<(), MT, S, SP>::builder()
|
let builder = RestartingMgr::<(), MT, S, SP>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
.monitor(Some(self.monitor.clone()))
|
.monitor(Some(self.monitor.clone()))
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
@ -655,9 +678,12 @@ where
|
|||||||
.exit_cleanly_after(Some(NonZeroUsize::try_from(self.cores.ids.len()).unwrap()))
|
.exit_cleanly_after(Some(NonZeroUsize::try_from(self.cores.ids.len()).unwrap()))
|
||||||
.configuration(self.configuration)
|
.configuration(self.configuration)
|
||||||
.serialize_state(self.serialize_state)
|
.serialize_state(self.serialize_state)
|
||||||
.hooks(tuple_list!())
|
.hooks(tuple_list!());
|
||||||
.build()
|
|
||||||
.launch()?;
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let builder = builder.time_ref(self.time_obs.reference());
|
||||||
|
|
||||||
|
builder.build().launch()?;
|
||||||
|
|
||||||
// Broker exited. kill all clients.
|
// Broker exited. kill all clients.
|
||||||
for handle in &handles {
|
for handle in &handles {
|
||||||
|
@ -13,8 +13,6 @@ use std::net::TcpStream;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
use libafl_bolts::current_time;
|
|
||||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||||
use libafl_bolts::os::startable_self;
|
use libafl_bolts::os::startable_self;
|
||||||
#[cfg(all(unix, feature = "std", not(miri)))]
|
#[cfg(all(unix, feature = "std", not(miri)))]
|
||||||
@ -32,6 +30,11 @@ use libafl_bolts::{
|
|||||||
llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse},
|
llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse},
|
||||||
IP_LOCALHOST,
|
IP_LOCALHOST,
|
||||||
};
|
};
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use libafl_bolts::{
|
||||||
|
current_time,
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use libafl_bolts::{llmp::LlmpConnection, shmem::StdShMemProvider, staterestore::StateRestorer};
|
use libafl_bolts::{llmp::LlmpConnection, shmem::StdShMemProvider, staterestore::StateRestorer};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
@ -49,6 +52,8 @@ use super::{hooks::EventManagerHooksTuple, CustomBufEventResult, CustomBufHandle
|
|||||||
use crate::events::AdaptiveSerializer;
|
use crate::events::AdaptiveSerializer;
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use crate::events::EVENTMGR_SIGHANDLER_STATE;
|
use crate::events::EVENTMGR_SIGHANDLER_STATE;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use crate::observers::TimeObserver;
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{
|
events::{
|
||||||
BrokerEventResult, Event, EventConfig, EventFirer, EventManager, EventManagerId,
|
BrokerEventResult, Event, EventConfig, EventFirer, EventManager, EventManagerId,
|
||||||
@ -336,7 +341,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// An [`EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp,
|
/// An [`EventManager`] that forwards all events to other attached fuzzers on shared maps or via tcp,
|
||||||
/// using low-level message passing, [`libafl_bolts::llmp`].
|
/// using low-level message passing, [`llmp`].
|
||||||
pub struct LlmpEventManager<EMH, S, SP>
|
pub struct LlmpEventManager<EMH, S, SP>
|
||||||
where
|
where
|
||||||
S: State,
|
S: State,
|
||||||
@ -361,6 +366,8 @@ where
|
|||||||
serializations_cnt: usize,
|
serializations_cnt: usize,
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
should_serialize_cnt: usize,
|
should_serialize_cnt: usize,
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
phantom: PhantomData<S>,
|
phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +402,10 @@ where
|
|||||||
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
||||||
&mut self.should_serialize_cnt
|
&mut self.should_serialize_cnt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn time_ref(&self) -> &Reference<TimeObserver> {
|
||||||
|
&self.time_ref
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, S, SP> core::fmt::Debug for LlmpEventManager<EMH, S, SP>
|
impl<EMH, S, SP> core::fmt::Debug for LlmpEventManager<EMH, S, SP>
|
||||||
@ -432,6 +443,7 @@ where
|
|||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Create a manager from a raw LLMP client
|
/// Create a manager from a raw LLMP client
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
pub fn new(llmp: LlmpClient<SP>, configuration: EventConfig) -> Result<Self, Error> {
|
pub fn new(llmp: LlmpClient<SP>, configuration: EventConfig) -> Result<Self, Error> {
|
||||||
Ok(LlmpEventManager {
|
Ok(LlmpEventManager {
|
||||||
hooks: tuple_list!(),
|
hooks: tuple_list!(),
|
||||||
@ -439,14 +451,6 @@ where
|
|||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
configuration,
|
configuration,
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
serialization_time: Duration::ZERO,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
deserialization_time: Duration::ZERO,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
serializations_cnt: 0,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
should_serialize_cnt: 0,
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
custom_buf_handlers: vec![],
|
custom_buf_handlers: vec![],
|
||||||
})
|
})
|
||||||
@ -456,7 +460,7 @@ where
|
|||||||
///
|
///
|
||||||
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
/// will act as a client.
|
/// will act as a client.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
pub fn on_port(
|
pub fn on_port(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
port: u16,
|
port: u16,
|
||||||
@ -468,7 +472,7 @@ where
|
|||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
/// stored by [`LlmpClient::to_env()`].
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
pub fn existing_client_from_env(
|
pub fn existing_client_from_env(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
env_name: &str,
|
env_name: &str,
|
||||||
@ -479,6 +483,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create an existing client from description
|
/// Create an existing client from description
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
pub fn existing_client_from_description(
|
pub fn existing_client_from_description(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
description: &LlmpClientDescription,
|
description: &LlmpClientDescription,
|
||||||
@ -487,6 +492,69 @@ where
|
|||||||
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
Self::new(llmp, configuration)
|
Self::new(llmp, configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a manager from a raw LLMP client
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn new(
|
||||||
|
llmp: LlmpClient<SP>,
|
||||||
|
configuration: EventConfig,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(LlmpEventManager {
|
||||||
|
hooks: tuple_list!(),
|
||||||
|
llmp,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
configuration,
|
||||||
|
serialization_time: Duration::ZERO,
|
||||||
|
deserialization_time: Duration::ZERO,
|
||||||
|
serializations_cnt: 0,
|
||||||
|
should_serialize_cnt: 0,
|
||||||
|
time_ref,
|
||||||
|
phantom: PhantomData,
|
||||||
|
custom_buf_handlers: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an LLMP event manager on a port
|
||||||
|
///
|
||||||
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
|
/// will act as a client.
|
||||||
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
pub fn on_port(
|
||||||
|
shmem_provider: SP,
|
||||||
|
port: u16,
|
||||||
|
configuration: EventConfig,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<LlmpEventManager<(), S, SP>, Error> {
|
||||||
|
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
|
Self::new(llmp, configuration, time_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
pub fn existing_client_from_env(
|
||||||
|
shmem_provider: SP,
|
||||||
|
env_name: &str,
|
||||||
|
configuration: EventConfig,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<LlmpEventManager<(), S, SP>, Error> {
|
||||||
|
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
|
Self::new(llmp, configuration, time_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an existing client from description
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn existing_client_from_description(
|
||||||
|
shmem_provider: SP,
|
||||||
|
description: &LlmpClientDescription,
|
||||||
|
configuration: EventConfig,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<LlmpEventManager<(), S, SP>, Error> {
|
||||||
|
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
|
Self::new(llmp, configuration, time_ref)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EMH, S, SP> LlmpEventManager<EMH, S, SP>
|
impl<EMH, S, SP> LlmpEventManager<EMH, S, SP>
|
||||||
@ -494,6 +562,135 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
|
/// Create a manager from a raw LLMP client with hooks
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
|
pub fn with_hooks(
|
||||||
|
llmp: LlmpClient<SP>,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
hooks,
|
||||||
|
llmp,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
configuration,
|
||||||
|
phantom: PhantomData,
|
||||||
|
custom_buf_handlers: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an LLMP event manager on a port with hook
|
||||||
|
///
|
||||||
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
|
/// will act as a client.
|
||||||
|
/// This will make a new connection to the broker so will return its new [`ClientId`], too
|
||||||
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
|
pub fn on_port_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
port: u16,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
|
/// create a event manager from env with hooks
|
||||||
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
|
pub fn existing_client_from_env_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
env_name: &str,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an existing client from description
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
|
pub fn existing_client_from_description_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
description: &LlmpClientDescription,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a manager from a raw LLMP client with hooks
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn with_hooks(
|
||||||
|
llmp: LlmpClient<SP>,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
hooks,
|
||||||
|
llmp,
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
configuration,
|
||||||
|
serialization_time: Duration::ZERO,
|
||||||
|
deserialization_time: Duration::ZERO,
|
||||||
|
serializations_cnt: 0,
|
||||||
|
should_serialize_cnt: 0,
|
||||||
|
time_ref,
|
||||||
|
phantom: PhantomData,
|
||||||
|
custom_buf_handlers: vec![],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an LLMP event manager on a port with hook
|
||||||
|
///
|
||||||
|
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
||||||
|
/// will act as a client.
|
||||||
|
/// This will make a new connection to the broker so will return its new [`ClientId`], too
|
||||||
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
pub fn on_port_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
port: u16,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks, time_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If a client respawns, it may reuse the existing connection, previously
|
||||||
|
/// stored by [`LlmpClient::to_env()`].
|
||||||
|
/// create a event manager from env with hooks
|
||||||
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
pub fn existing_client_from_env_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
env_name: &str,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks, time_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an existing client from description
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
pub fn existing_client_from_description_with_hooks(
|
||||||
|
shmem_provider: SP,
|
||||||
|
description: &LlmpClientDescription,
|
||||||
|
configuration: EventConfig,
|
||||||
|
hooks: EMH,
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
||||||
|
Self::with_hooks(llmp, configuration, hooks, time_ref)
|
||||||
|
}
|
||||||
|
|
||||||
/// Calling this function will tell the llmp broker that this client is exiting
|
/// Calling this function will tell the llmp broker that this client is exiting
|
||||||
/// This should be called from the restarter not from the actual fuzzer client
|
/// This should be called from the restarter not from the actual fuzzer client
|
||||||
/// This function serves the same roll as the `LlmpClient.send_exiting()`
|
/// This function serves the same roll as the `LlmpClient.send_exiting()`
|
||||||
@ -526,77 +723,12 @@ where
|
|||||||
log::info!("Asking he broker to be disconnected");
|
log::info!("Asking he broker to be disconnected");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
/// Create a manager from a raw LLMP client with hooks
|
|
||||||
pub fn with_hooks(
|
|
||||||
llmp: LlmpClient<SP>,
|
|
||||||
configuration: EventConfig,
|
|
||||||
hooks: EMH,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Ok(Self {
|
|
||||||
hooks,
|
|
||||||
llmp,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
|
||||||
configuration,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
serialization_time: Duration::ZERO,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
deserialization_time: Duration::ZERO,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
serializations_cnt: 0,
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
|
||||||
should_serialize_cnt: 0,
|
|
||||||
phantom: PhantomData,
|
|
||||||
custom_buf_handlers: vec![],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an LLMP event manager on a port with hook
|
|
||||||
///
|
|
||||||
/// If the port is not yet bound, it will act as a broker; otherwise, it
|
|
||||||
/// will act as a client.
|
|
||||||
/// This will make a new connection to the broker so will return its new [`ClientId`], too
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn on_port_with_hooks(
|
|
||||||
shmem_provider: SP,
|
|
||||||
port: u16,
|
|
||||||
configuration: EventConfig,
|
|
||||||
hooks: EMH,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let llmp = LlmpClient::create_attach_to_tcp(shmem_provider, port)?;
|
|
||||||
Self::with_hooks(llmp, configuration, hooks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously
|
|
||||||
/// stored by [`LlmpClient::to_env()`].
|
|
||||||
/// create a event manager from env with hooks
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn existing_client_from_env_with_hooks(
|
|
||||||
shmem_provider: SP,
|
|
||||||
env_name: &str,
|
|
||||||
configuration: EventConfig,
|
|
||||||
hooks: EMH,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let llmp = LlmpClient::on_existing_from_env(shmem_provider, env_name)?;
|
|
||||||
Self::with_hooks(llmp, configuration, hooks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describe the client event manager's LLMP parts in a restorable fashion
|
/// Describe the client event manager's LLMP parts in a restorable fashion
|
||||||
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
pub fn describe(&self) -> Result<LlmpClientDescription, Error> {
|
||||||
self.llmp.describe()
|
self.llmp.describe()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an existing client from description
|
|
||||||
pub fn existing_client_from_description_with_hooks(
|
|
||||||
shmem_provider: SP,
|
|
||||||
description: &LlmpClientDescription,
|
|
||||||
configuration: EventConfig,
|
|
||||||
hooks: EMH,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let llmp = LlmpClient::existing_client_from_description(shmem_provider, description)?;
|
|
||||||
Self::with_hooks(llmp, configuration, hooks)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write the config for a client [`EventManager`] to env vars, a new
|
/// Write the config for a client [`EventManager`] to env vars, a new
|
||||||
/// client can reattach using [`LlmpEventManager::existing_client_from_env()`].
|
/// client can reattach using [`LlmpEventManager::existing_client_from_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -958,6 +1090,10 @@ where
|
|||||||
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
fn should_serialize_cnt_mut(&mut self) -> &mut usize {
|
||||||
self.llmp_mgr.should_serialize_cnt_mut()
|
self.llmp_mgr.should_serialize_cnt_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn time_ref(&self) -> &Reference<TimeObserver> {
|
||||||
|
&self.llmp_mgr.time_ref
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
@ -1172,7 +1308,7 @@ pub enum ManagerKind {
|
|||||||
/// Sets up a restarting fuzzer, using the [`StdShMemProvider`], and standard features.
|
/// Sets up a restarting fuzzer, using the [`StdShMemProvider`], and standard features.
|
||||||
/// The restarting mgr is a combination of restarter and runner, that can be used on systems with and without `fork` support.
|
/// The restarting mgr is a combination of restarter and runner, that can be used on systems with and without `fork` support.
|
||||||
/// The restarter will spawn a new process each time the child crashes or timeouts.
|
/// The restarter will spawn a new process each time the child crashes or timeouts.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(all(feature = "std", not(feature = "adaptive_serialization")))]
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn setup_restarting_mgr_std<MT, S>(
|
pub fn setup_restarting_mgr_std<MT, S>(
|
||||||
monitor: MT,
|
monitor: MT,
|
||||||
@ -1199,6 +1335,38 @@ where
|
|||||||
.launch()
|
.launch()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets up a restarting fuzzer, using the [`StdShMemProvider`], and standard features.
|
||||||
|
/// The restarting mgr is a combination of restarter and runner, that can be used on systems with and without `fork` support.
|
||||||
|
/// The restarter will spawn a new process each time the child crashes or timeouts.
|
||||||
|
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
|
pub fn setup_restarting_mgr_std<MT, S>(
|
||||||
|
monitor: MT,
|
||||||
|
broker_port: u16,
|
||||||
|
configuration: EventConfig,
|
||||||
|
time_obs: &TimeObserver,
|
||||||
|
) -> Result<
|
||||||
|
(
|
||||||
|
Option<S>,
|
||||||
|
LlmpRestartingEventManager<(), S, StdShMemProvider>,
|
||||||
|
),
|
||||||
|
Error,
|
||||||
|
>
|
||||||
|
where
|
||||||
|
MT: Monitor + Clone,
|
||||||
|
S: State + HasExecutions,
|
||||||
|
{
|
||||||
|
RestartingMgr::builder()
|
||||||
|
.shmem_provider(StdShMemProvider::new()?)
|
||||||
|
.monitor(Some(monitor))
|
||||||
|
.broker_port(broker_port)
|
||||||
|
.configuration(configuration)
|
||||||
|
.hooks(tuple_list!())
|
||||||
|
.time_ref(time_obs.reference())
|
||||||
|
.build()
|
||||||
|
.launch()
|
||||||
|
}
|
||||||
|
|
||||||
/// Provides a `builder` which can be used to build a [`RestartingMgr`], which is a combination of a
|
/// Provides a `builder` which can be used to build a [`RestartingMgr`], which is a combination of a
|
||||||
/// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The
|
/// `restarter` and `runner`, that can be used on systems both with and without `fork` support. The
|
||||||
/// `restarter` will start a new process each time the child crashes or times out.
|
/// `restarter` will start a new process each time the child crashes or times out.
|
||||||
@ -1243,6 +1411,8 @@ where
|
|||||||
serialize_state: LlmpShouldSaveState,
|
serialize_state: LlmpShouldSaveState,
|
||||||
/// The hooks passed to event manager:
|
/// The hooks passed to event manager:
|
||||||
hooks: EMH,
|
hooks: EMH,
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
time_ref: Reference<TimeObserver>,
|
||||||
#[builder(setter(skip), default = PhantomData)]
|
#[builder(setter(skip), default = PhantomData)]
|
||||||
phantom_data: PhantomData<(EMH, S)>,
|
phantom_data: PhantomData<(EMH, S)>,
|
||||||
}
|
}
|
||||||
@ -1310,11 +1480,19 @@ where
|
|||||||
return Err(Error::shutting_down());
|
return Err(Error::shutting_down());
|
||||||
}
|
}
|
||||||
LlmpConnection::IsClient { client } => {
|
LlmpConnection::IsClient { client } => {
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let mgr = LlmpEventManager::<EMH, S, SP>::with_hooks(
|
let mgr = LlmpEventManager::<EMH, S, SP>::with_hooks(
|
||||||
client,
|
client,
|
||||||
self.configuration,
|
self.configuration,
|
||||||
self.hooks,
|
self.hooks,
|
||||||
)?;
|
)?;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let mgr = LlmpEventManager::<EMH, S, SP>::with_hooks(
|
||||||
|
client,
|
||||||
|
self.configuration,
|
||||||
|
self.hooks,
|
||||||
|
self.time_ref.clone(),
|
||||||
|
)?;
|
||||||
(mgr, None)
|
(mgr, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1331,12 +1509,21 @@ where
|
|||||||
}
|
}
|
||||||
ManagerKind::Client { cpu_core } => {
|
ManagerKind::Client { cpu_core } => {
|
||||||
// We are a client
|
// We are a client
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let mgr = LlmpEventManager::<EMH, S, SP>::on_port_with_hooks(
|
let mgr = LlmpEventManager::<EMH, S, SP>::on_port_with_hooks(
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
self.broker_port,
|
self.broker_port,
|
||||||
self.configuration,
|
self.configuration,
|
||||||
self.hooks,
|
self.hooks,
|
||||||
)?;
|
)?;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let mgr = LlmpEventManager::<EMH, S, SP>::on_port_with_hooks(
|
||||||
|
self.shmem_provider.clone(),
|
||||||
|
self.broker_port,
|
||||||
|
self.configuration,
|
||||||
|
self.hooks,
|
||||||
|
self.time_ref.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
(mgr, cpu_core)
|
(mgr, cpu_core)
|
||||||
}
|
}
|
||||||
@ -1449,15 +1636,25 @@ where
|
|||||||
// If we're restarting, deserialize the old state.
|
// If we're restarting, deserialize the old state.
|
||||||
let (state, mut mgr) =
|
let (state, mut mgr) =
|
||||||
if let Some((state_opt, mgr_description)) = staterestorer.restore()? {
|
if let Some((state_opt, mgr_description)) = staterestorer.restore()? {
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
|
let llmp_mgr = LlmpEventManager::existing_client_from_description_with_hooks(
|
||||||
|
new_shmem_provider,
|
||||||
|
&mgr_description,
|
||||||
|
self.configuration,
|
||||||
|
self.hooks,
|
||||||
|
)?;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let llmp_mgr = LlmpEventManager::existing_client_from_description_with_hooks(
|
||||||
|
new_shmem_provider,
|
||||||
|
&mgr_description,
|
||||||
|
self.configuration,
|
||||||
|
self.hooks,
|
||||||
|
self.time_ref.clone(),
|
||||||
|
)?;
|
||||||
(
|
(
|
||||||
state_opt,
|
state_opt,
|
||||||
LlmpRestartingEventManager::with_save_state(
|
LlmpRestartingEventManager::with_save_state(
|
||||||
LlmpEventManager::existing_client_from_description_with_hooks(
|
llmp_mgr,
|
||||||
new_shmem_provider,
|
|
||||||
&mgr_description,
|
|
||||||
self.configuration,
|
|
||||||
self.hooks,
|
|
||||||
)?,
|
|
||||||
staterestorer,
|
staterestorer,
|
||||||
self.serialize_state,
|
self.serialize_state,
|
||||||
),
|
),
|
||||||
@ -1465,12 +1662,21 @@ where
|
|||||||
} else {
|
} else {
|
||||||
log::info!("First run. Let's set it all up");
|
log::info!("First run. Let's set it all up");
|
||||||
// Mgr to send and receive msgs from/to all other fuzzer instances
|
// Mgr to send and receive msgs from/to all other fuzzer instances
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let mgr = LlmpEventManager::<EMH, S, SP>::existing_client_from_env_with_hooks(
|
let mgr = LlmpEventManager::<EMH, S, SP>::existing_client_from_env_with_hooks(
|
||||||
new_shmem_provider,
|
new_shmem_provider,
|
||||||
_ENV_FUZZER_BROKER_CLIENT_INITIAL,
|
_ENV_FUZZER_BROKER_CLIENT_INITIAL,
|
||||||
self.configuration,
|
self.configuration,
|
||||||
self.hooks,
|
self.hooks,
|
||||||
)?;
|
)?;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let mgr = LlmpEventManager::<EMH, S, SP>::existing_client_from_env_with_hooks(
|
||||||
|
new_shmem_provider,
|
||||||
|
_ENV_FUZZER_BROKER_CLIENT_INITIAL,
|
||||||
|
self.configuration,
|
||||||
|
self.hooks,
|
||||||
|
self.time_ref.clone(),
|
||||||
|
)?;
|
||||||
|
|
||||||
(
|
(
|
||||||
None,
|
None,
|
||||||
@ -1854,6 +2060,8 @@ where
|
|||||||
mod tests {
|
mod tests {
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
|
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use libafl_bolts::tuples::Referenceable;
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{LlmpClient, LlmpSharedMap},
|
llmp::{LlmpClient, LlmpSharedMap},
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
@ -1872,6 +2080,7 @@ mod tests {
|
|||||||
fuzzer::Fuzzer,
|
fuzzer::Fuzzer,
|
||||||
inputs::BytesInput,
|
inputs::BytesInput,
|
||||||
mutators::BitFlipMutator,
|
mutators::BitFlipMutator,
|
||||||
|
observers::TimeObserver,
|
||||||
schedulers::RandScheduler,
|
schedulers::RandScheduler,
|
||||||
stages::StdMutationalStage,
|
stages::StdMutationalStage,
|
||||||
state::StdState,
|
state::StdState,
|
||||||
@ -1884,6 +2093,10 @@ mod tests {
|
|||||||
fn test_mgr_state_restore() {
|
fn test_mgr_state_restore() {
|
||||||
let rand = StdRand::with_seed(0);
|
let rand = StdRand::with_seed(0);
|
||||||
|
|
||||||
|
let time = TimeObserver::new("time");
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let time_ref = time.reference();
|
||||||
|
|
||||||
let mut corpus = InMemoryCorpus::<BytesInput>::new();
|
let mut corpus = InMemoryCorpus::<BytesInput>::new();
|
||||||
let testcase = Testcase::new(vec![0; 4].into());
|
let testcase = Testcase::new(vec![0; 4].into());
|
||||||
corpus.add(testcase).unwrap();
|
corpus.add(testcase).unwrap();
|
||||||
@ -1910,7 +2123,11 @@ mod tests {
|
|||||||
llmp_client.mark_safe_to_unmap();
|
llmp_client.mark_safe_to_unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let mut llmp_mgr = LlmpEventManager::new(llmp_client, "fuzzer".into()).unwrap();
|
let mut llmp_mgr = LlmpEventManager::new(llmp_client, "fuzzer".into()).unwrap();
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let mut llmp_mgr =
|
||||||
|
LlmpEventManager::new(llmp_client, "fuzzer".into(), time_ref.clone()).unwrap();
|
||||||
|
|
||||||
let scheduler = RandScheduler::new();
|
let scheduler = RandScheduler::new();
|
||||||
|
|
||||||
@ -1922,7 +2139,7 @@ mod tests {
|
|||||||
let mut harness = |_buf: &BytesInput| ExitKind::Ok;
|
let mut harness = |_buf: &BytesInput| ExitKind::Ok;
|
||||||
let mut executor = InProcessExecutor::new(
|
let mut executor = InProcessExecutor::new(
|
||||||
&mut harness,
|
&mut harness,
|
||||||
tuple_list!(),
|
tuple_list!(time),
|
||||||
&mut fuzzer,
|
&mut fuzzer,
|
||||||
&mut state,
|
&mut state,
|
||||||
&mut llmp_mgr,
|
&mut llmp_mgr,
|
||||||
@ -1952,22 +2169,29 @@ mod tests {
|
|||||||
assert!(sc_cpy.has_content());
|
assert!(sc_cpy.has_content());
|
||||||
|
|
||||||
let (mut state_clone, mgr_description) = staterestorer.restore().unwrap().unwrap();
|
let (mut state_clone, mgr_description) = staterestorer.restore().unwrap().unwrap();
|
||||||
|
#[cfg(not(feature = "adaptive_serialization"))]
|
||||||
let mut llmp_clone = LlmpEventManager::existing_client_from_description(
|
let mut llmp_clone = LlmpEventManager::existing_client_from_description(
|
||||||
shmem_provider,
|
shmem_provider,
|
||||||
&mgr_description,
|
&mgr_description,
|
||||||
"fuzzer".into(),
|
"fuzzer".into(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
let mut llmp_clone = LlmpEventManager::existing_client_from_description(
|
||||||
|
shmem_provider,
|
||||||
|
&mgr_description,
|
||||||
|
"fuzzer".into(),
|
||||||
|
time_ref,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if false {
|
fuzzer
|
||||||
fuzzer
|
.fuzz_one(
|
||||||
.fuzz_one(
|
&mut stages,
|
||||||
&mut stages,
|
&mut executor,
|
||||||
&mut executor,
|
&mut state_clone,
|
||||||
&mut state_clone,
|
&mut llmp_clone,
|
||||||
&mut llmp_clone,
|
)
|
||||||
)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ use ahash::RandomState;
|
|||||||
pub use launcher::*;
|
pub use launcher::*;
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Handler, Signal};
|
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Handler, Signal};
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use libafl_bolts::tuples::{MatchNameRef, Reference};
|
||||||
use libafl_bolts::{current_time, ClientId};
|
use libafl_bolts::{current_time, ClientId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -119,7 +121,7 @@ impl Handler for ShutdownSignalData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A per-fuzzer unique `ID`, usually starting with `0` and increasing
|
/// A per-fuzzer unique `ID`, usually starting with `0` and increasing
|
||||||
/// by `1` in multiprocessed [`EventManager`]s, such as [`self::llmp::LlmpEventManager`].
|
/// by `1` in multiprocessed [`EventManager`]s, such as [`LlmpEventManager`].
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct EventManagerId(
|
pub struct EventManagerId(
|
||||||
@ -129,6 +131,8 @@ pub struct EventManagerId(
|
|||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
use crate::monitors::ClientPerfMonitor;
|
use crate::monitors::ClientPerfMonitor;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use crate::observers::TimeObserver;
|
||||||
use crate::{inputs::UsesInput, stages::HasCurrentStage, state::UsesState};
|
use crate::{inputs::UsesInput, stages::HasCurrentStage, state::UsesState};
|
||||||
|
|
||||||
/// The log event severity
|
/// The log event severity
|
||||||
@ -415,7 +419,7 @@ where
|
|||||||
pub trait EventFirer: UsesState {
|
pub trait EventFirer: UsesState {
|
||||||
/// Send off an [`Event`] to the broker
|
/// Send off an [`Event`] to the broker
|
||||||
///
|
///
|
||||||
/// For multi-processed managers, such as [`llmp::LlmpEventManager`],
|
/// For multi-processed managers, such as [`LlmpEventManager`],
|
||||||
/// this serializes the [`Event`] and commits it to the [`llmp`] page.
|
/// this serializes the [`Event`] and commits it to the [`llmp`] page.
|
||||||
/// In this case, if you `fire` faster than the broker can consume
|
/// In this case, if you `fire` faster than the broker can consume
|
||||||
/// (for example for each [`Input`], on multiple cores)
|
/// (for example for each [`Input`], on multiple cores)
|
||||||
@ -466,7 +470,7 @@ where
|
|||||||
{
|
{
|
||||||
/// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker.
|
/// Given the last time, if `monitor_timeout` seconds passed, send off an info/monitor/heartbeat message to the broker.
|
||||||
/// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent)
|
/// Returns the new `last` time (so the old one, unless `monitor_timeout` time has passed and monitor have been sent)
|
||||||
/// Will return an [`crate::Error`], if the stats could not be sent.
|
/// Will return an [`Error`], if the stats could not be sent.
|
||||||
fn maybe_report_progress(
|
fn maybe_report_progress(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
@ -487,7 +491,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send off an info/monitor/heartbeat message to the broker.
|
/// Send off an info/monitor/heartbeat message to the broker.
|
||||||
/// Will return an [`crate::Error`], if the stats could not be sent.
|
/// Will return an [`Error`], if the stats could not be sent.
|
||||||
fn report_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
|
fn report_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
|
||||||
let executions = *state.executions();
|
let executions = *state.executions();
|
||||||
let cur = current_time();
|
let cur = current_time();
|
||||||
@ -875,6 +879,9 @@ pub trait AdaptiveSerializer {
|
|||||||
/// How many times shoukd have been serialized an observer (mut)
|
/// How many times shoukd have been serialized an observer (mut)
|
||||||
fn should_serialize_cnt_mut(&mut self) -> &mut usize;
|
fn should_serialize_cnt_mut(&mut self) -> &mut usize;
|
||||||
|
|
||||||
|
/// A [`Reference`] to the time observer to determine the `time_factor`
|
||||||
|
fn time_ref(&self) -> &Reference<TimeObserver>;
|
||||||
|
|
||||||
/// Serialize the observer using the `time_factor` and `percentage_threshold`.
|
/// Serialize the observer using the `time_factor` and `percentage_threshold`.
|
||||||
/// These parameters are unique to each of the different types of `EventManager`
|
/// These parameters are unique to each of the different types of `EventManager`
|
||||||
fn serialize_observers_adaptive<S, OT>(
|
fn serialize_observers_adaptive<S, OT>(
|
||||||
@ -888,7 +895,7 @@ pub trait AdaptiveSerializer {
|
|||||||
S: UsesInput,
|
S: UsesInput,
|
||||||
{
|
{
|
||||||
let exec_time = observers
|
let exec_time = observers
|
||||||
.match_name::<crate::observers::TimeObserver>("time")
|
.get(self.time_ref())
|
||||||
.map(|o| o.last_runtime().unwrap_or(Duration::ZERO))
|
.map(|o| o.last_runtime().unwrap_or(Duration::ZERO))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
observers::UsesObservers,
|
observers::UsesObservers,
|
||||||
@ -80,12 +82,12 @@ where
|
|||||||
A: HasObservers,
|
A: HasObservers,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &Self::Observers {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.primary.observers()
|
self.primary.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut Self::Observers {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.primary.observers_mut()
|
self.primary.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ use std::{
|
|||||||
|
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
fs::{get_unique_std_input_file, InputFile},
|
fs::{get_unique_std_input_file, InputFile},
|
||||||
tuples::MatchName,
|
tuples::{MatchName, RefIndexable},
|
||||||
AsSlice,
|
AsSlice,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -397,12 +397,12 @@ where
|
|||||||
T: Debug,
|
T: Debug,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,10 @@
|
|||||||
//!
|
//!
|
||||||
use core::{cell::UnsafeCell, fmt::Debug, ptr};
|
use core::{cell::UnsafeCell, fmt::Debug, ptr};
|
||||||
|
|
||||||
use libafl_bolts::{ownedref::OwnedMutPtr, tuples::MatchName};
|
use libafl_bolts::{
|
||||||
|
ownedref::OwnedMutPtr,
|
||||||
|
tuples::{MatchName, RefIndexable},
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -183,6 +186,7 @@ where
|
|||||||
B: MatchName,
|
B: MatchName,
|
||||||
DOT: MatchName,
|
DOT: MatchName,
|
||||||
{
|
{
|
||||||
|
#[allow(deprecated)]
|
||||||
fn match_name<T>(&self, name: &str) -> Option<&T> {
|
fn match_name<T>(&self, name: &str) -> Option<&T> {
|
||||||
if let Some(t) = self.primary.as_ref().match_name::<T>(name) {
|
if let Some(t) = self.primary.as_ref().match_name::<T>(name) {
|
||||||
Some(t)
|
Some(t)
|
||||||
@ -192,6 +196,8 @@ where
|
|||||||
self.differential.match_name::<T>(name)
|
self.differential.match_name::<T>(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(deprecated)]
|
||||||
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
|
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
|
||||||
if let Some(t) = self.primary.as_mut().match_name_mut::<T>(name) {
|
if let Some(t) = self.primary.as_mut().match_name_mut::<T>(name) {
|
||||||
Some(t)
|
Some(t)
|
||||||
@ -238,26 +244,25 @@ where
|
|||||||
DOT: DifferentialObserversTuple<OTA, OTB, A::State>,
|
DOT: DifferentialObserversTuple<OTA, OTB, A::State>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &ProxyObserversTuple<OTA, OTB, DOT> {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.observers
|
self.observers
|
||||||
.get()
|
.get()
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set(self.primary.observers(), self.secondary.observers());
|
.set(&*self.primary.observers(), &*self.secondary.observers());
|
||||||
self.observers.get().as_ref().unwrap()
|
RefIndexable::from(self.observers.get().as_ref().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut ProxyObserversTuple<OTA, OTB, DOT> {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.observers
|
self.observers.get().as_mut().unwrap().set(
|
||||||
.get()
|
&*self.primary.observers_mut(),
|
||||||
.as_mut()
|
&*self.secondary.observers_mut(),
|
||||||
.unwrap()
|
);
|
||||||
.set(self.primary.observers(), self.secondary.observers());
|
RefIndexable::from(self.observers.get().as_mut().unwrap())
|
||||||
self.observers.get().as_mut().unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ use libafl_bolts::{
|
|||||||
fs::{get_unique_std_input_file, InputFile},
|
fs::{get_unique_std_input_file, InputFile},
|
||||||
os::{dup2, pipes::Pipe},
|
os::{dup2, pipes::Pipe},
|
||||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||||
tuples::Prepend,
|
tuples::{MatchNameRef, Prepend, RefIndexable, Reference, Referenceable},
|
||||||
AsSlice, AsSliceMut, Truncate,
|
AsSlice, AsSliceMut, Truncate,
|
||||||
};
|
};
|
||||||
use nix::{
|
use nix::{
|
||||||
@ -497,6 +497,8 @@ where
|
|||||||
map: Option<SP::ShMem>,
|
map: Option<SP::ShMem>,
|
||||||
phantom: PhantomData<S>,
|
phantom: PhantomData<S>,
|
||||||
map_size: Option<usize>,
|
map_size: Option<usize>,
|
||||||
|
#[cfg(feature = "regex")]
|
||||||
|
asan_obs: Reference<AsanBacktraceObserver>,
|
||||||
timeout: TimeSpec,
|
timeout: TimeSpec,
|
||||||
crash_exitcode: Option<i8>,
|
crash_exitcode: Option<i8>,
|
||||||
}
|
}
|
||||||
@ -584,6 +586,8 @@ pub struct ForkserverExecutorBuilder<'a, SP> {
|
|||||||
real_map_size: i32,
|
real_map_size: i32,
|
||||||
kill_signal: Option<Signal>,
|
kill_signal: Option<Signal>,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
|
#[cfg(feature = "regex")]
|
||||||
|
asan_obs: Option<Reference<AsanBacktraceObserver>>,
|
||||||
crash_exitcode: Option<i8>,
|
crash_exitcode: Option<i8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,6 +637,10 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> {
|
|||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
map_size: self.map_size,
|
map_size: self.map_size,
|
||||||
timeout,
|
timeout,
|
||||||
|
asan_obs: self
|
||||||
|
.asan_obs
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(AsanBacktraceObserver::default().reference()),
|
||||||
crash_exitcode: self.crash_exitcode,
|
crash_exitcode: self.crash_exitcode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -691,6 +699,10 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> {
|
|||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
map_size: self.map_size,
|
map_size: self.map_size,
|
||||||
timeout,
|
timeout,
|
||||||
|
asan_obs: self
|
||||||
|
.asan_obs
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(AsanBacktraceObserver::default().reference()),
|
||||||
crash_exitcode: self.crash_exitcode,
|
crash_exitcode: self.crash_exitcode,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1058,6 +1070,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> {
|
|||||||
max_input_size: MAX_INPUT_SIZE_DEFAULT,
|
max_input_size: MAX_INPUT_SIZE_DEFAULT,
|
||||||
kill_signal: None,
|
kill_signal: None,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
|
asan_obs: None,
|
||||||
crash_exitcode: None,
|
crash_exitcode: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1084,6 +1097,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> {
|
|||||||
max_input_size: MAX_INPUT_SIZE_DEFAULT,
|
max_input_size: MAX_INPUT_SIZE_DEFAULT,
|
||||||
kill_signal: None,
|
kill_signal: None,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
|
asan_obs: None,
|
||||||
crash_exitcode: None,
|
crash_exitcode: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1178,10 +1192,7 @@ where
|
|||||||
if libc::WIFSIGNALED(self.forkserver().status()) || exitcode_is_crash {
|
if libc::WIFSIGNALED(self.forkserver().status()) || exitcode_is_crash {
|
||||||
exit_kind = ExitKind::Crash;
|
exit_kind = ExitKind::Crash;
|
||||||
#[cfg(feature = "regex")]
|
#[cfg(feature = "regex")]
|
||||||
if let Some(asan_observer) = self
|
if let Some(asan_observer) = self.observers.get_mut(&self.asan_obs) {
|
||||||
.observers_mut()
|
|
||||||
.match_name_mut::<AsanBacktraceObserver>("AsanBacktraceObserver")
|
|
||||||
{
|
|
||||||
asan_observer.parse_asan_output_from_asan_log_file(pid)?;
|
asan_observer.parse_asan_output_from_asan_log_file(pid)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1229,13 +1240,13 @@ where
|
|||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ use core::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::tuples::{tuple_list, Merge};
|
use libafl_bolts::tuples::{tuple_list, Merge, RefIndexable};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use windows::Win32::System::Threading::SetThreadStackGuarantee;
|
use windows::Win32::System::Threading::SetThreadStackGuarantee;
|
||||||
|
|
||||||
@ -85,13 +85,13 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use core::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::tuples::tuple_list;
|
use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||||
|
|
||||||
#[cfg(any(unix, feature = "std"))]
|
#[cfg(any(unix, feature = "std"))]
|
||||||
use crate::executors::hooks::inprocess::GLOBAL_STATE;
|
use crate::executors::hooks::inprocess::GLOBAL_STATE;
|
||||||
@ -151,12 +151,12 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
|||||||
E::State: HasExecutions + HasSolutions + HasCorpus,
|
E::State: HasExecutions + HasSolutions + HasCorpus,
|
||||||
Z: HasObjective<Objective = OF, State = E::State>,
|
Z: HasObjective<Objective = OF, State = E::State>,
|
||||||
{
|
{
|
||||||
let observers = executor.observers_mut();
|
let mut observers = executor.observers_mut();
|
||||||
|
|
||||||
observers
|
observers
|
||||||
.post_exec_all(state, input, &exitkind)
|
.post_exec_all(state, input, &exitkind)
|
||||||
@ -446,7 +446,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
|||||||
|
|
||||||
let interesting = fuzzer
|
let interesting = fuzzer
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, event_mgr, input, observers, &exitkind)
|
.is_interesting(state, event_mgr, input, &*observers, &exitkind)
|
||||||
.expect("In run_observers_and_save_state objective failure.");
|
.expect("In run_observers_and_save_state objective failure.");
|
||||||
|
|
||||||
if interesting {
|
if interesting {
|
||||||
@ -456,7 +456,7 @@ pub fn run_observers_and_save_state<E, EM, OF, Z>(
|
|||||||
new_testcase.set_parent_id_optional(*state.corpus().current());
|
new_testcase.set_parent_id_optional(*state.corpus().current());
|
||||||
fuzzer
|
fuzzer
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.append_metadata(state, event_mgr, observers, &mut new_testcase)
|
.append_metadata(state, event_mgr, &*observers, &mut new_testcase)
|
||||||
.expect("Failed adding metadata");
|
.expect("Failed adding metadata");
|
||||||
state
|
state
|
||||||
.solutions_mut()
|
.solutions_mut()
|
||||||
|
@ -8,7 +8,7 @@ use core::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::tuples::tuple_list;
|
use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
@ -142,12 +142,12 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ use core::{
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
os::unix_signals::Signal,
|
os::unix_signals::Signal,
|
||||||
shmem::ShMemProvider,
|
shmem::ShMemProvider,
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge, RefIndexable},
|
||||||
};
|
};
|
||||||
use nix::{
|
use nix::{
|
||||||
sys::wait::{waitpid, WaitStatus},
|
sys::wait::{waitpid, WaitStatus},
|
||||||
@ -339,12 +339,12 @@ where
|
|||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use core::{
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
os::unix_signals::{ucontext_t, Signal},
|
os::unix_signals::{ucontext_t, Signal},
|
||||||
shmem::ShMemProvider,
|
shmem::ShMemProvider,
|
||||||
tuples::tuple_list,
|
tuples::{tuple_list, RefIndexable},
|
||||||
};
|
};
|
||||||
use libc::siginfo_t;
|
use libc::siginfo_t;
|
||||||
use nix::unistd::{fork, ForkResult};
|
use nix::unistd::{fork, ForkResult};
|
||||||
@ -255,12 +255,12 @@ where
|
|||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ pub mod child_signal_handlers {
|
|||||||
let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
|
let data = addr_of_mut!(FORK_EXECUTOR_GLOBAL_DATA);
|
||||||
if !data.is_null() && (*data).is_valid() {
|
if !data.is_null() && (*data).is_valid() {
|
||||||
let executor = (*data).executor_mut::<E>();
|
let executor = (*data).executor_mut::<E>();
|
||||||
let observers = executor.observers_mut();
|
let mut observers = executor.observers_mut();
|
||||||
let state = (*data).state_mut::<E::State>();
|
let state = (*data).state_mut::<E::State>();
|
||||||
// Invalidate data to not execute again the observer hooks in the crash handler
|
// Invalidate data to not execute again the observer hooks in the crash handler
|
||||||
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
let input = (*data).take_current_input::<<E::State as UsesInput>::Input>();
|
||||||
@ -326,7 +326,7 @@ pub mod child_signal_handlers {
|
|||||||
{
|
{
|
||||||
if data.is_valid() {
|
if data.is_valid() {
|
||||||
let executor = data.executor_mut::<E>();
|
let executor = data.executor_mut::<E>();
|
||||||
let observers = executor.observers_mut();
|
let mut observers = executor.observers_mut();
|
||||||
let state = data.state_mut::<E::State>();
|
let state = data.state_mut::<E::State>();
|
||||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||||
observers
|
observers
|
||||||
@ -349,7 +349,7 @@ pub mod child_signal_handlers {
|
|||||||
{
|
{
|
||||||
if data.is_valid() {
|
if data.is_valid() {
|
||||||
let executor = data.executor_mut::<E>();
|
let executor = data.executor_mut::<E>();
|
||||||
let observers = executor.observers_mut();
|
let mut observers = executor.observers_mut();
|
||||||
let state = data.state_mut::<E::State>();
|
let state = data.state_mut::<E::State>();
|
||||||
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
let input = data.take_current_input::<<E::State as UsesInput>::Input>();
|
||||||
observers
|
observers
|
||||||
|
@ -5,7 +5,10 @@ use core::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::{shmem::ShMemProvider, tuples::tuple_list};
|
use libafl_bolts::{
|
||||||
|
shmem::ShMemProvider,
|
||||||
|
tuples::{tuple_list, RefIndexable},
|
||||||
|
};
|
||||||
use nix::unistd::{fork, ForkResult};
|
use nix::unistd::{fork, ForkResult};
|
||||||
|
|
||||||
use super::super::hooks::ExecutorHooksTuple;
|
use super::super::hooks::ExecutorHooksTuple;
|
||||||
@ -245,12 +248,12 @@ where
|
|||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ pub use inprocess::InProcessExecutor;
|
|||||||
pub use inprocess_fork::InProcessForkExecutor;
|
pub use inprocess_fork::InProcessForkExecutor;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use libafl_bolts::os::unix_signals::Signal;
|
use libafl_bolts::os::unix_signals::Signal;
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use shadow::ShadowExecutor;
|
pub use shadow::ShadowExecutor;
|
||||||
pub use with_observers::WithObservers;
|
pub use with_observers::WithObservers;
|
||||||
@ -110,10 +111,10 @@ libafl_bolts::impl_serdeany!(DiffExitKind);
|
|||||||
/// Holds a tuple of Observers
|
/// Holds a tuple of Observers
|
||||||
pub trait HasObservers: UsesObservers {
|
pub trait HasObservers: UsesObservers {
|
||||||
/// Get the linked observers
|
/// Get the linked observers
|
||||||
fn observers(&self) -> &Self::Observers;
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers>;
|
||||||
|
|
||||||
/// Get the linked observers (mutable)
|
/// Get the linked observers (mutable)
|
||||||
fn observers_mut(&mut self) -> &mut Self::Observers;
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An executor takes the given inputs, and runs the harness/target.
|
/// An executor takes the given inputs, and runs the harness/target.
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use core::fmt::{self, Debug, Formatter};
|
use core::fmt::{self, Debug, Formatter};
|
||||||
|
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
observers::{ObserversTuple, UsesObservers},
|
observers::{ObserversTuple, UsesObservers},
|
||||||
@ -45,14 +47,14 @@ where
|
|||||||
|
|
||||||
/// The shadow observers are not considered by the feedbacks and the manager, mutable
|
/// The shadow observers are not considered by the feedbacks and the manager, mutable
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shadow_observers(&self) -> &SOT {
|
pub fn shadow_observers(&self) -> RefIndexable<&SOT, SOT> {
|
||||||
&self.shadow_observers
|
RefIndexable::from(&self.shadow_observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The shadow observers are not considered by the feedbacks and the manager, mutable
|
/// The shadow observers are not considered by the feedbacks and the manager, mutable
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn shadow_observers_mut(&mut self) -> &mut SOT {
|
pub fn shadow_observers_mut(&mut self) -> RefIndexable<&mut SOT, SOT> {
|
||||||
&mut self.shadow_observers
|
RefIndexable::from(&mut self.shadow_observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,12 +96,12 @@ where
|
|||||||
SOT: ObserversTuple<E::State>,
|
SOT: ObserversTuple<E::State>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &Self::Observers {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.executor.observers()
|
self.executor.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut Self::Observers {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.executor.observers_mut()
|
self.executor.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
observers::{ObserversTuple, UsesObservers},
|
observers::{ObserversTuple, UsesObservers},
|
||||||
@ -53,12 +55,12 @@ where
|
|||||||
E: UsesState,
|
E: UsesState,
|
||||||
OT: ObserversTuple<E::State>,
|
OT: ObserversTuple<E::State>,
|
||||||
{
|
{
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,10 @@
|
|||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use core::{fmt::Debug, marker::PhantomData};
|
use core::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
use libafl_bolts::Named;
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
@ -24,30 +27,30 @@ use crate::{
|
|||||||
/// to be not interesting.
|
/// to be not interesting.
|
||||||
/// Requires a [`ConcolicObserver`] to observe the concolic trace.
|
/// Requires a [`ConcolicObserver`] to observe the concolic trace.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ConcolicFeedback<S> {
|
pub struct ConcolicFeedback<'map, S> {
|
||||||
name: Cow<'static, str>,
|
obs_ref: Reference<ConcolicObserver<'map>>,
|
||||||
phantom: PhantomData<S>,
|
phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> ConcolicFeedback<S> {
|
impl<'map, S> ConcolicFeedback<'map, S> {
|
||||||
/// Creates a concolic feedback from an observer
|
/// Creates a concolic feedback from an observer
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_observer(observer: &ConcolicObserver) -> Self {
|
pub fn from_observer(observer: &ConcolicObserver<'map>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: observer.name().clone(),
|
obs_ref: observer.reference(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Named for ConcolicFeedback<S> {
|
impl<S> Named for ConcolicFeedback<'_, S> {
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
self.obs_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Feedback<S> for ConcolicFeedback<S>
|
impl<S> Feedback<S> for ConcolicFeedback<'_, S>
|
||||||
where
|
where
|
||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
@ -79,7 +82,7 @@ where
|
|||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
{
|
{
|
||||||
if let Some(metadata) = observers
|
if let Some(metadata) = observers
|
||||||
.match_name::<ConcolicObserver>(&self.name)
|
.get(&self.obs_ref)
|
||||||
.map(ConcolicObserver::create_metadata_from_current_map)
|
.map(ConcolicObserver::create_metadata_from_current_map)
|
||||||
{
|
{
|
||||||
testcase.metadata_map_mut().insert(metadata);
|
testcase.metadata_map_mut().insert(metadata);
|
||||||
|
@ -7,7 +7,10 @@ use core::{
|
|||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::{tuples::MatchName, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchName, MatchNameRef, Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -55,12 +58,12 @@ where
|
|||||||
/// This feedback's name
|
/// This feedback's name
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
/// The first observer to compare against
|
/// The first observer to compare against
|
||||||
o1_name: Cow<'static, str>,
|
o1_ref: Reference<O1>,
|
||||||
/// The second observer to compare against
|
/// The second observer to compare against
|
||||||
o2_name: Cow<'static, str>,
|
o2_ref: Reference<O2>,
|
||||||
/// The function used to compare the two observers
|
/// The function used to compare the two observers
|
||||||
compare_fn: F,
|
compare_fn: F,
|
||||||
phantomm: PhantomData<(O1, O2, I, S)>,
|
phantomm: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, I, O1, O2, S> DiffFeedback<F, I, O1, O2, S>
|
impl<F, I, O1, O2, S> DiffFeedback<F, I, O1, O2, S>
|
||||||
@ -71,16 +74,17 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new [`DiffFeedback`] using two observers and a test function.
|
/// 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, compare_fn: F) -> Result<Self, Error> {
|
||||||
let o1_name = o1.name().clone();
|
let o1_ref = o1.reference();
|
||||||
let o2_name = o2.name().clone();
|
let o2_ref = o2.reference();
|
||||||
if o1_name == o2_name {
|
if o1_ref.name() == o2_ref.name() {
|
||||||
Err(Error::illegal_argument(format!(
|
Err(Error::illegal_argument(format!(
|
||||||
"DiffFeedback: observer names must be different (both were {o1_name})"
|
"DiffFeedback: observer names must be different (both were {})",
|
||||||
|
o1_ref.name()
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
o1_name,
|
o1_ref,
|
||||||
o2_name,
|
o2_ref,
|
||||||
name: Cow::from(name),
|
name: Cow::from(name),
|
||||||
compare_fn,
|
compare_fn,
|
||||||
phantomm: PhantomData,
|
phantomm: PhantomData,
|
||||||
@ -101,8 +105,8 @@ where
|
|||||||
fn create_feedback(&self, _ctx: &T) -> DiffFeedback<F, I, O1, O2, S> {
|
fn create_feedback(&self, _ctx: &T) -> DiffFeedback<F, I, O1, O2, S> {
|
||||||
Self {
|
Self {
|
||||||
name: self.name.clone(),
|
name: self.name.clone(),
|
||||||
o1_name: self.o1_name.clone(),
|
o1_ref: self.o1_ref.clone(),
|
||||||
o2_name: self.o2_name.clone(),
|
o2_ref: self.o2_ref.clone(),
|
||||||
compare_fn: self.compare_fn.clone(),
|
compare_fn: self.compare_fn.clone(),
|
||||||
phantomm: self.phantomm,
|
phantomm: self.phantomm,
|
||||||
}
|
}
|
||||||
@ -127,11 +131,11 @@ where
|
|||||||
O2: Named,
|
O2: Named,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
write!(
|
f.debug_struct("DiffFeedback")
|
||||||
f,
|
.field("name", self.name())
|
||||||
"DiffFeedback {{ name: {}, o1: {}, o2: {} }}",
|
.field("o1", &self.o1_ref)
|
||||||
self.name, self.o1_name, self.o2_name
|
.field("o2", &self.o2_ref)
|
||||||
)
|
.finish_non_exhaustive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,11 +164,11 @@ where
|
|||||||
Error::illegal_argument(format!("DiffFeedback: observer {name} not found"))
|
Error::illegal_argument(format!("DiffFeedback: observer {name} not found"))
|
||||||
}
|
}
|
||||||
let o1: &O1 = observers
|
let o1: &O1 = observers
|
||||||
.match_name(&self.o1_name)
|
.get(&self.o1_ref)
|
||||||
.ok_or_else(|| err(&self.o1_name))?;
|
.ok_or_else(|| err(self.o1_ref.name()))?;
|
||||||
let o2: &O2 = observers
|
let o2: &O2 = observers
|
||||||
.match_name(&self.o2_name)
|
.get(&self.o2_ref)
|
||||||
.ok_or_else(|| err(&self.o2_name))?;
|
.ok_or_else(|| err(self.o2_ref.name()))?;
|
||||||
|
|
||||||
Ok((self.compare_fn)(o1, o2) == DiffResult::Diff)
|
Ok((self.compare_fn)(o1, o2) == DiffResult::Diff)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
use core::{fmt::Debug, hash::Hash, marker::PhantomData};
|
use core::{fmt::Debug, hash::Hash};
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use libafl_bolts::{Error, HasRefCnt, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Error, HasRefCnt, Named,
|
||||||
|
};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -70,10 +73,8 @@ pub struct ListFeedback<T>
|
|||||||
where
|
where
|
||||||
T: Hash + Eq,
|
T: Hash + Eq,
|
||||||
{
|
{
|
||||||
name: Cow<'static, str>,
|
obs_ref: Reference<ListObserver<T>>,
|
||||||
observer_name: Cow<'static, str>,
|
|
||||||
novelty: HashSet<T>,
|
novelty: HashSet<T>,
|
||||||
phantom: PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
libafl_bolts::impl_serdeany!(
|
libafl_bolts::impl_serdeany!(
|
||||||
@ -88,7 +89,7 @@ where
|
|||||||
{
|
{
|
||||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
// eprintln!("self.name {:#?}", &self.name);
|
// eprintln!("self.name {:#?}", &self.name);
|
||||||
state.add_named_metadata(&self.name, ListFeedbackMetadata::<T>::default());
|
state.add_named_metadata(self.name(), ListFeedbackMetadata::<T>::default());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
@ -105,15 +106,13 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers
|
let observer = observers.get(&self.obs_ref).unwrap();
|
||||||
.match_name::<ListObserver<T>>(&self.observer_name)
|
|
||||||
.unwrap();
|
|
||||||
// TODO register the list content in a testcase metadata
|
// TODO register the list content in a testcase metadata
|
||||||
self.novelty.clear();
|
self.novelty.clear();
|
||||||
// can't fail
|
// can't fail
|
||||||
let history_set = state
|
let history_set = state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
.get_mut::<ListFeedbackMetadata<T>>(&self.name)
|
.get_mut::<ListFeedbackMetadata<T>>(self.name())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for v in observer.list() {
|
for v in observer.list() {
|
||||||
if !history_set.set.contains(v) {
|
if !history_set.set.contains(v) {
|
||||||
@ -136,7 +135,7 @@ where
|
|||||||
{
|
{
|
||||||
let history_set = state
|
let history_set = state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
.get_mut::<ListFeedbackMetadata<T>>(&self.name)
|
.get_mut::<ListFeedbackMetadata<T>>(self.name())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for v in &self.novelty {
|
for v in &self.novelty {
|
||||||
@ -152,7 +151,7 @@ where
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
self.obs_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,10 +163,8 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(observer: &ListObserver<T>) -> Self {
|
pub fn new(observer: &ListObserver<T>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: observer.name().clone(),
|
obs_ref: observer.reference(),
|
||||||
observer_name: observer.name().clone(),
|
|
||||||
novelty: HashSet::<T>::new(),
|
novelty: HashSet::<T>::new(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,10 @@ use core::{
|
|||||||
ops::{BitAnd, BitOr},
|
ops::{BitAnd, BitOr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::{AsIter, AsSlice, AsSliceMut, HasRefCnt, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
AsIter, AsSlice, AsSliceMut, HasRefCnt, Named,
|
||||||
|
};
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -17,32 +20,31 @@ use crate::{
|
|||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
events::{Event, EventFirer},
|
events::{Event, EventFirer},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{Feedback, HasObserverName},
|
feedbacks::{Feedback, HasObserverReference},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
monitors::{AggregatorOps, UserStats, UserStatsValue},
|
monitors::{AggregatorOps, UserStats, UserStatsValue},
|
||||||
observers::{CanTrack, MapObserver, Observer, ObserversTuple, UsesObserver},
|
observers::{CanTrack, MapObserver, Observer, ObserversTuple},
|
||||||
state::State,
|
state::State,
|
||||||
Error, HasMetadata, HasNamedMetadata,
|
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`].
|
/// 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, S, T> = MapFeedback<C, DifferentIsNovel, O, OrReducer, S, T>;
|
pub type AflMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, OrReducer, T>;
|
||||||
|
|
||||||
/// A [`MapFeedback`] that strives to maximize the map contents.
|
/// A [`MapFeedback`] that strives to maximize the map contents.
|
||||||
pub type MaxMapFeedback<C, O, S, T> = MapFeedback<C, DifferentIsNovel, O, MaxReducer, S, T>;
|
pub type MaxMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, MaxReducer, T>;
|
||||||
/// A [`MapFeedback`] that strives to minimize the map contents.
|
/// A [`MapFeedback`] that strives to minimize the map contents.
|
||||||
pub type MinMapFeedback<C, O, S, T> = MapFeedback<C, DifferentIsNovel, O, MinReducer, S, T>;
|
pub type MinMapFeedback<C, O, T> = MapFeedback<C, DifferentIsNovel, O, MinReducer, T>;
|
||||||
|
|
||||||
/// A [`MapFeedback`] that always returns `true` for `is_interesting`. Useful for tracing all executions.
|
/// A [`MapFeedback`] that always returns `true` for `is_interesting`. Useful for tracing all executions.
|
||||||
pub type AlwaysInterestingMapFeedback<C, O, S, T> = MapFeedback<C, AllIsNovel, O, NopReducer, S, T>;
|
pub type AlwaysInterestingMapFeedback<C, O, T> = MapFeedback<C, AllIsNovel, O, NopReducer, T>;
|
||||||
|
|
||||||
/// A [`MapFeedback`] that strives to maximize the map contents,
|
/// A [`MapFeedback`] that strives to maximize the map contents,
|
||||||
/// but only, if a value is larger than `pow2` of the previous.
|
/// but only, if a value is larger than `pow2` of the previous.
|
||||||
pub type MaxMapPow2Feedback<C, O, S, T> = MapFeedback<C, NextPow2IsNovel, O, MaxReducer, S, T>;
|
pub type MaxMapPow2Feedback<C, O, T> = MapFeedback<C, NextPow2IsNovel, O, MaxReducer, T>;
|
||||||
/// A [`MapFeedback`] that strives to maximize the map contents,
|
/// A [`MapFeedback`] that strives to maximize the map contents,
|
||||||
/// but only, if a value is larger than `pow2` of the previous.
|
/// but only, if a value is larger than `pow2` of the previous.
|
||||||
pub type MaxMapOneOrFilledFeedback<C, O, S, T> =
|
pub type MaxMapOneOrFilledFeedback<C, O, T> = MapFeedback<C, OneOrFilledIsNovel, O, MaxReducer, T>;
|
||||||
MapFeedback<C, OneOrFilledIsNovel, O, MaxReducer, S, T>;
|
|
||||||
|
|
||||||
/// A `Reducer` function is used to aggregate values for the novelty search
|
/// A `Reducer` function is used to aggregate values for the novelty search
|
||||||
pub trait Reducer<T>: 'static
|
pub trait Reducer<T>: 'static
|
||||||
@ -380,35 +382,27 @@ where
|
|||||||
|
|
||||||
/// The most common AFL-like feedback type
|
/// The most common AFL-like feedback type
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapFeedback<C, N, O, R, S, T> {
|
pub struct MapFeedback<C, N, O, R, T> {
|
||||||
/// New indexes observed in the last observation
|
/// New indexes observed in the last observation
|
||||||
novelties: Option<Vec<usize>>,
|
novelties: Option<Vec<usize>>,
|
||||||
/// Name identifier of this instance
|
/// Name identifier of this instance
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
/// Name identifier of the observer
|
/// Name identifier of the observer
|
||||||
observer_name: Cow<'static, str>,
|
map_ref: Reference<C>,
|
||||||
/// Name of the feedback as shown in the `UserStats`
|
/// Name of the feedback as shown in the `UserStats`
|
||||||
stats_name: Cow<'static, str>,
|
stats_name: Cow<'static, str>,
|
||||||
/// Phantom Data of Reducer
|
/// Phantom Data of Reducer
|
||||||
phantom: PhantomData<(C, N, O, R, S, T)>,
|
phantom: PhantomData<(C, N, O, R, T)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, N, O, R, S, T> UsesObserver<S> for MapFeedback<C, N, O, R, S, T>
|
impl<C, N, O, R, S, T> Feedback<S> for MapFeedback<C, N, O, R, T>
|
||||||
where
|
|
||||||
S: UsesInput,
|
|
||||||
C: AsRef<O> + Observer<S>,
|
|
||||||
{
|
|
||||||
type Observer = C;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, N, O, R, S, T> Feedback<S> for MapFeedback<C, N, O, R, S, T>
|
|
||||||
where
|
where
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
O: MapObserver<Entry = T> + for<'it> AsIter<'it, Item = T>,
|
O: MapObserver<Entry = T> + for<'it> AsIter<'it, Item = T>,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
S: State + HasNamedMetadata,
|
S: State + HasNamedMetadata,
|
||||||
T: Default + Copy + Serialize + for<'de> Deserialize<'de> + PartialEq + Debug + 'static,
|
T: Default + Copy + Serialize + for<'de> Deserialize<'de> + PartialEq + Debug + 'static,
|
||||||
C: CanTrack + AsRef<O>,
|
C: CanTrack + AsRef<O> + Observer<S>,
|
||||||
{
|
{
|
||||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
// Initialize `MapFeedbackMetadata` with an empty vector and add it to the state.
|
// Initialize `MapFeedbackMetadata` with an empty vector and add it to the state.
|
||||||
@ -464,10 +458,7 @@ where
|
|||||||
let meta = MapNoveltiesMetadata::new(novelties);
|
let meta = MapNoveltiesMetadata::new(novelties);
|
||||||
testcase.add_metadata(meta);
|
testcase.add_metadata(meta);
|
||||||
}
|
}
|
||||||
let observer = observers
|
let observer = observers.get(&self.map_ref).unwrap().as_ref();
|
||||||
.match_name::<C>(&self.observer_name)
|
|
||||||
.unwrap()
|
|
||||||
.as_ref();
|
|
||||||
let initial = observer.initial();
|
let initial = observer.initial();
|
||||||
let map_state = state
|
let map_state = state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
@ -546,12 +537,12 @@ where
|
|||||||
|
|
||||||
/// Specialize for the common coverage map size, maximization of u8s
|
/// Specialize for the common coverage map size, maximization of u8s
|
||||||
#[rustversion::nightly]
|
#[rustversion::nightly]
|
||||||
impl<C, O, S> Feedback<S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer, S, u8>
|
impl<C, O, S> Feedback<S> for MapFeedback<C, DifferentIsNovel, O, MaxReducer, u8>
|
||||||
where
|
where
|
||||||
O: MapObserver<Entry = u8> + AsSlice<Entry = u8>,
|
O: MapObserver<Entry = u8> + AsSlice<Entry = u8>,
|
||||||
for<'it> O: AsIter<'it, Item = u8>,
|
for<'it> O: AsIter<'it, Item = u8>,
|
||||||
S: State + HasNamedMetadata,
|
S: State + HasNamedMetadata,
|
||||||
C: CanTrack + AsRef<O>,
|
C: CanTrack + AsRef<O> + Observer<S>,
|
||||||
{
|
{
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
#[allow(clippy::needless_range_loop)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
@ -572,10 +563,7 @@ where
|
|||||||
|
|
||||||
let mut interesting = false;
|
let mut interesting = false;
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers
|
let observer = observers.get(&self.map_ref).unwrap().as_ref();
|
||||||
.match_name::<C>(&self.observer_name)
|
|
||||||
.unwrap()
|
|
||||||
.as_ref();
|
|
||||||
|
|
||||||
let map_state = state
|
let map_state = state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
@ -666,21 +654,23 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, N, O, R, S, T> Named for MapFeedback<C, N, O, R, S, T> {
|
impl<C, N, O, R, T> Named for MapFeedback<C, N, O, R, T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, N, O, R, S, T> HasObserverName for MapFeedback<C, N, O, R, S, T>
|
impl<C, N, O, R, T> HasObserverReference for MapFeedback<C, N, O, R, T>
|
||||||
where
|
where
|
||||||
O: Named,
|
O: Named,
|
||||||
C: AsRef<O>,
|
C: AsRef<O>,
|
||||||
{
|
{
|
||||||
|
type Observer = C;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observer_name(&self) -> &Cow<'static, str> {
|
fn observer_ref(&self) -> &Reference<C> {
|
||||||
&self.observer_name
|
&self.map_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -693,24 +683,22 @@ fn create_stats_name(name: &Cow<'static, str>) -> Cow<'static, str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, N, O, R, S, T> MapFeedback<C, N, O, R, S, T>
|
impl<C, N, O, R, T> MapFeedback<C, N, O, R, T>
|
||||||
where
|
where
|
||||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
O: MapObserver<Entry = T>,
|
O: MapObserver<Entry = T>,
|
||||||
for<'it> O: AsIter<'it, Item = T>,
|
for<'it> O: AsIter<'it, Item = T>,
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
S: UsesInput + HasNamedMetadata,
|
C: CanTrack + AsRef<O> + Named,
|
||||||
C: CanTrack + AsRef<O>,
|
|
||||||
{
|
{
|
||||||
/// Create new `MapFeedback`
|
/// Create new `MapFeedback`
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(map_observer: &C) -> Self {
|
pub fn new(map_observer: &C) -> Self {
|
||||||
let map_observer = map_observer.as_ref();
|
|
||||||
Self {
|
Self {
|
||||||
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
|
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
|
||||||
name: map_observer.name().clone(),
|
name: map_observer.name().clone(),
|
||||||
observer_name: map_observer.name().clone(),
|
map_ref: map_observer.reference(),
|
||||||
stats_name: create_stats_name(map_observer.name()),
|
stats_name: create_stats_name(map_observer.name()),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
@ -722,10 +710,9 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_name(name: &'static str, map_observer: &C) -> Self {
|
pub fn with_name(name: &'static str, map_observer: &C) -> Self {
|
||||||
let name = Cow::from(name);
|
let name = Cow::from(name);
|
||||||
let map_observer = map_observer.as_ref();
|
|
||||||
Self {
|
Self {
|
||||||
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
|
novelties: if C::NOVELTIES { Some(vec![]) } else { None },
|
||||||
observer_name: map_observer.name().clone(),
|
map_ref: map_observer.reference(),
|
||||||
stats_name: create_stats_name(&name),
|
stats_name: create_stats_name(&name),
|
||||||
name,
|
name,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -735,7 +722,7 @@ where
|
|||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
#[allow(clippy::needless_range_loop)]
|
#[allow(clippy::needless_range_loop)]
|
||||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||||
fn is_interesting_default<EM, OT>(
|
fn is_interesting_default<EM, S, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
@ -746,13 +733,11 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
|
S: UsesInput + HasNamedMetadata,
|
||||||
{
|
{
|
||||||
let mut interesting = false;
|
let mut interesting = false;
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers
|
let observer = observers.get(&self.map_ref).unwrap().as_ref();
|
||||||
.match_name::<C>(&self.observer_name)
|
|
||||||
.unwrap()
|
|
||||||
.as_ref();
|
|
||||||
|
|
||||||
let map_state = state
|
let map_state = state
|
||||||
.named_metadata_map_mut()
|
.named_metadata_map_mut()
|
||||||
|
@ -4,43 +4,27 @@
|
|||||||
|
|
||||||
// TODO: make S of Feedback<S> an associated type when specialisation + AT is stable
|
// TODO: make S of Feedback<S> an associated type when specialisation + AT is stable
|
||||||
|
|
||||||
pub mod map;
|
|
||||||
|
|
||||||
use alloc::borrow::Cow;
|
use alloc::borrow::Cow;
|
||||||
|
|
||||||
pub use map::*;
|
|
||||||
|
|
||||||
pub mod differential;
|
|
||||||
pub use differential::DiffFeedback;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub mod concolic;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use concolic::ConcolicFeedback;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub mod new_hash_feedback;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use new_hash_feedback::NewHashFeedback;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub use new_hash_feedback::NewHashFeedbackMetadata;
|
|
||||||
|
|
||||||
#[cfg(feature = "nautilus")]
|
|
||||||
pub mod nautilus;
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub mod stdio;
|
|
||||||
pub mod transferred;
|
|
||||||
|
|
||||||
/// The module for list feedback
|
|
||||||
pub mod list;
|
|
||||||
use core::{
|
use core::{
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_bolts::Named;
|
#[cfg(feature = "std")]
|
||||||
|
pub use concolic::ConcolicFeedback;
|
||||||
|
pub use differential::DiffFeedback;
|
||||||
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
pub use list::*;
|
pub use list::*;
|
||||||
|
pub use map::*;
|
||||||
#[cfg(feature = "nautilus")]
|
#[cfg(feature = "nautilus")]
|
||||||
pub use nautilus::*;
|
pub use nautilus::*;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use new_hash_feedback::NewHashFeedback;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub use new_hash_feedback::NewHashFeedbackMetadata;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -52,6 +36,22 @@ use crate::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub mod map;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod concolic;
|
||||||
|
pub mod differential;
|
||||||
|
#[cfg(feature = "nautilus")]
|
||||||
|
pub mod nautilus;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod new_hash_feedback;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod stdio;
|
||||||
|
pub mod transferred;
|
||||||
|
|
||||||
|
/// The module for list feedback
|
||||||
|
pub mod list;
|
||||||
|
|
||||||
/// Feedbacks evaluate the observers.
|
/// Feedbacks evaluate the observers.
|
||||||
/// Basically, they reduce the information provided by an observer to a value,
|
/// Basically, they reduce the information provided by an observer to a value,
|
||||||
/// indicating the "interestingness" of the last run.
|
/// indicating the "interestingness" of the last run.
|
||||||
@ -138,9 +138,12 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
|
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
|
||||||
pub trait HasObserverName {
|
pub trait HasObserverReference {
|
||||||
|
/// The observer for which we hold a reference
|
||||||
|
type Observer: ?Sized;
|
||||||
|
|
||||||
/// The name associated with the observer
|
/// The name associated with the observer
|
||||||
fn observer_name(&self) -> &Cow<'static, str>;
|
fn observer_ref(&self) -> &Reference<Self::Observer>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A combined feedback consisting of multiple [`Feedback`]s
|
/// A combined feedback consisting of multiple [`Feedback`]s
|
||||||
@ -931,7 +934,7 @@ pub type TimeoutFeedbackFactory = DefaultFeedbackFactory<TimeoutFeedback>;
|
|||||||
/// It decides, if the given [`TimeObserver`] value of a run is interesting.
|
/// It decides, if the given [`TimeObserver`] value of a run is interesting.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct TimeFeedback {
|
pub struct TimeFeedback {
|
||||||
name: Cow<'static, str>,
|
obs_ref: Reference<TimeObserver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Feedback<S> for TimeFeedback
|
impl<S> Feedback<S> for TimeFeedback
|
||||||
@ -968,7 +971,7 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
{
|
{
|
||||||
let observer = observers.match_name::<TimeObserver>(self.name()).unwrap();
|
let observer = observers.get(&self.obs_ref).unwrap();
|
||||||
*testcase.exec_time_mut() = *observer.last_runtime();
|
*testcase.exec_time_mut() = *observer.last_runtime();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -983,24 +986,16 @@ where
|
|||||||
impl Named for TimeFeedback {
|
impl Named for TimeFeedback {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
self.obs_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeFeedback {
|
impl TimeFeedback {
|
||||||
/// Creates a new [`TimeFeedback`], deciding if the value of a [`TimeObserver`] with the given `name` of a run is interesting.
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(name: &'static str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: Cow::from(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [`TimeFeedback`], deciding if the given [`TimeObserver`] value of a run is interesting.
|
/// Creates a new [`TimeFeedback`], deciding if the given [`TimeObserver`] value of a run is interesting.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_observer(observer: &TimeObserver) -> Self {
|
pub fn new(observer: &TimeObserver) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: observer.name().clone(),
|
obs_ref: observer.reference(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,16 @@ use alloc::{borrow::Cow, string::ToString};
|
|||||||
use std::{fmt::Debug, marker::PhantomData};
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use libafl_bolts::Named;
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventFirer,
|
events::EventFirer,
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{Feedback, HasObserverName},
|
feedbacks::{Feedback, HasObserverReference},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
observers::{ObserverWithHashField, ObserversTuple},
|
observers::{ObserverWithHashField, ObserversTuple},
|
||||||
state::State,
|
state::State,
|
||||||
@ -79,10 +82,10 @@ impl HashSetState<u64> for NewHashFeedbackMetadata {
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct NewHashFeedback<O, S> {
|
pub struct NewHashFeedback<O, S> {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
observer_name: Cow<'static, str>,
|
o_ref: Reference<O>,
|
||||||
/// Initial capacity of hash set
|
/// Initial capacity of hash set
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
o_type: PhantomData<(O, S)>,
|
phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O, S> Feedback<S> for NewHashFeedback<O, S>
|
impl<O, S> Feedback<S> for NewHashFeedback<O, S>
|
||||||
@ -112,7 +115,7 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<O>(&self.observer_name)
|
.get(&self.o_ref)
|
||||||
.expect("A NewHashFeedback needs a BacktraceObserver");
|
.expect("A NewHashFeedback needs a BacktraceObserver");
|
||||||
|
|
||||||
let backtrace_state = state
|
let backtrace_state = state
|
||||||
@ -142,10 +145,12 @@ impl<O, S> Named for NewHashFeedback<O, S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O, S> HasObserverName for NewHashFeedback<O, S> {
|
impl<O, S> HasObserverReference for NewHashFeedback<O, S> {
|
||||||
|
type Observer = O;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observer_name(&self) -> &Cow<'static, str> {
|
fn observer_ref(&self) -> &Reference<O> {
|
||||||
&self.observer_name
|
&self.o_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,9 +176,9 @@ where
|
|||||||
pub fn with_capacity(observer: &O, capacity: usize) -> Self {
|
pub fn with_capacity(observer: &O, capacity: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: Cow::from(NEWHASHFEEDBACK_PREFIX.to_string() + observer.name()),
|
name: Cow::from(NEWHASHFEEDBACK_PREFIX.to_string() + observer.name()),
|
||||||
observer_name: observer.name().clone(),
|
o_ref: observer.reference(),
|
||||||
capacity,
|
capacity,
|
||||||
o_type: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
use alloc::{borrow::Cow, string::String};
|
use alloc::{borrow::Cow, string::String};
|
||||||
|
|
||||||
use libafl_bolts::{impl_serdeany, Named};
|
use libafl_bolts::{
|
||||||
|
impl_serdeany,
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -28,7 +32,7 @@ impl_serdeany!(StdOutMetadata);
|
|||||||
/// is never interesting (use with an OR).
|
/// is never interesting (use with an OR).
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct StdOutToMetadataFeedback {
|
pub struct StdOutToMetadataFeedback {
|
||||||
name: Cow<'static, str>,
|
o_ref: Reference<StdOutObserver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Feedback<S> for StdOutToMetadataFeedback
|
impl<S> Feedback<S> for StdOutToMetadataFeedback
|
||||||
@ -66,7 +70,7 @@ where
|
|||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<StdOutObserver>(self.name())
|
.get(&self.o_ref)
|
||||||
.ok_or(Error::illegal_state("StdOutObserver is missing"))?;
|
.ok_or(Error::illegal_state("StdOutObserver is missing"))?;
|
||||||
let buffer = observer
|
let buffer = observer
|
||||||
.stdout
|
.stdout
|
||||||
@ -91,25 +95,16 @@ where
|
|||||||
impl Named for StdOutToMetadataFeedback {
|
impl Named for StdOutToMetadataFeedback {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
self.o_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdOutToMetadataFeedback {
|
impl StdOutToMetadataFeedback {
|
||||||
/// Creates a new [`StdOutToMetadataFeedback`]. The provided `name` is
|
|
||||||
/// used to look up the observer.
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(name: &'static str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: Cow::from(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [`StdOutToMetadataFeedback`].
|
/// Creates a new [`StdOutToMetadataFeedback`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_observer(observer: &StdOutObserver) -> Self {
|
pub fn new(observer: &StdOutObserver) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: observer.name().clone(),
|
o_ref: observer.reference(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,7 +122,7 @@ impl_serdeany!(StdErrMetadata);
|
|||||||
/// is never interesting (use with an OR).
|
/// is never interesting (use with an OR).
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct StdErrToMetadataFeedback {
|
pub struct StdErrToMetadataFeedback {
|
||||||
name: Cow<'static, str>,
|
o_ref: Reference<StdErrObserver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Feedback<S> for StdErrToMetadataFeedback
|
impl<S> Feedback<S> for StdErrToMetadataFeedback
|
||||||
@ -165,7 +160,7 @@ where
|
|||||||
EM: EventFirer<State = S>,
|
EM: EventFirer<State = S>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<StdErrObserver>(self.name())
|
.get(&self.o_ref)
|
||||||
.ok_or(Error::illegal_state("StdErrObserver is missing"))?;
|
.ok_or(Error::illegal_state("StdErrObserver is missing"))?;
|
||||||
let buffer = observer
|
let buffer = observer
|
||||||
.stderr
|
.stderr
|
||||||
@ -190,25 +185,16 @@ where
|
|||||||
impl Named for StdErrToMetadataFeedback {
|
impl Named for StdErrToMetadataFeedback {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
self.o_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdErrToMetadataFeedback {
|
impl StdErrToMetadataFeedback {
|
||||||
/// Creates a new [`StdErrToMetadataFeedback`]. The provided `name` is
|
|
||||||
/// used to look up the observer.
|
|
||||||
#[must_use]
|
|
||||||
pub fn new(name: &'static str) -> Self {
|
|
||||||
Self {
|
|
||||||
name: Cow::from(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new [`StdErrToMetadataFeedback`].
|
/// Creates a new [`StdErrToMetadataFeedback`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_observer(observer: &StdErrObserver) -> Self {
|
pub fn new(observer: &StdErrObserver) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: observer.name().clone(),
|
o_ref: observer.reference(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,9 +541,9 @@ where
|
|||||||
let exit_kind = self.execute_input(state, executor, manager, &input)?;
|
let exit_kind = self.execute_input(state, executor, manager, &input)?;
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
|
|
||||||
self.scheduler.on_evaluation(state, &input, observers)?;
|
self.scheduler.on_evaluation(state, &input, &*observers)?;
|
||||||
|
|
||||||
self.execute_and_process(state, manager, input, observers, &exit_kind, send_events)
|
self.execute_and_process(state, manager, input, &*observers, &exit_kind, send_events)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,18 +595,22 @@ where
|
|||||||
|
|
||||||
// Maybe a solution
|
// Maybe a solution
|
||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
let is_solution = self
|
let is_solution =
|
||||||
.objective_mut()
|
self.objective_mut()
|
||||||
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
.is_interesting(state, manager, &input, &*observers, &exit_kind)?;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
let is_solution = self
|
let is_solution = self.objective_mut().is_interesting_introspection(
|
||||||
.objective_mut()
|
state,
|
||||||
.is_interesting_introspection(state, manager, &input, observers, &exit_kind)?;
|
manager,
|
||||||
|
&input,
|
||||||
|
&*observers,
|
||||||
|
&exit_kind,
|
||||||
|
)?;
|
||||||
|
|
||||||
if is_solution {
|
if is_solution {
|
||||||
self.objective_mut()
|
self.objective_mut()
|
||||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
||||||
let idx = state.solutions_mut().add(testcase)?;
|
let idx = state.solutions_mut().add(testcase)?;
|
||||||
|
|
||||||
let executions = *state.executions();
|
let executions = *state.executions();
|
||||||
@ -627,25 +631,29 @@ where
|
|||||||
// several is_interesting implementations collect some data about the run, later used in
|
// several is_interesting implementations collect some data about the run, later used in
|
||||||
// append_metadata; we *must* invoke is_interesting here to collect it
|
// append_metadata; we *must* invoke is_interesting here to collect it
|
||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
let _corpus_worthy = self
|
let _corpus_worthy =
|
||||||
.feedback_mut()
|
self.feedback_mut()
|
||||||
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
.is_interesting(state, manager, &input, &*observers, &exit_kind)?;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
let _corpus_worthy = self
|
let _corpus_worthy = self.feedback_mut().is_interesting_introspection(
|
||||||
.feedback_mut()
|
state,
|
||||||
.is_interesting_introspection(state, manager, &input, observers, &exit_kind)?;
|
manager,
|
||||||
|
&input,
|
||||||
|
&*observers,
|
||||||
|
&exit_kind,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Add the input to the main corpus
|
// Add the input to the main corpus
|
||||||
self.feedback_mut()
|
self.feedback_mut()
|
||||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
||||||
let idx = state.corpus_mut().add(testcase)?;
|
let idx = state.corpus_mut().add(testcase)?;
|
||||||
self.scheduler_mut().on_add(state, idx)?;
|
self.scheduler_mut().on_add(state, idx)?;
|
||||||
|
|
||||||
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
|
let observers_buf = if manager.configuration() == EventConfig::AlwaysUnique {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
manager.serialize_observers::<OT>(observers)?
|
manager.serialize_observers::<OT>(&*observers)?
|
||||||
};
|
};
|
||||||
manager.fire(
|
manager.fire(
|
||||||
state,
|
state,
|
||||||
|
@ -8,12 +8,9 @@ use crate::{inputs::UsesInput, observers::Observer};
|
|||||||
|
|
||||||
/// A simple observer with a list of things.
|
/// A simple observer with a list of things.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
#[serde(bound = "T: serde::de::DeserializeOwned + serde::Serialize")]
|
||||||
#[allow(clippy::unsafe_derive_deserialize)]
|
#[allow(clippy::unsafe_derive_deserialize)]
|
||||||
pub struct ListObserver<T>
|
pub struct ListObserver<T> {
|
||||||
where
|
|
||||||
T: Debug + Serialize,
|
|
||||||
{
|
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
/// The list
|
/// The list
|
||||||
list: OwnedMutPtr<Vec<T>>,
|
list: OwnedMutPtr<Vec<T>>,
|
||||||
|
@ -38,15 +38,6 @@ pub use value::*;
|
|||||||
|
|
||||||
use crate::{executors::ExitKind, inputs::UsesInput, state::UsesState, Error};
|
use crate::{executors::ExitKind, inputs::UsesInput, state::UsesState, Error};
|
||||||
|
|
||||||
/// Something that uses observer like mapfeedbacks
|
|
||||||
pub trait UsesObserver<S>
|
|
||||||
where
|
|
||||||
S: UsesInput,
|
|
||||||
{
|
|
||||||
/// The observer type used
|
|
||||||
type Observer: Observer<S>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Observers observe different information about the target.
|
/// Observers observe different information about the target.
|
||||||
/// They can then be used by various sorts of feedback.
|
/// They can then be used by various sorts of feedback.
|
||||||
pub trait Observer<S>: Named
|
pub trait Observer<S>: Named
|
||||||
|
@ -27,7 +27,10 @@ pub mod weighted;
|
|||||||
pub use weighted::{StdWeightedScheduler, WeightedScheduler};
|
pub use weighted::{StdWeightedScheduler, WeightedScheduler};
|
||||||
|
|
||||||
pub mod tuneable;
|
pub mod tuneable;
|
||||||
use libafl_bolts::rands::Rand;
|
use libafl_bolts::{
|
||||||
|
rands::Rand,
|
||||||
|
tuples::{MatchNameRef, Reference},
|
||||||
|
};
|
||||||
pub use tuneable::*;
|
pub use tuneable::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -79,7 +82,7 @@ where
|
|||||||
fn set_last_hash(&mut self, value: usize);
|
fn set_last_hash(&mut self, value: usize);
|
||||||
|
|
||||||
/// Get the observer map observer name
|
/// Get the observer map observer name
|
||||||
fn map_observer_name(&self) -> &str;
|
fn map_observer_ref(&self) -> &Reference<C>;
|
||||||
|
|
||||||
/// Called when a [`Testcase`] is added to the corpus
|
/// Called when a [`Testcase`] is added to the corpus
|
||||||
fn on_add_metadata(&self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
fn on_add_metadata(&self, state: &mut Self::State, idx: CorpusId) -> Result<(), Error> {
|
||||||
@ -118,7 +121,7 @@ where
|
|||||||
OT: ObserversTuple<Self::State>,
|
OT: ObserversTuple<Self::State>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<C>(self.map_observer_name())
|
.get(self.map_observer_ref())
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
||||||
.as_ref();
|
.as_ref();
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
//! The queue corpus scheduler for power schedules.
|
//! The queue corpus scheduler for power schedules.
|
||||||
|
|
||||||
use alloc::{
|
use alloc::vec::Vec;
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
use libafl_bolts::Named;
|
use libafl_bolts::{
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -173,9 +173,9 @@ pub enum PowerSchedule {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PowerQueueScheduler<C, O, S> {
|
pub struct PowerQueueScheduler<C, O, S> {
|
||||||
strat: PowerSchedule,
|
strat: PowerSchedule,
|
||||||
map_observer_name: String,
|
map_observer_ref: Reference<C>,
|
||||||
last_hash: usize,
|
last_hash: usize,
|
||||||
phantom: PhantomData<(C, O, S)>,
|
phantom: PhantomData<(O, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, O, S> UsesState for PowerQueueScheduler<C, O, S>
|
impl<C, O, S> UsesState for PowerQueueScheduler<C, O, S>
|
||||||
@ -226,8 +226,8 @@ where
|
|||||||
self.last_hash = hash;
|
self.last_hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_observer_name(&self) -> &str {
|
fn map_observer_ref(&self) -> &Reference<C> {
|
||||||
&self.map_observer_name
|
&self.map_observer_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,9 +256,9 @@ where
|
|||||||
|
|
||||||
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
fn next(&mut self, state: &mut Self::State) -> Result<CorpusId, Error> {
|
||||||
if state.corpus().count() == 0 {
|
if state.corpus().count() == 0 {
|
||||||
Err(Error::empty(String::from(
|
Err(Error::empty(
|
||||||
"No entries in corpus. This often implies the target is not properly instrumented.",
|
"No entries in corpus. This often implies the target is not properly instrumented.",
|
||||||
)))
|
))
|
||||||
} else {
|
} else {
|
||||||
let id = match state.corpus().current() {
|
let id = match state.corpus().current() {
|
||||||
Some(cur) => {
|
Some(cur) => {
|
||||||
@ -305,7 +305,7 @@ where
|
|||||||
}
|
}
|
||||||
PowerQueueScheduler {
|
PowerQueueScheduler {
|
||||||
strat,
|
strat,
|
||||||
map_observer_name: map_observer.name().to_string(),
|
map_observer_ref: map_observer.reference(),
|
||||||
last_hash: 0,
|
last_hash: 0,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
//! The queue corpus scheduler with weighted queue item selection [from AFL++](https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32).
|
//! The queue corpus scheduler with weighted queue item selection [from AFL++](https://github.com/AFLplusplus/AFLplusplus/blob/1d4f1e48797c064ee71441ba555b29fc3f467983/src/afl-fuzz-queue.c#L32).
|
||||||
//! This queue corpus scheduler needs calibration stage.
|
//! This queue corpus scheduler needs calibration stage.
|
||||||
|
|
||||||
use alloc::string::{String, ToString};
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use libafl_bolts::{rands::Rand, Named};
|
use libafl_bolts::{
|
||||||
|
rands::Rand,
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -95,9 +98,9 @@ libafl_bolts::impl_serdeany!(WeightedScheduleMetadata);
|
|||||||
pub struct WeightedScheduler<C, F, O, S> {
|
pub struct WeightedScheduler<C, F, O, S> {
|
||||||
table_invalidated: bool,
|
table_invalidated: bool,
|
||||||
strat: Option<PowerSchedule>,
|
strat: Option<PowerSchedule>,
|
||||||
map_observer_name: String,
|
map_observer_ref: Reference<C>,
|
||||||
last_hash: usize,
|
last_hash: usize,
|
||||||
phantom: PhantomData<(C, F, O, S)>,
|
phantom: PhantomData<(F, O, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, F, O, S> WeightedScheduler<C, F, O, S>
|
impl<C, F, O, S> WeightedScheduler<C, F, O, S>
|
||||||
@ -121,7 +124,7 @@ where
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
strat,
|
strat,
|
||||||
map_observer_name: map_observer.name().to_string(),
|
map_observer_ref: map_observer.reference(),
|
||||||
last_hash: 0,
|
last_hash: 0,
|
||||||
table_invalidated: true,
|
table_invalidated: true,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -271,8 +274,8 @@ where
|
|||||||
self.last_hash = hash;
|
self.last_hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_observer_name(&self) -> &str {
|
fn map_observer_ref(&self) -> &Reference<C> {
|
||||||
&self.map_observer_name
|
&self.map_observer_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,9 +313,9 @@ where
|
|||||||
}
|
}
|
||||||
let corpus_counts = state.corpus().count();
|
let corpus_counts = state.corpus().count();
|
||||||
if corpus_counts == 0 {
|
if corpus_counts == 0 {
|
||||||
Err(Error::empty(String::from(
|
Err(Error::empty(
|
||||||
"No entries in corpus. This often implies the target is not properly instrumented.",
|
"No entries in corpus. This often implies the target is not properly instrumented.",
|
||||||
)))
|
))
|
||||||
} else {
|
} else {
|
||||||
let s = random_corpus_id!(state.corpus(), state.rand_mut());
|
let s = random_corpus_id!(state.corpus(), state.rand_mut());
|
||||||
|
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
|
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{borrow::Cow, vec::Vec};
|
||||||
borrow::Cow,
|
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use libafl_bolts::{current_time, impl_serdeany, AsIter, Named};
|
use libafl_bolts::{current_time, impl_serdeany, tuples::Reference, AsIter, Named};
|
||||||
use num_traits::Bounded;
|
use num_traits::Bounded;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -16,10 +12,11 @@ use crate::{
|
|||||||
corpus::{Corpus, SchedulerTestcaseMetadata},
|
corpus::{Corpus, SchedulerTestcaseMetadata},
|
||||||
events::{Event, EventFirer, LogSeverity},
|
events::{Event, EventFirer, LogSeverity},
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
feedbacks::{map::MapFeedbackMetadata, HasObserverName},
|
feedbacks::{map::MapFeedbackMetadata, HasObserverReference},
|
||||||
fuzzer::Evaluator,
|
fuzzer::Evaluator,
|
||||||
|
inputs::UsesInput,
|
||||||
monitors::{AggregatorOps, UserStats, UserStatsValue},
|
monitors::{AggregatorOps, UserStats, UserStatsValue},
|
||||||
observers::{MapObserver, ObserversTuple, UsesObserver},
|
observers::{MapObserver, ObserversTuple},
|
||||||
schedulers::powersched::SchedulerMetadata,
|
schedulers::powersched::SchedulerMetadata,
|
||||||
stages::{ExecutionCountRestartHelper, Stage},
|
stages::{ExecutionCountRestartHelper, Stage},
|
||||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, State, UsesState},
|
state::{HasCorpus, HasCurrentTestcase, HasExecutions, State, UsesState},
|
||||||
@ -66,13 +63,13 @@ impl UnstableEntriesMetadata {
|
|||||||
/// The calibration stage will measure the average exec time and the target's stability for this input.
|
/// The calibration stage will measure the average exec time and the target's stability for this input.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CalibrationStage<C, O, OT, S> {
|
pub struct CalibrationStage<C, O, OT, S> {
|
||||||
map_observer_name: String,
|
map_observer_ref: Reference<C>,
|
||||||
map_name: String,
|
map_name: Cow<'static, str>,
|
||||||
stage_max: usize,
|
stage_max: usize,
|
||||||
/// If we should track stability
|
/// If we should track stability
|
||||||
track_stability: bool,
|
track_stability: bool,
|
||||||
restart_helper: ExecutionCountRestartHelper,
|
restart_helper: ExecutionCountRestartHelper,
|
||||||
phantom: PhantomData<(C, O, OT, S)>,
|
phantom: PhantomData<(O, OT, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CAL_STAGE_START: usize = 4; // AFL++'s CAL_CYCLES_FAST + 1
|
const CAL_STAGE_START: usize = 4; // AFL++'s CAL_CYCLES_FAST + 1
|
||||||
@ -147,10 +144,7 @@ where
|
|||||||
.observers_mut()
|
.observers_mut()
|
||||||
.post_exec_all(state, &input, &exit_kind)?;
|
.post_exec_all(state, &input, &exit_kind)?;
|
||||||
|
|
||||||
let map_first = &executor
|
let map_first = &executor.observers()[&self.map_observer_ref]
|
||||||
.observers()
|
|
||||||
.match_name::<C>(&self.map_observer_name)
|
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
@ -191,10 +185,7 @@ where
|
|||||||
.post_exec_all(state, &input, &exit_kind)?;
|
.post_exec_all(state, &input, &exit_kind)?;
|
||||||
|
|
||||||
if self.track_stability {
|
if self.track_stability {
|
||||||
let map = &executor
|
let map = &executor.observers()[&self.map_observer_ref]
|
||||||
.observers()
|
|
||||||
.match_name::<C>(&self.map_observer_name)
|
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
@ -248,11 +239,8 @@ where
|
|||||||
|
|
||||||
// If weighted scheduler or powerscheduler is used, update it
|
// If weighted scheduler or powerscheduler is used, update it
|
||||||
if state.has_metadata::<SchedulerMetadata>() {
|
if state.has_metadata::<SchedulerMetadata>() {
|
||||||
let map = executor
|
let observers = executor.observers();
|
||||||
.observers()
|
let map = observers[&self.map_observer_ref].as_ref();
|
||||||
.match_name::<C>(&self.map_observer_name)
|
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
|
||||||
.as_ref();
|
|
||||||
|
|
||||||
let mut bitmap_size = map.count_bytes();
|
let mut bitmap_size = map.count_bytes();
|
||||||
assert!(bitmap_size != 0);
|
assert!(bitmap_size != 0);
|
||||||
@ -343,21 +331,20 @@ where
|
|||||||
impl<C, O, OT, S> CalibrationStage<C, O, OT, S>
|
impl<C, O, OT, S> CalibrationStage<C, O, OT, S>
|
||||||
where
|
where
|
||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
|
for<'it> O: AsIter<'it, Item = O::Entry>,
|
||||||
C: AsRef<O>,
|
C: AsRef<O>,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
S: HasCorpus + HasMetadata + HasNamedMetadata,
|
S: UsesInput + HasNamedMetadata,
|
||||||
{
|
{
|
||||||
/// Create a new [`CalibrationStage`].
|
/// Create a new [`CalibrationStage`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new<F>(map_feedback: &F) -> Self
|
pub fn new<F>(map_feedback: &F) -> Self
|
||||||
where
|
where
|
||||||
F: HasObserverName + Named + UsesObserver<S, Observer = C>,
|
F: HasObserverReference<Observer = C> + Named,
|
||||||
for<'it> O: AsIter<'it, Item = O::Entry>,
|
|
||||||
C: AsRef<O>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
map_observer_name: map_feedback.observer_name().to_string(),
|
map_observer_ref: map_feedback.observer_ref().clone(),
|
||||||
map_name: map_feedback.name().to_string(),
|
map_name: map_feedback.name().clone(),
|
||||||
stage_max: CAL_STAGE_START,
|
stage_max: CAL_STAGE_START,
|
||||||
track_stability: true,
|
track_stability: true,
|
||||||
restart_helper: ExecutionCountRestartHelper::default(),
|
restart_helper: ExecutionCountRestartHelper::default(),
|
||||||
@ -369,13 +356,11 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn ignore_stability<F>(map_feedback: &F) -> Self
|
pub fn ignore_stability<F>(map_feedback: &F) -> Self
|
||||||
where
|
where
|
||||||
F: HasObserverName + Named + UsesObserver<S, Observer = C>,
|
F: HasObserverReference<Observer = C> + Named,
|
||||||
for<'it> O: AsIter<'it, Item = O::Entry>,
|
|
||||||
C: AsRef<O>,
|
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
map_observer_name: map_feedback.observer_name().to_string(),
|
map_observer_ref: map_feedback.observer_ref().clone(),
|
||||||
map_name: map_feedback.name().to_string(),
|
map_name: map_feedback.name().clone(),
|
||||||
stage_max: CAL_STAGE_START,
|
stage_max: CAL_STAGE_START,
|
||||||
track_stability: false,
|
track_stability: false,
|
||||||
restart_helper: ExecutionCountRestartHelper::default(),
|
restart_helper: ExecutionCountRestartHelper::default(),
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
//! The colorization stage from `colorization()` in afl++
|
//! The colorization stage from `colorization()` in afl++
|
||||||
use alloc::{borrow::Cow, collections::binary_heap::BinaryHeap, string::ToString, vec::Vec};
|
use alloc::{borrow::Cow, collections::binary_heap::BinaryHeap, vec::Vec};
|
||||||
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, ops::Range};
|
use core::{cmp::Ordering, fmt::Debug, marker::PhantomData, ops::Range};
|
||||||
|
|
||||||
use libafl_bolts::{rands::Rand, tuples::MatchName, Named};
|
use libafl_bolts::{
|
||||||
|
rands::Rand,
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -51,9 +55,9 @@ impl Ord for Earlier {
|
|||||||
/// The mutational stage using power schedules
|
/// The mutational stage using power schedules
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ColorizationStage<C, E, EM, O, Z> {
|
pub struct ColorizationStage<C, E, EM, O, Z> {
|
||||||
map_observer_name: Cow<'static, str>,
|
map_observer_ref: Reference<C>,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
phantom: PhantomData<(C, E, EM, O, E, Z)>,
|
phantom: PhantomData<(E, EM, O, E, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, EM, O, Z> UsesState for ColorizationStage<C, E, EM, O, Z>
|
impl<C, E, EM, O, Z> UsesState for ColorizationStage<C, E, EM, O, Z>
|
||||||
@ -68,7 +72,7 @@ where
|
|||||||
E: UsesState,
|
E: UsesState,
|
||||||
{
|
{
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.map_observer_name
|
self.map_observer_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +96,7 @@ where
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// Run with the mutated input
|
// Run with the mutated input
|
||||||
Self::colorize(fuzzer, executor, state, manager, &self.map_observer_name)?;
|
Self::colorize(fuzzer, executor, state, manager, &self.map_observer_ref)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -164,7 +168,7 @@ where
|
|||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
state: &mut E::State,
|
state: &mut E::State,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
name: &str,
|
obs_ref: &Reference<C>,
|
||||||
) -> Result<E::Input, Error> {
|
) -> Result<E::Input, Error> {
|
||||||
let mut input = state.current_input_cloned()?;
|
let mut input = state.current_input_cloned()?;
|
||||||
// The backup of the input
|
// The backup of the input
|
||||||
@ -179,7 +183,7 @@ where
|
|||||||
|
|
||||||
// Idea: No need to do this every time
|
// Idea: No need to do this every time
|
||||||
let orig_hash =
|
let orig_hash =
|
||||||
Self::get_raw_map_hash_run(fuzzer, executor, state, manager, consumed_input, name)?;
|
Self::get_raw_map_hash_run(fuzzer, executor, state, manager, consumed_input, obs_ref)?;
|
||||||
let changed_bytes = changed.bytes_mut();
|
let changed_bytes = changed.bytes_mut();
|
||||||
let input_len = changed_bytes.len();
|
let input_len = changed_bytes.len();
|
||||||
|
|
||||||
@ -224,7 +228,7 @@ where
|
|||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
consumed_input,
|
consumed_input,
|
||||||
name,
|
obs_ref,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
if orig_hash == changed_hash {
|
if orig_hash == changed_hash {
|
||||||
@ -297,7 +301,7 @@ where
|
|||||||
/// Creates a new [`ColorizationStage`]
|
/// Creates a new [`ColorizationStage`]
|
||||||
pub fn new(map_observer: &C) -> Self {
|
pub fn new(map_observer: &C) -> Self {
|
||||||
Self {
|
Self {
|
||||||
map_observer_name: map_observer.name().clone(),
|
map_observer_ref: map_observer.reference(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,17 +313,14 @@ where
|
|||||||
state: &mut E::State,
|
state: &mut E::State,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: E::Input,
|
input: E::Input,
|
||||||
name: &str,
|
obs_ref: &Reference<C>,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
executor.observers_mut().pre_exec_all(state, &input)?;
|
executor.observers_mut().pre_exec_all(state, &input)?;
|
||||||
|
|
||||||
let exit_kind = executor.run_target(fuzzer, state, manager, &input)?;
|
let exit_kind = executor.run_target(fuzzer, state, manager, &input)?;
|
||||||
|
|
||||||
let observer = executor
|
let observers = executor.observers();
|
||||||
.observers()
|
let observer = observers[obs_ref].as_ref();
|
||||||
.match_name::<C>(name)
|
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
|
||||||
.as_ref();
|
|
||||||
|
|
||||||
let hash = observer.hash_simple() as usize;
|
let hash = observer.hash_simple() as usize;
|
||||||
|
|
||||||
|
@ -2,13 +2,16 @@
|
|||||||
//! and use the results for fuzzer input and mutations.
|
//! and use the results for fuzzer input and mutations.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use alloc::{borrow::Cow, string::String};
|
use alloc::borrow::Cow;
|
||||||
#[cfg(feature = "concolic_mutation")]
|
#[cfg(feature = "concolic_mutation")]
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{string::ToString, vec::Vec};
|
||||||
#[cfg(feature = "concolic_mutation")]
|
#[cfg(feature = "concolic_mutation")]
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use libafl_bolts::{tuples::MatchName, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(all(feature = "concolic_mutation", feature = "introspection"))]
|
#[cfg(all(feature = "concolic_mutation", feature = "introspection"))]
|
||||||
use crate::monitors::PerfFeature;
|
use crate::monitors::PerfFeature;
|
||||||
@ -34,26 +37,26 @@ use crate::{
|
|||||||
|
|
||||||
/// Wraps a [`TracingStage`] to add concolic observing.
|
/// Wraps a [`TracingStage`] to add concolic observing.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ConcolicTracingStage<EM, TE, Z> {
|
pub struct ConcolicTracingStage<'a, EM, TE, Z> {
|
||||||
inner: TracingStage<EM, TE, Z>,
|
inner: TracingStage<EM, TE, Z>,
|
||||||
observer_name: String,
|
obs_ref: Reference<ConcolicObserver<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> UsesState for ConcolicTracingStage<EM, TE, Z>
|
impl<EM, TE, Z> UsesState for ConcolicTracingStage<'_, EM, TE, Z>
|
||||||
where
|
where
|
||||||
TE: UsesState,
|
TE: UsesState,
|
||||||
{
|
{
|
||||||
type State = TE::State;
|
type State = TE::State;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> Named for ConcolicTracingStage<EM, TE, Z> {
|
impl<EM, TE, Z> Named for ConcolicTracingStage<'_, EM, TE, Z> {
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
static NAME: Cow<'static, str> = Cow::Borrowed("ConcolicTracingStage");
|
static NAME: Cow<'static, str> = Cow::Borrowed("ConcolicTracingStage");
|
||||||
&NAME
|
&NAME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, TE, Z> Stage<E, EM, Z> for ConcolicTracingStage<EM, TE, Z>
|
impl<E, EM, TE, Z> Stage<E, EM, Z> for ConcolicTracingStage<'_, EM, TE, Z>
|
||||||
where
|
where
|
||||||
E: UsesState<State = TE::State>,
|
E: UsesState<State = TE::State>,
|
||||||
EM: UsesState<State = TE::State>,
|
EM: UsesState<State = TE::State>,
|
||||||
@ -70,12 +73,7 @@ where
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.inner.trace(fuzzer, state, manager)?;
|
self.inner.trace(fuzzer, state, manager)?;
|
||||||
if let Some(observer) = self
|
if let Some(observer) = self.inner.executor().observers().get(&self.obs_ref) {
|
||||||
.inner
|
|
||||||
.executor()
|
|
||||||
.observers()
|
|
||||||
.match_name::<ConcolicObserver>(&self.observer_name)
|
|
||||||
{
|
|
||||||
let metadata = observer.create_metadata_from_current_map();
|
let metadata = observer.create_metadata_from_current_map();
|
||||||
state
|
state
|
||||||
.current_testcase_mut()?
|
.current_testcase_mut()?
|
||||||
@ -94,14 +92,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> ConcolicTracingStage<EM, TE, Z> {
|
impl<'a, EM, TE, Z> ConcolicTracingStage<'a, EM, TE, Z> {
|
||||||
/// Creates a new default tracing stage using the given [`Executor`], observing traces from a
|
/// Creates a new default tracing stage using the given [`Executor`], observing traces from a
|
||||||
/// [`ConcolicObserver`] with the given name.
|
/// [`ConcolicObserver`] with the given name.
|
||||||
pub fn new(inner: TracingStage<EM, TE, Z>, observer_name: String) -> Self {
|
pub fn new(inner: TracingStage<EM, TE, Z>, obs_ref: Reference<ConcolicObserver<'a>>) -> Self {
|
||||||
Self {
|
Self { inner, obs_ref }
|
||||||
inner,
|
|
||||||
observer_name,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
//! The tracing stage can trace the target and enrich a [`crate::corpus::Testcase`] with metadata, for example for `CmpLog`.
|
//! The tracing stage can trace the target and enrich a [`crate::corpus::Testcase`] with metadata, for example for `CmpLog`.
|
||||||
|
|
||||||
use alloc::{
|
use alloc::{borrow::Cow, vec::Vec};
|
||||||
borrow::Cow,
|
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::{fmt::Debug, marker::PhantomData};
|
use core::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
use libafl_bolts::{AsSlice, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{Reference, Referenceable},
|
||||||
|
AsSlice, Named,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, HasCurrentCorpusIdx},
|
corpus::{Corpus, HasCurrentCorpusIdx},
|
||||||
@ -44,9 +43,9 @@ fn find_next_char(list: &[Option<u8>], mut idx: usize, ch: u8) -> usize {
|
|||||||
/// A stage that runs a tracer executor
|
/// A stage that runs a tracer executor
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GeneralizationStage<C, EM, O, OT, Z> {
|
pub struct GeneralizationStage<C, EM, O, OT, Z> {
|
||||||
map_observer_name: String,
|
map_observer_ref: Reference<C>,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
phantom: PhantomData<(C, EM, O, OT, Z)>,
|
phantom: PhantomData<(EM, O, OT, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, EM, O, OT, Z> Named for GeneralizationStage<C, EM, O, OT, Z> {
|
impl<C, EM, O, OT, Z> Named for GeneralizationStage<C, EM, O, OT, Z> {
|
||||||
@ -67,7 +66,7 @@ where
|
|||||||
impl<C, E, EM, O, Z> Stage<E, EM, Z> for GeneralizationStage<C, EM, O, E::Observers, Z>
|
impl<C, E, EM, O, Z> Stage<E, EM, Z> for GeneralizationStage<C, EM, O, E::Observers, Z>
|
||||||
where
|
where
|
||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
C: CanTrack + AsRef<O>,
|
C: CanTrack + AsRef<O> + Named,
|
||||||
E: Executor<EM, Z> + HasObservers,
|
E: Executor<EM, Z> + HasObservers,
|
||||||
E::Observers: ObserversTuple<E::State>,
|
E::Observers: ObserversTuple<E::State>,
|
||||||
E::State:
|
E::State:
|
||||||
@ -339,7 +338,7 @@ impl<C, EM, O, OT, Z> GeneralizationStage<C, EM, O, OT, Z>
|
|||||||
where
|
where
|
||||||
EM: UsesState,
|
EM: UsesState,
|
||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
C: CanTrack + AsRef<O>,
|
C: CanTrack + AsRef<O> + Named,
|
||||||
OT: ObserversTuple<EM::State>,
|
OT: ObserversTuple<EM::State>,
|
||||||
EM::State: UsesInput<Input = BytesInput> + HasExecutions + HasMetadata + HasCorpus,
|
EM::State: UsesInput<Input = BytesInput> + HasExecutions + HasMetadata + HasCorpus,
|
||||||
{
|
{
|
||||||
@ -348,16 +347,7 @@ where
|
|||||||
pub fn new(map_observer: &C) -> Self {
|
pub fn new(map_observer: &C) -> Self {
|
||||||
require_novelties_tracking!("GeneralizationStage", C);
|
require_novelties_tracking!("GeneralizationStage", C);
|
||||||
Self {
|
Self {
|
||||||
map_observer_name: map_observer.as_ref().name().to_string(),
|
map_observer_ref: map_observer.reference(),
|
||||||
phantom: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new [`GeneralizationStage`] from name
|
|
||||||
#[must_use]
|
|
||||||
pub fn from_name(map_observer_name: &str) -> Self {
|
|
||||||
Self {
|
|
||||||
map_observer_name: map_observer_name.to_string(),
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,10 +381,7 @@ where
|
|||||||
.post_exec_all(state, input, &exit_kind)?;
|
.post_exec_all(state, input, &exit_kind)?;
|
||||||
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
||||||
|
|
||||||
let cnt = executor
|
let cnt = executor.observers()[&self.map_observer_ref]
|
||||||
.observers()
|
|
||||||
.match_name::<C>(&self.map_observer_name)
|
|
||||||
.ok_or_else(|| Error::key_not_found("MapObserver not found".to_string()))?
|
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.how_many_set(novelties);
|
.how_many_set(novelties);
|
||||||
|
|
||||||
|
@ -429,11 +429,12 @@ where
|
|||||||
|
|
||||||
push_stage.set_current_corpus_idx(corpus_idx);
|
push_stage.set_current_corpus_idx(corpus_idx);
|
||||||
|
|
||||||
push_stage.init(fuzzer, state, event_mgr, executor.observers_mut())?;
|
push_stage.init(fuzzer, state, event_mgr, &mut *executor.observers_mut())?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let input =
|
let input =
|
||||||
match push_stage.pre_exec(fuzzer, state, event_mgr, executor.observers_mut()) {
|
match push_stage.pre_exec(fuzzer, state, event_mgr, &mut *executor.observers_mut())
|
||||||
|
{
|
||||||
Some(Ok(next_input)) => next_input,
|
Some(Ok(next_input)) => next_input,
|
||||||
Some(Err(err)) => return Err(err),
|
Some(Err(err)) => return Err(err),
|
||||||
None => break,
|
None => break,
|
||||||
@ -445,14 +446,14 @@ where
|
|||||||
fuzzer,
|
fuzzer,
|
||||||
state,
|
state,
|
||||||
event_mgr,
|
event_mgr,
|
||||||
executor.observers_mut(),
|
&mut *executor.observers_mut(),
|
||||||
input,
|
input,
|
||||||
exit_kind,
|
exit_kind,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.push_stage
|
self.push_stage
|
||||||
.deinit(fuzzer, state, event_mgr, executor.observers_mut())
|
.deinit(fuzzer, state, event_mgr, &mut *executor.observers_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -4,13 +4,16 @@ use alloc::borrow::Cow;
|
|||||||
use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData};
|
use core::{borrow::BorrowMut, fmt::Debug, hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
use ahash::RandomState;
|
use ahash::RandomState;
|
||||||
use libafl_bolts::{HasLen, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
HasLen, Named,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, HasCurrentCorpusIdx, Testcase},
|
corpus::{Corpus, HasCurrentCorpusIdx, Testcase},
|
||||||
events::EventFirer,
|
events::EventFirer,
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
feedbacks::{Feedback, FeedbackFactory, HasObserverName},
|
feedbacks::{Feedback, FeedbackFactory, HasObserverReference},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
mark_feature_time,
|
mark_feature_time,
|
||||||
mutators::{MutationResult, Mutator},
|
mutators::{MutationResult, Mutator},
|
||||||
@ -91,7 +94,7 @@ where
|
|||||||
fuzzer.execute_input(state, executor, manager, &base)?;
|
fuzzer.execute_input(state, executor, manager, &base)?;
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
|
|
||||||
let mut feedback = self.create_feedback(observers);
|
let mut feedback = self.create_feedback(&*observers);
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
loop {
|
loop {
|
||||||
@ -130,7 +133,7 @@ where
|
|||||||
state,
|
state,
|
||||||
manager,
|
manager,
|
||||||
input.clone(),
|
input.clone(),
|
||||||
observers,
|
&*observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
false,
|
false,
|
||||||
)?;
|
)?;
|
||||||
@ -139,7 +142,7 @@ where
|
|||||||
&& state.solutions().count() == solution_count
|
&& state.solutions().count() == solution_count
|
||||||
{
|
{
|
||||||
// we do not care about interesting inputs!
|
// we do not care about interesting inputs!
|
||||||
if feedback.is_interesting(state, manager, &input, observers, &exit_kind)? {
|
if feedback.is_interesting(state, manager, &input, &*observers, &exit_kind)? {
|
||||||
// we found a reduced corpus entry! use the smaller base
|
// we found a reduced corpus entry! use the smaller base
|
||||||
base = input;
|
base = input;
|
||||||
base_post = Some(post.clone());
|
base_post = Some(post.clone());
|
||||||
@ -172,11 +175,11 @@ where
|
|||||||
// marked as interesting above; similarly, it should not trigger objectives
|
// marked as interesting above; similarly, it should not trigger objectives
|
||||||
fuzzer
|
fuzzer
|
||||||
.feedback_mut()
|
.feedback_mut()
|
||||||
.is_interesting(state, manager, &base, observers, &exit_kind)?;
|
.is_interesting(state, manager, &base, &*observers, &exit_kind)?;
|
||||||
let mut testcase = Testcase::with_executions(base, *state.executions());
|
let mut testcase = Testcase::with_executions(base, *state.executions());
|
||||||
fuzzer
|
fuzzer
|
||||||
.feedback_mut()
|
.feedback_mut()
|
||||||
.append_metadata(state, manager, observers, &mut testcase)?;
|
.append_metadata(state, manager, &*observers, &mut testcase)?;
|
||||||
let prev = state.corpus_mut().replace(base_corpus_idx, testcase)?;
|
let prev = state.corpus_mut().replace(base_corpus_idx, testcase)?;
|
||||||
fuzzer
|
fuzzer
|
||||||
.scheduler_mut()
|
.scheduler_mut()
|
||||||
@ -245,6 +248,14 @@ where
|
|||||||
IP: MutatedTransformPost<CS::State> + Clone,
|
IP: MutatedTransformPost<CS::State> + Clone,
|
||||||
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
|
I: MutatedTransform<CS::Input, CS::State, Post = IP> + Clone,
|
||||||
{
|
{
|
||||||
|
fn restart_progress_should_run(&mut self, state: &mut Self::State) -> Result<bool, Error> {
|
||||||
|
self.restart_helper.restart_progress_should_run(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_restart_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
|
||||||
|
self.restart_helper.clear_restart_progress(state)
|
||||||
|
}
|
||||||
|
|
||||||
fn perform(
|
fn perform(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
@ -259,14 +270,6 @@ where
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restart_progress_should_run(&mut self, state: &mut Self::State) -> Result<bool, Error> {
|
|
||||||
self.restart_helper.restart_progress_should_run(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn clear_restart_progress(&mut self, state: &mut Self::State) -> Result<(), Error> {
|
|
||||||
self.restart_helper.clear_restart_progress(state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CS, E, EM, F1, F2, FF, I, IP, M, OT, Z> FeedbackFactory<F2, Z::State, OT>
|
impl<CS, E, EM, F1, F2, FF, I, IP, M, OT, Z> FeedbackFactory<F2, Z::State, OT>
|
||||||
@ -348,28 +351,31 @@ where
|
|||||||
/// A feedback which checks if the hash of the currently observed map is equal to the original hash
|
/// A feedback which checks if the hash of the currently observed map is equal to the original hash
|
||||||
/// provided
|
/// provided
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapEqualityFeedback<M, S> {
|
pub struct MapEqualityFeedback<C, M, S> {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
obs_name: Cow<'static, str>,
|
map_ref: Reference<C>,
|
||||||
orig_hash: u64,
|
orig_hash: u64,
|
||||||
phantom: PhantomData<(M, S)>,
|
phantom: PhantomData<(M, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S> Named for MapEqualityFeedback<M, S> {
|
impl<C, M, S> Named for MapEqualityFeedback<C, M, S> {
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S> HasObserverName for MapEqualityFeedback<M, S> {
|
impl<C, M, S> HasObserverReference for MapEqualityFeedback<C, M, S> {
|
||||||
fn observer_name(&self) -> &Cow<'static, str> {
|
type Observer = C;
|
||||||
&self.obs_name
|
|
||||||
|
fn observer_ref(&self) -> &Reference<Self::Observer> {
|
||||||
|
&self.map_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S> Feedback<S> for MapEqualityFeedback<M, S>
|
impl<C, M, S> Feedback<S> for MapEqualityFeedback<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: MapObserver,
|
||||||
|
C: AsRef<M>,
|
||||||
S: State,
|
S: State,
|
||||||
{
|
{
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
@ -385,52 +391,57 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
let obs = observers
|
let obs = observers
|
||||||
.match_name::<M>(self.observer_name())
|
.get(self.observer_ref())
|
||||||
.expect("Should have been provided valid observer name.");
|
.expect("Should have been provided valid observer name.");
|
||||||
Ok(obs.hash_simple() == self.orig_hash)
|
Ok(obs.as_ref().hash_simple() == self.orig_hash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A feedback factory for ensuring that the maps for minimized inputs are the same
|
/// A feedback factory for ensuring that the maps for minimized inputs are the same
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct MapEqualityFactory<M, S> {
|
pub struct MapEqualityFactory<C, M, S> {
|
||||||
obs_name: Cow<'static, str>,
|
map_ref: Reference<C>,
|
||||||
phantom: PhantomData<(M, S)>,
|
phantom: PhantomData<(C, M, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S> MapEqualityFactory<M, S>
|
impl<C, M, S> MapEqualityFactory<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: MapObserver,
|
||||||
|
C: AsRef<M> + Referenceable,
|
||||||
{
|
{
|
||||||
/// Creates a new map equality feedback for the given observer
|
/// Creates a new map equality feedback for the given observer
|
||||||
pub fn with_observer(obs: &M) -> Self {
|
pub fn new(obs: &C) -> Self {
|
||||||
Self {
|
Self {
|
||||||
obs_name: obs.name().clone(),
|
map_ref: obs.reference(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, S> HasObserverName for MapEqualityFactory<M, S> {
|
impl<C, M, S> HasObserverReference for MapEqualityFactory<C, M, S> {
|
||||||
fn observer_name(&self) -> &Cow<'static, str> {
|
type Observer = C;
|
||||||
&self.obs_name
|
|
||||||
|
fn observer_ref(&self) -> &Reference<C> {
|
||||||
|
&self.map_ref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, OT, S> FeedbackFactory<MapEqualityFeedback<M, S>, S, OT> for MapEqualityFactory<M, S>
|
impl<C, M, OT, S> FeedbackFactory<MapEqualityFeedback<C, M, S>, S, OT>
|
||||||
|
for MapEqualityFactory<C, M, S>
|
||||||
where
|
where
|
||||||
M: MapObserver,
|
M: MapObserver,
|
||||||
|
C: AsRef<M> + Referenceable,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
S: State + Debug,
|
S: State + Debug,
|
||||||
{
|
{
|
||||||
fn create_feedback(&self, observers: &OT) -> MapEqualityFeedback<M, S> {
|
fn create_feedback(&self, observers: &OT) -> MapEqualityFeedback<C, M, S> {
|
||||||
let obs = observers
|
let obs = observers
|
||||||
.match_name::<M>(self.observer_name())
|
.get(self.observer_ref())
|
||||||
.expect("Should have been provided valid observer name.");
|
.expect("Should have been provided valid observer name.");
|
||||||
MapEqualityFeedback {
|
MapEqualityFeedback {
|
||||||
name: Cow::from("MapEq"),
|
name: Cow::from("MapEq"),
|
||||||
obs_name: self.obs_name.clone(),
|
map_ref: obs.reference(),
|
||||||
orig_hash: obs.hash_simple(),
|
orig_hash: obs.as_ref().hash_simple(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ pub fn read_time_counter() -> u64 {
|
|||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read a timestamp for measurements
|
||||||
#[cfg(target_arch = "arm")]
|
#[cfg(target_arch = "arm")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn read_time_counter() -> u64 {
|
pub fn read_time_counter() -> u64 {
|
||||||
|
@ -2,15 +2,19 @@
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::{borrow::Cow, vec::Vec};
|
use alloc::{borrow::Cow, vec::Vec};
|
||||||
#[rustversion::not(nightly)]
|
#[cfg(feature = "alloc")]
|
||||||
use core::any::type_name;
|
use core::ops::{Deref, DerefMut};
|
||||||
use core::{
|
use core::{
|
||||||
any::TypeId,
|
any::{type_name, TypeId},
|
||||||
|
fmt::{Debug, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem::transmute,
|
mem::transmute,
|
||||||
|
ops::{Index, IndexMut},
|
||||||
ptr::{addr_of, addr_of_mut},
|
ptr::{addr_of, addr_of_mut},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
|
pub use tuple_list::{tuple_list, tuple_list_type, TupleList};
|
||||||
|
|
||||||
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
#[cfg(any(feature = "xxh3", feature = "alloc"))]
|
||||||
@ -219,9 +223,9 @@ where
|
|||||||
|
|
||||||
/// Returns the first element with the given type
|
/// Returns the first element with the given type
|
||||||
pub trait MatchFirstType {
|
pub trait MatchFirstType {
|
||||||
/// Returns the first element with the given type as borrow, or [`Option::None`]
|
/// Returns the first element with the given type as borrow, or [`None`]
|
||||||
fn match_first_type<T: 'static>(&self) -> Option<&T>;
|
fn match_first_type<T: 'static>(&self) -> Option<&T>;
|
||||||
/// Returns the first element with the given type as mutable borrow, or [`Option::None`]
|
/// Returns the first element with the given type as mutable borrow, or [`None`]
|
||||||
fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T>;
|
fn match_first_type_mut<T: 'static>(&mut self) -> Option<&mut T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +262,7 @@ where
|
|||||||
|
|
||||||
/// Returns the first element with the given type (dereference mut version)
|
/// Returns the first element with the given type (dereference mut version)
|
||||||
pub trait ExtractFirstRefType {
|
pub trait ExtractFirstRefType {
|
||||||
/// Returns the first element with the given type as borrow, or [`Option::None`]
|
/// Returns the first element with the given type as borrow, or [`None`]
|
||||||
fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self);
|
fn take<'a, T: 'static>(self) -> (Option<&'a T>, Self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +309,7 @@ where
|
|||||||
|
|
||||||
/// Returns the first element with the given type (dereference mut version)
|
/// Returns the first element with the given type (dereference mut version)
|
||||||
pub trait ExtractFirstRefMutType {
|
pub trait ExtractFirstRefMutType {
|
||||||
/// Returns the first element with the given type as borrow, or [`Option::None`]
|
/// Returns the first element with the given type as borrow, or [`None`]
|
||||||
fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self);
|
fn take<'a, T: 'static>(self) -> (Option<&'a mut T>, Self);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,8 +460,10 @@ where
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait MatchName {
|
pub trait MatchName {
|
||||||
/// Match for a name and return the borrowed value
|
/// Match for a name and return the borrowed value
|
||||||
|
#[deprecated = "Use `.reference` and either `.get` (fallible access) or `[]` (infallible access) instead"]
|
||||||
fn match_name<T>(&self, name: &str) -> Option<&T>;
|
fn match_name<T>(&self, name: &str) -> Option<&T>;
|
||||||
/// Match for a name and return the mut borrowed value
|
/// Match for a name and return the mut borrowed value
|
||||||
|
#[deprecated = "Use `.reference` and either `.get` (fallible access) or `[]` (infallible access) instead"]
|
||||||
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T>;
|
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,6 +478,7 @@ impl MatchName for () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<Head, Tail> MatchName for (Head, Tail)
|
impl<Head, Tail> MatchName for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: Named,
|
Head: Named,
|
||||||
@ -494,56 +501,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds an element of a `type` by the given `name`.
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
pub trait MatchNameAndType {
|
|
||||||
/// Finds an element of a `type` by the given `name`, and returns a borrow, or [`Option::None`].
|
|
||||||
fn match_name_type<T: 'static>(&self, name: &str) -> Option<&T>;
|
|
||||||
/// Finds an element of a `type` by the given `name`, and returns a mut borrow, or [`Option::None`].
|
|
||||||
fn match_name_type_mut<T: 'static>(&mut self, name: &str) -> Option<&mut T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
impl MatchNameAndType for () {
|
|
||||||
fn match_name_type<T: 'static>(&self, _name: &str) -> Option<&T> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
fn match_name_type_mut<T: 'static>(&mut self, _name: &str) -> Option<&mut T> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
|
||||||
impl<Head, Tail> MatchNameAndType for (Head, Tail)
|
|
||||||
where
|
|
||||||
Head: 'static + Named,
|
|
||||||
Tail: MatchNameAndType,
|
|
||||||
{
|
|
||||||
fn match_name_type<T: 'static>(&self, name: &str) -> Option<&T> {
|
|
||||||
// Switch this check to https://stackoverflow.com/a/60138532/7658998 when in stable and remove 'static
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Head>() && name == self.0.name() {
|
|
||||||
unsafe { (addr_of!(self.0) as *const T).as_ref() }
|
|
||||||
} else {
|
|
||||||
self.1.match_name_type::<T>(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn match_name_type_mut<T: 'static>(&mut self, name: &str) -> Option<&mut T> {
|
|
||||||
// Switch this check to https://stackoverflow.com/a/60138532/7658998 when in stable and remove 'static
|
|
||||||
if TypeId::of::<T>() == TypeId::of::<Head>() && name == self.0.name() {
|
|
||||||
unsafe { (addr_of_mut!(self.0) as *mut T).as_mut() }
|
|
||||||
} else {
|
|
||||||
self.1.match_name_type_mut::<T>(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structs that has `Reference `
|
/// Structs that has `Reference `
|
||||||
/// You should use this when you want to avoid specifying types using `match_name_type_mut`
|
/// You should use this when you want to avoid specifying types using `match_name_type_mut`
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait Referenceable: Named {
|
pub trait Referenceable: Named {
|
||||||
/// Return the `Reference `
|
/// Return the `Reference `
|
||||||
fn type_ref(&self) -> Reference<Self> {
|
fn reference(&self) -> Reference<Self> {
|
||||||
Reference {
|
Reference {
|
||||||
name: Named::name(self).clone(),
|
name: Named::name(self).clone(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
@ -554,38 +517,141 @@ pub trait Referenceable: Named {
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
impl<N> Referenceable for N where N: Named {}
|
impl<N> Referenceable for N where N: Named {}
|
||||||
|
|
||||||
/// Empty object with the type T
|
/// Object with the type T and the name associated with its concrete value
|
||||||
#[derive(Debug)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub struct Reference<T: ?Sized> {
|
pub struct Reference<T: ?Sized> {
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
|
#[serde(skip)]
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<T: ?Sized> Reference<T> {
|
||||||
|
/// Fetch the name of the referenced instance.
|
||||||
|
///
|
||||||
|
/// We explicitly do *not* implement [`Named`], as this could potentially lead to confusion
|
||||||
|
/// where we make a [`Reference`] of a [`Reference`] as [`Named`] is blanket implemented.
|
||||||
|
#[must_use]
|
||||||
|
pub fn name(&self) -> &Cow<'static, str> {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<T> Clone for Reference<T> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
name: self.name.clone(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<T> Debug for Reference<T> {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_struct("Reference")
|
||||||
|
.field("name", self.name())
|
||||||
|
.field("type", &type_name::<T>())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Search using `Reference `
|
/// Search using `Reference `
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait MatchNameRef {
|
pub trait MatchNameRef {
|
||||||
/// Search using name and `Reference `
|
/// Search using name and `Reference `
|
||||||
fn match_by_ref<T>(&self, rf: Reference<T>) -> Option<&T>;
|
fn get<T>(&self, rf: &Reference<T>) -> Option<&T>;
|
||||||
|
|
||||||
/// Search using name and `Reference `
|
/// Search using name and `Reference `
|
||||||
fn match_by_ref_mut<T>(&mut self, rf: Reference<T>) -> Option<&mut T>;
|
fn get_mut<T>(&mut self, rf: &Reference<T>) -> Option<&mut T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
|
#[allow(deprecated)]
|
||||||
impl<M> MatchNameRef for M
|
impl<M> MatchNameRef for M
|
||||||
where
|
where
|
||||||
M: MatchName,
|
M: MatchName,
|
||||||
{
|
{
|
||||||
fn match_by_ref<T>(&self, rf: Reference<T>) -> Option<&T> {
|
fn get<T>(&self, rf: &Reference<T>) -> Option<&T> {
|
||||||
self.match_name::<T>(&rf.name)
|
self.match_name::<T>(&rf.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn match_by_ref_mut<T>(&mut self, rf: Reference<T>) -> Option<&mut T> {
|
fn get_mut<T>(&mut self, rf: &Reference<T>) -> Option<&mut T> {
|
||||||
self.match_name_mut::<T>(&rf.name)
|
self.match_name_mut::<T>(&rf.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper type to enable the indexing of [`MatchName`] implementors with `[]`.
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct RefIndexable<RM, M>(RM, PhantomData<M>);
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<RM, M> From<RM> for RefIndexable<RM, M>
|
||||||
|
where
|
||||||
|
RM: Deref<Target = M>,
|
||||||
|
M: MatchName,
|
||||||
|
{
|
||||||
|
fn from(value: RM) -> Self {
|
||||||
|
RefIndexable(value, PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<RM, M> Deref for RefIndexable<RM, M>
|
||||||
|
where
|
||||||
|
RM: Deref<Target = M>,
|
||||||
|
{
|
||||||
|
type Target = RM::Target;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<RM, M> DerefMut for RefIndexable<RM, M>
|
||||||
|
where
|
||||||
|
RM: DerefMut<Target = M>,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<T, RM, M> Index<&Reference<T>> for RefIndexable<RM, M>
|
||||||
|
where
|
||||||
|
RM: Deref<Target = M>,
|
||||||
|
M: MatchName,
|
||||||
|
{
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: &Reference<T>) -> &Self::Output {
|
||||||
|
let Some(e) = self.get(index) else {
|
||||||
|
panic!("Could not find entry matching {index:?}")
|
||||||
|
};
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
impl<T, RM, M> IndexMut<&Reference<T>> for RefIndexable<RM, M>
|
||||||
|
where
|
||||||
|
RM: DerefMut<Target = M>,
|
||||||
|
M: MatchName,
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: &Reference<T>) -> &mut Self::Output {
|
||||||
|
let Some(e) = self.get_mut(index) else {
|
||||||
|
panic!("Could not find entry matching {index:?}")
|
||||||
|
};
|
||||||
|
e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Allows prepending of values to a tuple
|
/// Allows prepending of values to a tuple
|
||||||
pub trait Prepend<T> {
|
pub trait Prepend<T> {
|
||||||
/// The Resulting [`TupleList`], of an [`Prepend::prepend()`] call,
|
/// The Resulting [`TupleList`], of an [`Prepend::prepend()`] call,
|
||||||
|
@ -22,7 +22,11 @@ use libafl::{
|
|||||||
state::State,
|
state::State,
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
use libafl_bolts::{ownedref::OwnedPtr, Named, SerdeAny};
|
use libafl_bolts::{
|
||||||
|
ownedref::OwnedPtr,
|
||||||
|
tuples::{MatchNameRef, Reference, Referenceable},
|
||||||
|
Named, SerdeAny,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use termcolor::{Color, ColorSpec, WriteColor};
|
use termcolor::{Color, ColorSpec, WriteColor};
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
@ -39,8 +43,6 @@ use crate::{
|
|||||||
alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, utils::disas_count,
|
alloc::AllocationMetadata, asan::asan_rt::ASAN_SAVE_REGISTER_COUNT, utils::disas_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
static ASAN_ERRORS_NAME: Cow<'static, str> = Cow::Borrowed("AsanErrors");
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub(crate) struct AsanReadWriteError {
|
pub(crate) struct AsanReadWriteError {
|
||||||
pub registers: [usize; ASAN_SAVE_REGISTER_COUNT],
|
pub registers: [usize; ASAN_SAVE_REGISTER_COUNT],
|
||||||
@ -591,6 +593,7 @@ where
|
|||||||
impl Named for AsanErrorsObserver {
|
impl Named for AsanErrorsObserver {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
|
static ASAN_ERRORS_NAME: Cow<'static, str> = Cow::Borrowed("AsanErrors");
|
||||||
&ASAN_ERRORS_NAME
|
&ASAN_ERRORS_NAME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,6 +646,7 @@ impl AsanErrorsObserver {
|
|||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct AsanErrorsFeedback<S> {
|
pub struct AsanErrorsFeedback<S> {
|
||||||
errors: Option<AsanErrors>,
|
errors: Option<AsanErrors>,
|
||||||
|
obs_ref: Reference<AsanErrorsObserver>,
|
||||||
phantom: PhantomData<S>,
|
phantom: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,7 +669,7 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<AsanErrorsObserver>(&ASAN_ERRORS_NAME)
|
.get(&self.obs_ref)
|
||||||
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
||||||
let errors = observer.errors();
|
let errors = observer.errors();
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
@ -702,23 +706,18 @@ where
|
|||||||
impl<S> Named for AsanErrorsFeedback<S> {
|
impl<S> Named for AsanErrorsFeedback<S> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&ASAN_ERRORS_NAME
|
self.obs_ref.name()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> AsanErrorsFeedback<S> {
|
impl<S> AsanErrorsFeedback<S> {
|
||||||
/// Create a new `AsanErrorsFeedback`
|
/// Create a new `AsanErrorsFeedback`
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new() -> Self {
|
pub fn new(obs: &AsanErrorsObserver) -> Self {
|
||||||
Self {
|
Self {
|
||||||
errors: None,
|
errors: None,
|
||||||
|
obs_ref: obs.reference(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Default for AsanErrorsFeedback<S> {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -19,6 +19,7 @@ use libafl::{
|
|||||||
state::{HasExecutions, State, UsesState},
|
state::{HasExecutions, State, UsesState},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
|
|
||||||
#[cfg(all(unix, not(test)))]
|
#[cfg(all(unix, not(test)))]
|
||||||
use crate::asan::errors::AsanErrors;
|
use crate::asan::errors::AsanErrors;
|
||||||
@ -145,12 +146,12 @@ where
|
|||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.base.observers()
|
self.base.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.base.observers_mut()
|
self.base.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,10 +416,15 @@ mod tests {
|
|||||||
|
|
||||||
let mut feedback = ConstFeedback::new(false);
|
let mut feedback = ConstFeedback::new(false);
|
||||||
|
|
||||||
|
let asan_obs = AsanErrorsObserver::from_static_asan_errors();
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
let mut objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
// true enables the AsanErrorFeedback
|
// true enables the AsanErrorFeedback
|
||||||
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
feedback_and_fast!(
|
||||||
|
ConstFeedback::from(true),
|
||||||
|
AsanErrorsFeedback::new(&asan_obs)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -436,7 +441,7 @@ mod tests {
|
|||||||
let mut fuzzer = StdFuzzer::new(StdScheduler::new(), feedback, objective);
|
let mut fuzzer = StdFuzzer::new(StdScheduler::new(), feedback, objective);
|
||||||
|
|
||||||
let observers = tuple_list!(
|
let observers = tuple_list!(
|
||||||
AsanErrorsObserver::from_static_asan_errors() //,
|
asan_obs //,
|
||||||
);
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -174,4 +174,4 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type ShrinkMapFeedback<C, O, S, T> = MinMapFeedback<C, MappedEdgeMapObserver<O, T>, S, usize>;
|
pub type ShrinkMapFeedback<C, O, T> = MinMapFeedback<C, MappedEdgeMapObserver<O, T>, usize>;
|
||||||
|
@ -244,7 +244,7 @@ macro_rules! fuzz_with {
|
|||||||
map_feedback,
|
map_feedback,
|
||||||
feedback_and_fast!(ConstFeedback::new($options.shrink()), shrinking_map_feedback),
|
feedback_and_fast!(ConstFeedback::new($options.shrink()), shrinking_map_feedback),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ use libafl::{
|
|||||||
state::{HasExecutions, State, UsesState},
|
state::{HasExecutions, State, UsesState},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use libafl_bolts::AsSlice;
|
use libafl_bolts::{tuples::RefIndexable, AsSlice};
|
||||||
use libnyx::NyxReturnValue;
|
use libnyx::NyxReturnValue;
|
||||||
|
|
||||||
use crate::helper::NyxHelper;
|
use crate::helper::NyxHelper;
|
||||||
@ -146,11 +146,11 @@ where
|
|||||||
S: State,
|
S: State,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,12 @@ use libafl::{
|
|||||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal};
|
|
||||||
#[cfg(feature = "fork")]
|
#[cfg(feature = "fork")]
|
||||||
use libafl_bolts::shmem::ShMemProvider;
|
use libafl_bolts::shmem::ShMemProvider;
|
||||||
|
use libafl_bolts::{
|
||||||
|
os::unix_signals::{siginfo_t, ucontext_t, Signal},
|
||||||
|
tuples::RefIndexable,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{helpers::QemuHelperTuple, hooks::QemuHooks, Qemu};
|
use crate::{helpers::QemuHelperTuple, hooks::QemuHooks, Qemu};
|
||||||
|
|
||||||
@ -308,7 +311,7 @@ where
|
|||||||
self.state.post_exec::<Self, EM, OT, OF, Z>(
|
self.state.post_exec::<Self, EM, OT, OF, Z>(
|
||||||
input,
|
input,
|
||||||
qemu,
|
qemu,
|
||||||
self.inner.observers_mut(),
|
&mut *self.inner.observers_mut(),
|
||||||
&mut exit_kind,
|
&mut exit_kind,
|
||||||
);
|
);
|
||||||
Ok(exit_kind)
|
Ok(exit_kind)
|
||||||
@ -343,12 +346,12 @@ where
|
|||||||
QT: QemuHelperTuple<S>,
|
QT: QemuHelperTuple<S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +483,7 @@ where
|
|||||||
self.state.hooks.helpers_mut().post_exec_all(
|
self.state.hooks.helpers_mut().post_exec_all(
|
||||||
qemu,
|
qemu,
|
||||||
input,
|
input,
|
||||||
self.inner.observers_mut(),
|
&mut *self.inner.observers_mut(),
|
||||||
&mut exit_kind,
|
&mut exit_kind,
|
||||||
);
|
);
|
||||||
Ok(exit_kind)
|
Ok(exit_kind)
|
||||||
@ -527,12 +530,12 @@ where
|
|||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ use libafl::{
|
|||||||
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
state::{HasCorpus, HasExecutions, HasSolutions, State, UsesState},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
use libafl_bolts::tuples::RefIndexable;
|
||||||
|
|
||||||
#[cfg(emulation_mode = "usermode")]
|
#[cfg(emulation_mode = "usermode")]
|
||||||
use crate::executor::inproc_qemu_crash_handler;
|
use crate::executor::inproc_qemu_crash_handler;
|
||||||
@ -164,7 +165,7 @@ where
|
|||||||
.post_exec::<Self, EM, OT, OF, Z>(
|
.post_exec::<Self, EM, OT, OF, Z>(
|
||||||
input,
|
input,
|
||||||
qemu,
|
qemu,
|
||||||
self.inner.inner.observers_mut(),
|
&mut *self.inner.inner.observers_mut(),
|
||||||
&mut exit_kind,
|
&mut exit_kind,
|
||||||
);
|
);
|
||||||
Ok(exit_kind)
|
Ok(exit_kind)
|
||||||
@ -199,12 +200,12 @@ where
|
|||||||
QT: QemuHelperTuple<S>,
|
QT: QemuHelperTuple<S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
self.inner.observers()
|
self.inner.observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
self.inner.observers_mut()
|
self.inner.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use libafl::{
|
|||||||
inputs::{Input, UsesInput},
|
inputs::{Input, UsesInput},
|
||||||
observers::{stacktrace::BacktraceObserver, ObserversTuple},
|
observers::{stacktrace::BacktraceObserver, ObserversTuple},
|
||||||
};
|
};
|
||||||
use libafl_bolts::{tuples::MatchFirstType, Named};
|
use libafl_bolts::tuples::{MatchFirstType, MatchNameRef, Reference, Referenceable};
|
||||||
use libafl_qemu_sys::GuestAddr;
|
use libafl_qemu_sys::GuestAddr;
|
||||||
use thread_local::ThreadLocal;
|
use thread_local::ThreadLocal;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ use crate::{
|
|||||||
Qemu,
|
Qemu,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait CallTraceCollector: 'static + Debug {
|
pub trait CallTraceCollector: 'static {
|
||||||
fn on_call<QT, S>(
|
fn on_call<QT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
hooks: &mut QemuHooks<QT, S>,
|
hooks: &mut QemuHooks<QT, S>,
|
||||||
@ -62,7 +62,7 @@ pub trait CallTraceCollector: 'static + Debug {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CallTraceCollectorTuple: 'static + MatchFirstType + Debug {
|
pub trait CallTraceCollectorTuple: 'static + MatchFirstType {
|
||||||
fn on_call_all<QT, S>(
|
fn on_call_all<QT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
hooks: &mut QemuHooks<QT, S>,
|
hooks: &mut QemuHooks<QT, S>,
|
||||||
@ -402,7 +402,7 @@ where
|
|||||||
impl<S, T> QemuHelper<S> for QemuCallTracerHelper<T>
|
impl<S, T> QemuHelper<S> for QemuCallTracerHelper<T>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput,
|
||||||
T: CallTraceCollectorTuple,
|
T: CallTraceCollectorTuple + Debug,
|
||||||
{
|
{
|
||||||
fn init_hooks<QT>(&self, hooks: &QemuHooks<QT, S>)
|
fn init_hooks<QT>(&self, hooks: &QemuHooks<QT, S>)
|
||||||
where
|
where
|
||||||
@ -437,25 +437,17 @@ where
|
|||||||
|
|
||||||
// TODO support multiple threads with thread local callstack
|
// TODO support multiple threads with thread local callstack
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct OnCrashBacktraceCollector {
|
pub struct OnCrashBacktraceCollector<'a> {
|
||||||
callstack_hash: u64,
|
callstack_hash: u64,
|
||||||
observer_name: String,
|
obs_ref: Reference<BacktraceObserver<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnCrashBacktraceCollector {
|
impl<'a> OnCrashBacktraceCollector<'a> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(observer: &BacktraceObserver<'_>) -> Self {
|
pub fn new(observer: &BacktraceObserver<'a>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
callstack_hash: 0,
|
callstack_hash: 0,
|
||||||
observer_name: observer.name().to_string(),
|
obs_ref: observer.reference(),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn with_name(observer_name: String) -> Self {
|
|
||||||
Self {
|
|
||||||
callstack_hash: 0,
|
|
||||||
observer_name,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +461,10 @@ impl OnCrashBacktraceCollector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallTraceCollector for OnCrashBacktraceCollector {
|
impl<'a> CallTraceCollector for OnCrashBacktraceCollector<'a>
|
||||||
|
where
|
||||||
|
'a: 'static,
|
||||||
|
{
|
||||||
#[allow(clippy::unnecessary_cast)]
|
#[allow(clippy::unnecessary_cast)]
|
||||||
fn on_call<QT, S>(
|
fn on_call<QT, S>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -516,7 +511,7 @@ impl CallTraceCollector for OnCrashBacktraceCollector {
|
|||||||
S: UsesInput,
|
S: UsesInput,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name_mut::<BacktraceObserver<'_>>(&self.observer_name)
|
.get_mut(&self.obs_ref)
|
||||||
.expect("A OnCrashBacktraceCollector needs a BacktraceObserver");
|
.expect("A OnCrashBacktraceCollector needs a BacktraceObserver");
|
||||||
observer.fill_external(self.callstack_hash, exit_kind);
|
observer.fill_external(self.callstack_hash, exit_kind);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ hexagon = ["libafl_qemu/hexagon"] # build qemu for hexagon
|
|||||||
pyo3-build-config = { version = "0.18", optional = true }
|
pyo3-build-config = { version = "0.18", optional = true }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.12.0" }
|
libafl = { path = "../libafl", version = "0.12.0", features = ["adaptive_serialization"] }
|
||||||
libafl_bolts = { path = "../libafl_bolts", version = "0.12.0" }
|
libafl_bolts = { path = "../libafl_bolts", version = "0.12.0" }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.12.0" }
|
libafl_targets = { path = "../libafl_targets", version = "0.12.0" }
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ use libafl_bolts::{
|
|||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge, Referenceable},
|
||||||
AsSliceMut,
|
AsSliceMut,
|
||||||
};
|
};
|
||||||
use typed_builder::TypedBuilder;
|
use typed_builder::TypedBuilder;
|
||||||
@ -114,9 +114,15 @@ impl<'a> ForkserverBytesCoverageSugar<'a> {
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| log::info!("{s}"));
|
let monitor = MultiMonitor::new(|s| log::info!("{s}"));
|
||||||
|
|
||||||
|
// Create an observation channel to keep track of the execution time
|
||||||
|
let time_observer = TimeObserver::new("time");
|
||||||
|
let time_ref = time_observer.reference();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
// Coverage map shared between target and fuzzer
|
// Coverage map shared between target and fuzzer
|
||||||
let mut shmem = shmem_provider_client.new_shmem(MAP_SIZE).unwrap();
|
let mut shmem = shmem_provider_client.new_shmem(MAP_SIZE).unwrap();
|
||||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||||
@ -131,16 +137,13 @@ impl<'a> ForkserverBytesCoverageSugar<'a> {
|
|||||||
.track_indices()
|
.track_indices()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
|
||||||
let time_observer = TimeObserver::new("time");
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// This one is composed by two Feedbacks in OR
|
||||||
let mut feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -292,7 +295,8 @@ impl<'a> ForkserverBytesCoverageSugar<'a> {
|
|||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(self.cores)
|
.cores(self.cores)
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.remote_broker_addr(self.remote_broker_addr);
|
.remote_broker_addr(self.remote_broker_addr)
|
||||||
|
.time_ref(time_ref);
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let launcher = launcher.stdout_file(Some("/dev/null"));
|
let launcher = launcher.stdout_file(Some("/dev/null"));
|
||||||
match launcher.build().launch() {
|
match launcher.build().launch() {
|
||||||
|
@ -29,7 +29,7 @@ use libafl_bolts::{
|
|||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge, Referenceable},
|
||||||
AsSlice,
|
AsSlice,
|
||||||
};
|
};
|
||||||
use libafl_targets::{std_edges_map_observer, CmpLogObserver};
|
use libafl_targets::{std_edges_map_observer, CmpLogObserver};
|
||||||
@ -138,17 +138,20 @@ where
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{s}"));
|
let monitor = MultiMonitor::new(|s| println!("{s}"));
|
||||||
|
|
||||||
|
// Create an observation channel to keep track of the execution time
|
||||||
|
let time_observer = TimeObserver::new("time");
|
||||||
|
let time_ref = time_observer.reference();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
HitcountsMapObserver::new(unsafe { std_edges_map_observer("edges") })
|
HitcountsMapObserver::new(unsafe { std_edges_map_observer("edges") })
|
||||||
.track_indices();
|
.track_indices();
|
||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
|
||||||
let time_observer = TimeObserver::new("time");
|
|
||||||
|
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", true);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
@ -157,7 +160,7 @@ where
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -340,7 +343,8 @@ where
|
|||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(self.cores)
|
.cores(self.cores)
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.remote_broker_addr(self.remote_broker_addr);
|
.remote_broker_addr(self.remote_broker_addr)
|
||||||
|
.time_ref(time_ref);
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let launcher = launcher.stdout_file(Some("/dev/null"));
|
let launcher = launcher.stdout_file(Some("/dev/null"));
|
||||||
match launcher.build().launch() {
|
match launcher.build().launch() {
|
||||||
|
@ -32,7 +32,7 @@ use libafl_bolts::{
|
|||||||
current_nanos,
|
current_nanos,
|
||||||
rands::StdRand,
|
rands::StdRand,
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge, Referenceable},
|
||||||
AsSlice,
|
AsSlice,
|
||||||
};
|
};
|
||||||
pub use libafl_qemu::emu::Qemu;
|
pub use libafl_qemu::emu::Qemu;
|
||||||
@ -146,9 +146,15 @@ where
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| log::info!("{s}"));
|
let monitor = MultiMonitor::new(|s| log::info!("{s}"));
|
||||||
|
|
||||||
|
// Create an observation channel to keep track of the execution time
|
||||||
|
let time_observer = TimeObserver::new("time");
|
||||||
|
let time_ref = time_observer.reference();
|
||||||
|
|
||||||
let mut run_client = |state: Option<_>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
|
let time_observer = time_observer.clone();
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer = unsafe {
|
let edges_observer = unsafe {
|
||||||
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
|
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
|
||||||
@ -159,9 +165,6 @@ where
|
|||||||
.track_indices()
|
.track_indices()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create an observation channel to keep track of the execution time
|
|
||||||
let time_observer = TimeObserver::new("time");
|
|
||||||
|
|
||||||
// Keep tracks of CMPs
|
// Keep tracks of CMPs
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", true);
|
||||||
|
|
||||||
@ -171,7 +174,7 @@ where
|
|||||||
// New maximization map feedback linked to the edges observer and the feedback state
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
MaxMapFeedback::new(&edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::with_observer(&time_observer)
|
TimeFeedback::new(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
@ -433,9 +436,11 @@ where
|
|||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(self.cores)
|
.cores(self.cores)
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.remote_broker_addr(self.remote_broker_addr);
|
.remote_broker_addr(self.remote_broker_addr)
|
||||||
|
.time_ref(time_ref);
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let launcher = launcher.stdout_file(Some("/dev/null"));
|
let launcher = launcher.stdout_file(Some("/dev/null"));
|
||||||
|
|
||||||
launcher.build().launch().expect("Launcher failed");
|
launcher.build().launch().expect("Launcher failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,7 @@ struct cmp_map {
|
|||||||
|
|
||||||
/// A [`CmpObserver`] observer for AFL++ redqueen
|
/// A [`CmpObserver`] observer for AFL++ redqueen
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct AFLppCmpLogObserver<'a, S>
|
pub struct AFLppCmpLogObserver<'a, S> {
|
||||||
where
|
|
||||||
S: UsesInput + HasMetadata,
|
|
||||||
{
|
|
||||||
cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>,
|
cmp_map: OwnedRefMut<'a, AFLppCmpLogMap>,
|
||||||
size: Option<OwnedRefMut<'a, usize>>,
|
size: Option<OwnedRefMut<'a, usize>>,
|
||||||
name: Cow<'static, str>,
|
name: Cow<'static, str>,
|
||||||
@ -80,7 +77,7 @@ where
|
|||||||
impl<'a, S> CmpObserver<'a, AFLppCmpLogMap, S, AFLppCmpValuesMetadata>
|
impl<'a, S> CmpObserver<'a, AFLppCmpLogMap, S, AFLppCmpValuesMetadata>
|
||||||
for AFLppCmpLogObserver<'a, S>
|
for AFLppCmpLogObserver<'a, S>
|
||||||
where
|
where
|
||||||
S: UsesInput + Debug + HasMetadata,
|
S: UsesInput + HasMetadata,
|
||||||
{
|
{
|
||||||
/// Get the number of usable cmps (all by default)
|
/// Get the number of usable cmps (all by default)
|
||||||
fn usable_count(&self) -> usize {
|
fn usable_count(&self) -> usize {
|
||||||
@ -142,7 +139,7 @@ where
|
|||||||
|
|
||||||
impl<'a, S> Observer<S> for AFLppCmpLogObserver<'a, S>
|
impl<'a, S> Observer<S> for AFLppCmpLogObserver<'a, S>
|
||||||
where
|
where
|
||||||
S: UsesInput + Debug + HasMetadata,
|
S: UsesInput + HasMetadata,
|
||||||
{
|
{
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _input: &S::Input) -> Result<(), Error> {
|
||||||
#[cfg(feature = "cmplog_extended_instrumentation")]
|
#[cfg(feature = "cmplog_extended_instrumentation")]
|
||||||
@ -176,19 +173,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> Named for AFLppCmpLogObserver<'a, S>
|
impl<'a, S> Named for AFLppCmpLogObserver<'a, S> {
|
||||||
where
|
|
||||||
S: UsesInput + HasMetadata,
|
|
||||||
{
|
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> AFLppCmpLogObserver<'a, S>
|
impl<'a, S> AFLppCmpLogObserver<'a, S> {
|
||||||
where
|
|
||||||
S: UsesInput + HasMetadata,
|
|
||||||
{
|
|
||||||
/// Creates a new [`AFLppCmpLogObserver`] with the given name and map.
|
/// Creates a new [`AFLppCmpLogObserver`] with the given name and map.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
use alloc::{
|
use alloc::borrow::Cow;
|
||||||
borrow::Cow,
|
|
||||||
string::{String, ToString},
|
|
||||||
};
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -14,34 +11,43 @@ use libafl::{
|
|||||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, UsesState},
|
state::{HasCorpus, HasCurrentTestcase, HasExecutions, UsesState},
|
||||||
Error, HasMetadata, HasNamedMetadata,
|
Error, HasMetadata, HasNamedMetadata,
|
||||||
};
|
};
|
||||||
use libafl_bolts::{tuples::MatchName, Named};
|
use libafl_bolts::{
|
||||||
|
tuples::{MatchNameRef, Reference},
|
||||||
|
Named,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::cmps::observers::AFLppCmpLogObserver;
|
use crate::cmps::observers::AFLppCmpLogObserver;
|
||||||
|
|
||||||
/// Trace with tainted input
|
/// Trace with tainted input
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct AFLppCmplogTracingStage<EM, TE, Z> {
|
pub struct AFLppCmplogTracingStage<'a, EM, TE, Z>
|
||||||
|
where
|
||||||
|
TE: UsesState,
|
||||||
|
{
|
||||||
tracer_executor: TE,
|
tracer_executor: TE,
|
||||||
cmplog_observer_name: Option<String>,
|
cmplog_observer_ref: Option<Reference<AFLppCmpLogObserver<'a, TE::State>>>,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
phantom: PhantomData<(EM, TE, Z)>,
|
phantom: PhantomData<(EM, TE, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> UsesState for AFLppCmplogTracingStage<EM, TE, Z>
|
impl<EM, TE, Z> UsesState for AFLppCmplogTracingStage<'_, EM, TE, Z>
|
||||||
where
|
where
|
||||||
TE: UsesState,
|
TE: UsesState,
|
||||||
{
|
{
|
||||||
type State = TE::State;
|
type State = TE::State;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> Named for AFLppCmplogTracingStage<EM, TE, Z> {
|
impl<EM, TE, Z> Named for AFLppCmplogTracingStage<'_, EM, TE, Z>
|
||||||
|
where
|
||||||
|
TE: UsesState,
|
||||||
|
{
|
||||||
fn name(&self) -> &Cow<'static, str> {
|
fn name(&self) -> &Cow<'static, str> {
|
||||||
static NAME: Cow<'static, str> = Cow::Borrowed("AFLppCmplogTracingStage");
|
static NAME: Cow<'static, str> = Cow::Borrowed("AFLppCmplogTracingStage");
|
||||||
&NAME
|
&NAME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, TE, Z> Stage<E, EM, Z> for AFLppCmplogTracingStage<EM, TE, Z>
|
impl<E, EM, TE, Z> Stage<E, EM, Z> for AFLppCmplogTracingStage<'_, EM, TE, Z>
|
||||||
where
|
where
|
||||||
E: UsesState<State = TE::State>,
|
E: UsesState<State = TE::State>,
|
||||||
TE: Executor<EM, Z> + HasObservers,
|
TE: Executor<EM, Z> + HasObservers,
|
||||||
@ -61,12 +67,8 @@ where
|
|||||||
// First run with the un-mutated input
|
// First run with the un-mutated input
|
||||||
let unmutated_input = state.current_input_cloned()?;
|
let unmutated_input = state.current_input_cloned()?;
|
||||||
|
|
||||||
if let Some(name) = &self.cmplog_observer_name {
|
if let Some(obs_ref) = &self.cmplog_observer_ref {
|
||||||
if let Some(ob) = self
|
if let Some(ob) = self.tracer_executor.observers_mut().get_mut(obs_ref) {
|
||||||
.tracer_executor
|
|
||||||
.observers_mut()
|
|
||||||
.match_name_mut::<AFLppCmpLogObserver<TE::State>>(name)
|
|
||||||
{
|
|
||||||
// This is not the original input,
|
// This is not the original input,
|
||||||
// Set it to false
|
// Set it to false
|
||||||
ob.set_original(true);
|
ob.set_original(true);
|
||||||
@ -95,12 +97,8 @@ where
|
|||||||
None => return Err(Error::unknown("No metadata found")),
|
None => return Err(Error::unknown("No metadata found")),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(name) = &self.cmplog_observer_name {
|
if let Some(obs_ref) = &self.cmplog_observer_ref {
|
||||||
if let Some(ob) = self
|
if let Some(ob) = self.tracer_executor.observers_mut().get_mut(obs_ref) {
|
||||||
.tracer_executor
|
|
||||||
.observers_mut()
|
|
||||||
.match_name_mut::<AFLppCmpLogObserver<TE::State>>(name)
|
|
||||||
{
|
|
||||||
// This is not the original input,
|
// This is not the original input,
|
||||||
// Set it to false
|
// Set it to false
|
||||||
ob.set_original(false);
|
ob.set_original(false);
|
||||||
@ -137,20 +135,26 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, TE, Z> AFLppCmplogTracingStage<EM, TE, Z> {
|
impl<'a, EM, TE, Z> AFLppCmplogTracingStage<'a, EM, TE, Z>
|
||||||
|
where
|
||||||
|
TE: UsesState,
|
||||||
|
{
|
||||||
/// Creates a new default stage
|
/// Creates a new default stage
|
||||||
pub fn new(tracer_executor: TE) -> Self {
|
pub fn new(tracer_executor: TE) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cmplog_observer_name: None,
|
cmplog_observer_ref: None,
|
||||||
tracer_executor,
|
tracer_executor,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// With cmplog observer
|
/// With cmplog observer
|
||||||
pub fn with_cmplog_observer_name(tracer_executor: TE, name: &'static str) -> Self {
|
pub fn with_cmplog_observer(
|
||||||
|
tracer_executor: TE,
|
||||||
|
obs_ref: Reference<AFLppCmpLogObserver<'a, TE::State>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cmplog_observer_name: Some(name.to_string()),
|
cmplog_observer_ref: Some(obs_ref),
|
||||||
tracer_executor,
|
tracer_executor,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ use libafl::{
|
|||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
fs::{InputFile, INPUTFILE_STD},
|
fs::{InputFile, INPUTFILE_STD},
|
||||||
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
shmem::{ShMem, ShMemProvider, StdShMemProvider},
|
||||||
|
tuples::RefIndexable,
|
||||||
AsSlice, AsSliceMut,
|
AsSlice, AsSliceMut,
|
||||||
};
|
};
|
||||||
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
|
use tinyinst::tinyinst::{litecov::RunResult, TinyInst};
|
||||||
@ -300,12 +301,12 @@ where
|
|||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
OT: ObserversTuple<S>,
|
OT: ObserversTuple<S>,
|
||||||
{
|
{
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> RefIndexable<&Self::Observers, Self::Observers> {
|
||||||
&self.observers
|
RefIndexable::from(&self.observers)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn observers_mut(&mut self) -> &mut OT {
|
fn observers_mut(&mut self) -> RefIndexable<&mut Self::Observers, Self::Observers> {
|
||||||
&mut self.observers
|
RefIndexable::from(&mut self.observers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a, S, SP, OT> UsesState for TinyInstExecutor<'a, S, SP, OT>
|
impl<'a, S, SP, OT> UsesState for TinyInstExecutor<'a, S, SP, OT>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user