Composing feedback (#85)
* composing feedbacks as logic operations and bump to 0.2 * adapt fuzzers and libafl_frida * fix windows build
This commit is contained in:
parent
9e9d95f93d
commit
9f3b0984c3
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "baby_fuzzer"
|
name = "baby_fuzzer"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -56,13 +56,13 @@ pub fn main() {
|
|||||||
StdRand::with_seed(current_nanos()),
|
StdRand::with_seed(current_nanos()),
|
||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// Feedbacks to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
tuple_list!(MaxMapFeedback::new_with_observer(&observer)),
|
MaxMapFeedback::new_with_observer(&observer),
|
||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
tuple_list!(CrashFeedback::new()),
|
CrashFeedback::new(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Setup a basic mutator with a mutational stage
|
// Setup a basic mutator with a mutational stage
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "frida_libpng"
|
name = "frida_libpng"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
@ -25,7 +25,7 @@ libafl = { path = "../../libafl/", features = [ "std", "llmp_compression" ] } #,
|
|||||||
capstone = "0.8.0"
|
capstone = "0.8.0"
|
||||||
frida-gum = { version = "0.4", git = "https://github.com/s1341/frida-rust", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
frida-gum = { version = "0.4", git = "https://github.com/s1341/frida-rust", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
#frida-gum = { version = "0.4", path = "../../../frida-rust/frida-gum", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
#frida-gum = { version = "0.4", path = "../../../frida-rust/frida-gum", features = [ "auto-download", "event-sink", "invocation-listener"] }
|
||||||
libafl_frida = { path = "../../libafl_frida", version = "0.1.0" }
|
libafl_frida = { path = "../../libafl_frida", version = "0.2.0" }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libloading = "0.7.0"
|
libloading = "0.7.0"
|
||||||
|
@ -12,6 +12,7 @@ use libafl::{
|
|||||||
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasExecHooks,
|
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasExecHooks,
|
||||||
HasExecHooksTuple, HasObservers, HasObserversHooks,
|
HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
},
|
},
|
||||||
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
@ -276,17 +277,13 @@ unsafe fn fuzz(
|
|||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// Feedbacks to rate the interestingness of an input
|
// Feedbacks to rate the interestingness of an input
|
||||||
tuple_list!(MaxMapFeedback::new_with_observer_track(
|
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
||||||
&edges_observer,
|
|
||||||
true,
|
|
||||||
false
|
|
||||||
)),
|
|
||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new_save_meta(objective_dir, Some(OnDiskMetadataFormat::JsonPretty))
|
OnDiskCorpus::new_save_meta(objective_dir, Some(OnDiskMetadataFormat::JsonPretty))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
tuple_list!(
|
feedback_or!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
AsanErrorsFeedback::new()
|
AsanErrorsFeedback::new()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libmozjpeg"
|
name = "libfuzzer_libmozjpeg"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use libafl::{
|
|||||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, RandCorpusScheduler},
|
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, RandCorpusScheduler},
|
||||||
events::setup_restarting_mgr_std,
|
events::setup_restarting_mgr_std,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
||||||
@ -76,7 +77,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// Feedbacks to rate the interestingness of an input
|
// Feedbacks to rate the interestingness of an input
|
||||||
tuple_list!(
|
feedback_or!(
|
||||||
MaxMapFeedback::new_with_observer(&edges_observer),
|
MaxMapFeedback::new_with_observer(&edges_observer),
|
||||||
MaxMapFeedback::new_with_observer(&cmps_observer),
|
MaxMapFeedback::new_with_observer(&cmps_observer),
|
||||||
MaxMapFeedback::new_with_observer(&allocs_observer)
|
MaxMapFeedback::new_with_observer(&allocs_observer)
|
||||||
@ -85,7 +86,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
tuple_list!(CrashFeedback::new()),
|
CrashFeedback::new(),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libpng"
|
name = "libfuzzer_libpng"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ use libafl::{
|
|||||||
},
|
},
|
||||||
events::{setup_restarting_mgr_std, EventManager},
|
events::{setup_restarting_mgr_std, EventManager},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
||||||
@ -76,7 +77,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// Feedbacks to rate the interestingness of an input
|
// Feedbacks to rate the interestingness of an input
|
||||||
tuple_list!(
|
feedback_or!(
|
||||||
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
||||||
TimeFeedback::new()
|
TimeFeedback::new()
|
||||||
),
|
),
|
||||||
@ -84,7 +85,7 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
tuple_list!(CrashFeedback::new(), TimeoutFeedback::new()),
|
feedback_or!(CrashFeedback::new(), TimeoutFeedback::new()),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_stb_image"
|
name = "libfuzzer_stb_image"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
@ -11,6 +11,7 @@ use libafl::{
|
|||||||
},
|
},
|
||||||
events::setup_restarting_mgr_std,
|
events::setup_restarting_mgr_std,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
mutators::scheduled::{havoc_mutations, StdScheduledMutator},
|
||||||
@ -73,15 +74,15 @@ fn fuzz(corpus_dirs: Vec<PathBuf>, objective_dir: PathBuf, broker_port: u16) ->
|
|||||||
// Corpus that will be evolved, we keep it in memory for performance
|
// Corpus that will be evolved, we keep it in memory for performance
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// Feedbacks to rate the interestingness of an input
|
// Feedbacks to rate the interestingness of an input
|
||||||
tuple_list!(
|
feedback_or!(
|
||||||
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
MaxMapFeedback::new_with_observer_track(&edges_observer, true, false),
|
||||||
TimeFeedback::new()
|
TimeFeedback::new()
|
||||||
),
|
),
|
||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedback to recognize an input as solution
|
||||||
tuple_list!(CrashFeedback::new()),
|
CrashFeedback::new(),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl"
|
name = "libafl"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
description = "Slot your own fuzzers together and extend their features using Rust"
|
description = "Slot your own fuzzers together and extend their features using Rust"
|
||||||
documentation = "https://docs.rs/libafl"
|
documentation = "https://docs.rs/libafl"
|
||||||
|
@ -23,8 +23,6 @@ where
|
|||||||
input: Option<I>,
|
input: Option<I>,
|
||||||
/// Filename, if this testcase is backed by a file in the filesystem
|
/// Filename, if this testcase is backed by a file in the filesystem
|
||||||
filename: Option<String>,
|
filename: Option<String>,
|
||||||
/// Accumulated fitness from all the feedbacks
|
|
||||||
fitness: u32,
|
|
||||||
/// Map of metadata associated with this testcase
|
/// Map of metadata associated with this testcase
|
||||||
metadata: SerdeAnyMap,
|
metadata: SerdeAnyMap,
|
||||||
/// Time needed to execute the input
|
/// Time needed to execute the input
|
||||||
@ -120,24 +118,6 @@ where
|
|||||||
self.filename = Some(filename);
|
self.filename = Some(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the fitness
|
|
||||||
#[inline]
|
|
||||||
pub fn fitness(&self) -> u32 {
|
|
||||||
self.fitness
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the fitness (mutable)
|
|
||||||
#[inline]
|
|
||||||
pub fn fitness_mut(&mut self) -> &mut u32 {
|
|
||||||
&mut self.fitness
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the fitness
|
|
||||||
#[inline]
|
|
||||||
pub fn set_fitness(&mut self, fitness: u32) {
|
|
||||||
self.fitness = fitness;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the execution time of the testcase
|
/// Get the execution time of the testcase
|
||||||
pub fn exec_time(&self) -> &Option<Duration> {
|
pub fn exec_time(&self) -> &Option<Duration> {
|
||||||
&self.exec_time
|
&self.exec_time
|
||||||
@ -157,7 +137,6 @@ where
|
|||||||
Testcase {
|
Testcase {
|
||||||
input: Some(input.into()),
|
input: Some(input.into()),
|
||||||
filename: None,
|
filename: None,
|
||||||
fitness: 0,
|
|
||||||
metadata: SerdeAnyMap::new(),
|
metadata: SerdeAnyMap::new(),
|
||||||
exec_time: None,
|
exec_time: None,
|
||||||
cached_len: None,
|
cached_len: None,
|
||||||
@ -170,20 +149,6 @@ where
|
|||||||
Testcase {
|
Testcase {
|
||||||
input: Some(input),
|
input: Some(input),
|
||||||
filename: Some(filename),
|
filename: Some(filename),
|
||||||
fitness: 0,
|
|
||||||
metadata: SerdeAnyMap::new(),
|
|
||||||
exec_time: None,
|
|
||||||
cached_len: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new Testcase instace given an input and a fitness
|
|
||||||
#[inline]
|
|
||||||
pub fn with_fitness(input: I, fitness: u32) -> Self {
|
|
||||||
Testcase {
|
|
||||||
input: Some(input),
|
|
||||||
filename: None,
|
|
||||||
fitness,
|
|
||||||
metadata: SerdeAnyMap::new(),
|
metadata: SerdeAnyMap::new(),
|
||||||
exec_time: None,
|
exec_time: None,
|
||||||
cached_len: None,
|
cached_len: None,
|
||||||
@ -195,7 +160,6 @@ where
|
|||||||
Testcase {
|
Testcase {
|
||||||
input: None,
|
input: None,
|
||||||
filename: None,
|
filename: None,
|
||||||
fitness: 0,
|
|
||||||
metadata: SerdeAnyMap::new(),
|
metadata: SerdeAnyMap::new(),
|
||||||
exec_time: None,
|
exec_time: None,
|
||||||
cached_len: None,
|
cached_len: None,
|
||||||
|
@ -292,10 +292,9 @@ where
|
|||||||
|
|
||||||
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
||||||
// TODO include ExitKind in NewTestcase
|
// TODO include ExitKind in NewTestcase
|
||||||
let fitness = state.is_interesting(&input, &observers, &ExitKind::Ok)?;
|
let is_interesting = state.is_interesting(&input, &observers, &ExitKind::Ok)?;
|
||||||
if fitness > 0
|
if state
|
||||||
&& state
|
.add_if_interesting(&input, is_interesting, scheduler)?
|
||||||
.add_if_interesting(&input, fitness, scheduler)?
|
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -19,10 +19,10 @@ use crate::{
|
|||||||
executors::{
|
executors::{
|
||||||
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
},
|
},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::{HasObjectives, HasSolutions},
|
state::{HasObjective, HasSolutions},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ where
|
|||||||
/// * `harness_fn` - the harness, executiong the function
|
/// * `harness_fn` - the harness, executiong the function
|
||||||
/// * `observers` - the observers observing the target during execution
|
/// * `observers` - the observers observing the target during execution
|
||||||
/// This may return an error on unix, if signal handler setup fails
|
/// This may return an error on unix, if signal handler setup fails
|
||||||
pub fn new<OC, OFT>(
|
pub fn new<OC, OF>(
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
@ -167,19 +167,19 @@ where
|
|||||||
where
|
where
|
||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjective<OF, I> + HasSolutions<OC, I>,
|
||||||
{
|
{
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
unsafe {
|
unsafe {
|
||||||
let data = &mut unix_signal_handler::GLOBAL_STATE;
|
let data = &mut unix_signal_handler::GLOBAL_STATE;
|
||||||
write_volatile(
|
write_volatile(
|
||||||
&mut data.crash_handler,
|
&mut data.crash_handler,
|
||||||
unix_signal_handler::inproc_crash_handler::<EM, I, OC, OFT, OT, S>,
|
unix_signal_handler::inproc_crash_handler::<EM, I, OC, OF, OT, S>,
|
||||||
);
|
);
|
||||||
write_volatile(
|
write_volatile(
|
||||||
&mut data.timeout_handler,
|
&mut data.timeout_handler,
|
||||||
unix_signal_handler::inproc_timeout_handler::<EM, I, OC, OFT, OT, S>,
|
unix_signal_handler::inproc_timeout_handler::<EM, I, OC, OF, OT, S>,
|
||||||
);
|
);
|
||||||
|
|
||||||
setup_signal_handler(data)?;
|
setup_signal_handler(data)?;
|
||||||
@ -190,11 +190,11 @@ where
|
|||||||
let data = &mut windows_exception_handler::GLOBAL_STATE;
|
let data = &mut windows_exception_handler::GLOBAL_STATE;
|
||||||
write_volatile(
|
write_volatile(
|
||||||
&mut data.crash_handler,
|
&mut data.crash_handler,
|
||||||
windows_exception_handler::inproc_crash_handler::<EM, I, OC, OFT, OT, S>,
|
windows_exception_handler::inproc_crash_handler::<EM, I, OC, OF, OT, S>,
|
||||||
);
|
);
|
||||||
//write_volatile(
|
//write_volatile(
|
||||||
// &mut data.timeout_handler,
|
// &mut data.timeout_handler,
|
||||||
// windows_exception_handler::inproc_timeout_handler::<EM, I, OC, OFT, OT, S>,
|
// windows_exception_handler::inproc_timeout_handler::<EM, I, OC, OF, OT, S>,
|
||||||
//);
|
//);
|
||||||
|
|
||||||
setup_exception_handler(data)?;
|
setup_exception_handler(data)?;
|
||||||
@ -234,10 +234,10 @@ mod unix_signal_handler {
|
|||||||
corpus::{Corpus, Testcase},
|
corpus::{Corpus, Testcase},
|
||||||
events::{Event, EventManager},
|
events::{Event, EventManager},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::{HasObjectives, HasSolutions},
|
state::{HasObjective, HasSolutions},
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO merge GLOBAL_STATE with the Windows one
|
// TODO merge GLOBAL_STATE with the Windows one
|
||||||
@ -308,7 +308,7 @@ mod unix_signal_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub unsafe fn inproc_timeout_handler<EM, I, OC, OFT, OT, S>(
|
pub unsafe fn inproc_timeout_handler<EM, I, OC, OF, OT, S>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
@ -317,8 +317,8 @@ mod unix_signal_handler {
|
|||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjective<OF, I> + HasSolutions<OC, I>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
{
|
{
|
||||||
let state = (data.state_ptr as *mut S).as_mut().unwrap();
|
let state = (data.state_ptr as *mut S).as_mut().unwrap();
|
||||||
@ -337,11 +337,11 @@ mod unix_signal_handler {
|
|||||||
let input = (data.current_input_ptr as *const I).as_ref().unwrap();
|
let input = (data.current_input_ptr as *const I).as_ref().unwrap();
|
||||||
data.current_input_ptr = ptr::null();
|
data.current_input_ptr = ptr::null();
|
||||||
|
|
||||||
let obj_fitness = state
|
let interesting = state
|
||||||
.objectives_mut()
|
.objective_mut()
|
||||||
.is_interesting_all(&input, observers, &ExitKind::Timeout)
|
.is_interesting(&input, observers, &ExitKind::Timeout)
|
||||||
.expect("In timeout handler objectives failure.");
|
.expect("In timeout handler objective failure.");
|
||||||
if obj_fitness > 0 {
|
if interesting {
|
||||||
state
|
state
|
||||||
.solutions_mut()
|
.solutions_mut()
|
||||||
.add(Testcase::new(input.clone()))
|
.add(Testcase::new(input.clone()))
|
||||||
@ -374,7 +374,7 @@ mod unix_signal_handler {
|
|||||||
/// Will be used for signal handling.
|
/// Will be used for signal handling.
|
||||||
/// It will store the current State to shmem, then exit.
|
/// It will store the current State to shmem, then exit.
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
pub unsafe fn inproc_crash_handler<EM, I, OC, OFT, OT, S>(
|
pub unsafe fn inproc_crash_handler<EM, I, OC, OF, OT, S>(
|
||||||
_signal: Signal,
|
_signal: Signal,
|
||||||
_info: siginfo_t,
|
_info: siginfo_t,
|
||||||
_context: &mut ucontext_t,
|
_context: &mut ucontext_t,
|
||||||
@ -383,8 +383,8 @@ mod unix_signal_handler {
|
|||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjective<OF, I> + HasSolutions<OC, I>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
{
|
{
|
||||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||||
@ -446,11 +446,11 @@ mod unix_signal_handler {
|
|||||||
// Make sure we don't crash in the crash handler forever.
|
// Make sure we don't crash in the crash handler forever.
|
||||||
data.current_input_ptr = ptr::null();
|
data.current_input_ptr = ptr::null();
|
||||||
|
|
||||||
let obj_fitness = state
|
let interesting = state
|
||||||
.objectives_mut()
|
.objective_mut()
|
||||||
.is_interesting_all(&input, observers, &ExitKind::Crash)
|
.is_interesting(&input, observers, &ExitKind::Crash)
|
||||||
.expect("In crash handler objectives failure.");
|
.expect("In crash handler objective failure.");
|
||||||
if obj_fitness > 0 {
|
if interesting {
|
||||||
let new_input = input.clone();
|
let new_input = input.clone();
|
||||||
state
|
state
|
||||||
.solutions_mut()
|
.solutions_mut()
|
||||||
@ -528,10 +528,10 @@ mod windows_exception_handler {
|
|||||||
corpus::{Corpus, Testcase},
|
corpus::{Corpus, Testcase},
|
||||||
events::{Event, EventManager},
|
events::{Event, EventManager},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::{HasObjectives, HasSolutions},
|
state::{HasObjective, HasSolutions},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Signal handling on unix systems needs some nasty unsafe.
|
/// Signal handling on unix systems needs some nasty unsafe.
|
||||||
@ -582,7 +582,7 @@ mod windows_exception_handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn inproc_crash_handler<EM, I, OC, OFT, OT, S>(
|
pub unsafe fn inproc_crash_handler<EM, I, OC, OF, OT, S>(
|
||||||
code: ExceptionCode,
|
code: ExceptionCode,
|
||||||
exception_pointers: *mut EXCEPTION_POINTERS,
|
exception_pointers: *mut EXCEPTION_POINTERS,
|
||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
@ -590,8 +590,8 @@ mod windows_exception_handler {
|
|||||||
EM: EventManager<I, S>,
|
EM: EventManager<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
S: HasObjectives<OFT, I> + HasSolutions<OC, I>,
|
S: HasObjective<OF, I> + HasSolutions<OC, I>,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -610,11 +610,11 @@ mod windows_exception_handler {
|
|||||||
// Make sure we don't crash in the crash handler forever.
|
// Make sure we don't crash in the crash handler forever.
|
||||||
data.current_input_ptr = ptr::null();
|
data.current_input_ptr = ptr::null();
|
||||||
|
|
||||||
let obj_fitness = state
|
let interesting = state
|
||||||
.objectives_mut()
|
.objective_mut()
|
||||||
.is_interesting_all(&input, observers, &ExitKind::Crash)
|
.is_interesting(&input, observers, &ExitKind::Crash)
|
||||||
.expect("In crash handler objectives failure.");
|
.expect("In crash handler objective failure.");
|
||||||
if obj_fitness > 0 {
|
if interesting {
|
||||||
let new_input = input.clone();
|
let new_input = input.clone();
|
||||||
state
|
state
|
||||||
.solutions_mut()
|
.solutions_mut()
|
||||||
|
@ -139,11 +139,11 @@ where
|
|||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let mut interesting = 0;
|
let mut interesting = false;
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
let observer = observers.match_name_type::<O>(&self.name).unwrap();
|
let observer = observers.match_name_type::<O>(&self.name).unwrap();
|
||||||
let size = observer.usable_count();
|
let size = observer.usable_count();
|
||||||
@ -157,7 +157,7 @@ where
|
|||||||
let reduced = R::reduce(history, item);
|
let reduced = R::reduce(history, item);
|
||||||
if history != reduced {
|
if history != reduced {
|
||||||
self.history_map[i] = reduced;
|
self.history_map[i] = reduced;
|
||||||
interesting += 1;
|
interesting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.indexes.is_some() && self.novelties.is_none() {
|
} else if self.indexes.is_some() && self.novelties.is_none() {
|
||||||
@ -171,7 +171,7 @@ where
|
|||||||
let reduced = R::reduce(history, item);
|
let reduced = R::reduce(history, item);
|
||||||
if history != reduced {
|
if history != reduced {
|
||||||
self.history_map[i] = reduced;
|
self.history_map[i] = reduced;
|
||||||
interesting += 1;
|
interesting = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.indexes.is_none() && self.novelties.is_some() {
|
} else if self.indexes.is_none() && self.novelties.is_some() {
|
||||||
@ -182,7 +182,7 @@ where
|
|||||||
let reduced = R::reduce(history, item);
|
let reduced = R::reduce(history, item);
|
||||||
if history != reduced {
|
if history != reduced {
|
||||||
self.history_map[i] = reduced;
|
self.history_map[i] = reduced;
|
||||||
interesting += 1;
|
interesting = true;
|
||||||
self.novelties.as_mut().unwrap().push(i);
|
self.novelties.as_mut().unwrap().push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -197,7 +197,7 @@ where
|
|||||||
let reduced = R::reduce(history, item);
|
let reduced = R::reduce(history, item);
|
||||||
if history != reduced {
|
if history != reduced {
|
||||||
self.history_map[i] = reduced;
|
self.history_map[i] = reduced;
|
||||||
interesting += 1;
|
interesting = true;
|
||||||
self.novelties.as_mut().unwrap().push(i);
|
self.novelties.as_mut().unwrap().push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,12 @@ use crate::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
use core::time::Duration;
|
use core::{marker::PhantomData, time::Duration};
|
||||||
|
|
||||||
/// 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.
|
||||||
pub trait Feedback<I>: Named + serde::Serialize + serde::de::DeserializeOwned + 'static
|
pub trait Feedback<I>: Named + serde::Serialize + serde::de::DeserializeOwned
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
@ -30,7 +30,7 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple;
|
||||||
|
|
||||||
@ -47,77 +47,239 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FeedbacksTuple<I>: serde::Serialize + serde::de::DeserializeOwned
|
/// Compose feedbacks with an AND operation
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||||
|
pub struct AndFeedback<A, B, I>
|
||||||
where
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// Get the total interestingness value from all feedbacks
|
pub first: A,
|
||||||
fn is_interesting_all<OT>(
|
pub second: B,
|
||||||
|
phantom: PhantomData<I>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, B, I> Feedback<I> for AndFeedback<A, B, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
|
||||||
OT: ObserversTuple;
|
|
||||||
|
|
||||||
/// Write metadata for this testcase
|
|
||||||
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// Discards metadata - the end of this input's execution
|
|
||||||
fn discard_metadata_all(&mut self, input: &I) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I> FeedbacksTuple<I> for ()
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn is_interesting_all<OT>(&mut self, _: &I, _: &OT, _: &ExitKind) -> Result<u32, Error>
|
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
Ok(0)
|
let a = self.first.is_interesting(input, observers, exit_kind)?;
|
||||||
}
|
let b = self.second.is_interesting(input, observers, exit_kind)?;
|
||||||
|
Ok(a && b)
|
||||||
#[inline]
|
|
||||||
fn append_metadata_all(&mut self, _testcase: &mut Testcase<I>) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn discard_metadata_all(&mut self, _input: &I) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Head, Tail, I> FeedbacksTuple<I> for (Head, Tail)
|
impl<A, B, I> Named for AndFeedback<A, B, I>
|
||||||
where
|
where
|
||||||
Head: Feedback<I>,
|
A: Feedback<I>,
|
||||||
Tail: FeedbacksTuple<I>,
|
B: Feedback<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting_all<OT>(
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
//format!("And({}, {})", self.first.name(), self.second.name())
|
||||||
|
"AndFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, B, I> AndFeedback<A, B, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new(first: A, second: B) -> Self {
|
||||||
|
Self {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compose feedbacks with an OR operation
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||||
|
pub struct OrFeedback<A, B, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub first: A,
|
||||||
|
pub second: B,
|
||||||
|
phantom: PhantomData<I>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, B, I> Feedback<I> for OrFeedback<A, B, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting<OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
Ok(self.0.is_interesting(input, observers, exit_kind)?
|
let a = self.first.is_interesting(input, observers, exit_kind)?;
|
||||||
+ self.1.is_interesting_all(input, observers, exit_kind)?)
|
let b = self.second.is_interesting(input, observers, exit_kind)?;
|
||||||
|
Ok(a || b)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn append_metadata_all(&mut self, testcase: &mut Testcase<I>) -> Result<(), Error> {
|
impl<A, B, I> Named for OrFeedback<A, B, I>
|
||||||
self.0.append_metadata(testcase)?;
|
where
|
||||||
self.1.append_metadata_all(testcase)
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
//format!("Or({}, {})", self.first.name(), self.second.name())
|
||||||
|
"OrFeedback"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn discard_metadata_all(&mut self, input: &I) -> Result<(), Error> {
|
impl<A, B, I> OrFeedback<A, B, I>
|
||||||
self.0.discard_metadata(input)?;
|
where
|
||||||
self.1.discard_metadata_all(input)
|
A: Feedback<I>,
|
||||||
|
B: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new(first: A, second: B) -> Self {
|
||||||
|
Self {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compose feedbacks with an OR operation
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(bound = "I: serde::de::DeserializeOwned")]
|
||||||
|
pub struct NotFeedback<A, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub first: A,
|
||||||
|
phantom: PhantomData<I>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, I> Feedback<I> for NotFeedback<A, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting<OT>(
|
||||||
|
&mut self,
|
||||||
|
input: &I,
|
||||||
|
observers: &OT,
|
||||||
|
exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
Ok(!self.first.is_interesting(input, observers, exit_kind)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, I> Named for NotFeedback<A, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
//format!("Not({})", self.first.name())
|
||||||
|
"NotFeedback"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A, I> NotFeedback<A, I>
|
||||||
|
where
|
||||||
|
A: Feedback<I>,
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
pub fn new(first: A) -> Self {
|
||||||
|
Self {
|
||||||
|
first,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Variadic macro to create a chain of AndFeedback
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! feedback_and {
|
||||||
|
( $last:expr ) => { $last };
|
||||||
|
|
||||||
|
( $head:expr, $($tail:expr), +) => {
|
||||||
|
// recursive call
|
||||||
|
$crate::feedbacks::AndFeedback::new($head , feedback_and!($($tail),+))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Variadic macro to create a chain of OrFeedback
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! feedback_or {
|
||||||
|
( $last:expr ) => { $last };
|
||||||
|
|
||||||
|
( $head:expr, $($tail:expr), +) => {
|
||||||
|
// recursive call
|
||||||
|
$crate::feedbacks::OrFeedback::new($head , feedback_or!($($tail),+))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Variadic macro to create a NotFeedback
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! feedback_not {
|
||||||
|
( $last:expr ) => {
|
||||||
|
$crate::feedbacks::NotFeedback::new($last)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hack to use () as empty Feedback
|
||||||
|
impl<I> Feedback<I> for ()
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
{
|
||||||
|
fn is_interesting<OT>(
|
||||||
|
&mut self,
|
||||||
|
_input: &I,
|
||||||
|
_observers: &OT,
|
||||||
|
_exit_kind: &ExitKind,
|
||||||
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Named for () {
|
||||||
|
#[inline]
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"Empty"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,14 +296,14 @@ where
|
|||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
if let ExitKind::Crash = exit_kind {
|
if let ExitKind::Crash = exit_kind {
|
||||||
Ok(1)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
Ok(0)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,14 +339,14 @@ where
|
|||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
if let ExitKind::Timeout = exit_kind {
|
if let ExitKind::Timeout = exit_kind {
|
||||||
Ok(1)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
Ok(0)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +371,7 @@ impl Default for TimeoutFeedback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Nop feedback that annotates execution time in the new testcase, if any
|
/// Nop feedback that annotates execution time in the new testcase, if any
|
||||||
|
/// For this Feedback, the testcase is never interesting (use with an OR)
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct TimeFeedback {
|
pub struct TimeFeedback {
|
||||||
exec_time: Option<Duration>,
|
exec_time: Option<Duration>,
|
||||||
@ -223,13 +386,13 @@ where
|
|||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let observer = observers.match_first_type::<TimeObserver>().unwrap();
|
let observer = observers.match_first_type::<TimeObserver>().unwrap();
|
||||||
self.exec_time = *observer.last_runtime();
|
self.exec_time = *observer.last_runtime();
|
||||||
Ok(0)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append to the testcase the generated metadata in case of a new corpus item
|
/// Append to the testcase the generated metadata in case of a new corpus item
|
||||||
|
@ -15,7 +15,7 @@ use crate::{
|
|||||||
executors::{
|
executors::{
|
||||||
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
},
|
},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::Feedback,
|
||||||
generators::Generator,
|
generators::Generator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
@ -98,30 +98,30 @@ pub trait HasMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering a feedbacks tuple
|
/// Trait for elements offering a feedback
|
||||||
pub trait HasFeedbacks<FT, I>: Sized
|
pub trait HasFeedback<F, I>: Sized
|
||||||
where
|
where
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// The feedbacks tuple
|
/// The feedback
|
||||||
fn feedbacks(&self) -> &FT;
|
fn feedback(&self) -> &F;
|
||||||
|
|
||||||
/// The feedbacks tuple (mut)
|
/// The feedback (mut)
|
||||||
fn feedbacks_mut(&mut self) -> &mut FT;
|
fn feedback_mut(&mut self) -> &mut F;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering an objective feedbacks tuple
|
/// Trait for elements offering an objective feedback tuple
|
||||||
pub trait HasObjectives<FT, I>: Sized
|
pub trait HasObjective<OF, I>: Sized
|
||||||
where
|
where
|
||||||
FT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// The objective feedbacks tuple
|
/// The objective feedback
|
||||||
fn objectives(&self) -> &FT;
|
fn objective(&self) -> &OF;
|
||||||
|
|
||||||
/// The objective feedbacks tuple (mut)
|
/// The objective feedback (mut)
|
||||||
fn objectives_mut(&mut self) -> &mut FT;
|
fn objective_mut(&mut self) -> &mut OF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for the execution counter
|
/// Trait for the execution counter
|
||||||
@ -153,7 +153,7 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple;
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ where
|
|||||||
fn add_if_interesting<CS>(
|
fn add_if_interesting<CS>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
fitness: u32,
|
is_interesting: bool,
|
||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<Option<usize>, Error>
|
) -> Result<Option<usize>, Error>
|
||||||
where
|
where
|
||||||
@ -169,7 +169,7 @@ where
|
|||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an input modyfing the state of the fuzzer and returning a fitness
|
/// Evaluate an input modyfing the state of the fuzzer
|
||||||
pub trait Evaluator<I>: Sized
|
pub trait Evaluator<I>: Sized
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
@ -181,7 +181,7 @@ where
|
|||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<(u32, Option<usize>), Error>
|
) -> Result<(bool, Option<usize>), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I>
|
E: Executor<I>
|
||||||
+ HasObservers<OT>
|
+ HasObservers<OT>
|
||||||
@ -194,15 +194,15 @@ where
|
|||||||
|
|
||||||
/// The state a fuzz run.
|
/// The state a fuzz run.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
#[serde(bound = "F: serde::de::DeserializeOwned")]
|
||||||
pub struct State<C, FT, I, OFT, R, SC>
|
pub struct State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// RNG instance
|
/// RNG instance
|
||||||
rand: R,
|
rand: R,
|
||||||
@ -213,11 +213,11 @@ where
|
|||||||
/// The corpus
|
/// The corpus
|
||||||
corpus: C,
|
corpus: C,
|
||||||
/// Feedbacks used to evaluate an input
|
/// Feedbacks used to evaluate an input
|
||||||
feedbacks: FT,
|
feedback: F,
|
||||||
// Solutions corpus
|
// Solutions corpus
|
||||||
solutions: SC,
|
solutions: SC,
|
||||||
/// Objective Feedbacks
|
/// Objective Feedbacks
|
||||||
objectives: OFT,
|
objective: OF,
|
||||||
/// Metadata stored for this state by one of the components
|
/// Metadata stored for this state by one of the components
|
||||||
metadata: SerdeAnyMap,
|
metadata: SerdeAnyMap,
|
||||||
/// MaxSize testcase size for mutators that appreciate it
|
/// MaxSize testcase size for mutators that appreciate it
|
||||||
@ -226,14 +226,14 @@ where
|
|||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasRand<R> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasRand<R> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// The rand instance
|
/// The rand instance
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -248,14 +248,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasCorpus<C, I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasCorpus<C, I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Returns the corpus
|
/// Returns the corpus
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -270,14 +270,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasSolutions<SC, I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasSolutions<SC, I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Returns the solutions corpus
|
/// Returns the solutions corpus
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -292,14 +292,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasMetadata for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasMetadata for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Get all the metadata into an HashMap
|
/// Get all the metadata into an HashMap
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -314,58 +314,58 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasFeedbacks<FT, I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasFeedback<F, I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// The feedbacks tuple
|
/// The feedback
|
||||||
#[inline]
|
#[inline]
|
||||||
fn feedbacks(&self) -> &FT {
|
fn feedback(&self) -> &F {
|
||||||
&self.feedbacks
|
&self.feedback
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The feedbacks tuple (mut)
|
/// The feedback (mut)
|
||||||
#[inline]
|
#[inline]
|
||||||
fn feedbacks_mut(&mut self) -> &mut FT {
|
fn feedback_mut(&mut self) -> &mut F {
|
||||||
&mut self.feedbacks
|
&mut self.feedback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasObjectives<OFT, I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasObjective<OF, I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// The objective feedbacks tuple
|
/// The objective feedback
|
||||||
#[inline]
|
#[inline]
|
||||||
fn objectives(&self) -> &OFT {
|
fn objective(&self) -> &OF {
|
||||||
&self.objectives
|
&self.objective
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The objective feedbacks tuple (mut)
|
/// The objective feedback (mut)
|
||||||
#[inline]
|
#[inline]
|
||||||
fn objectives_mut(&mut self) -> &mut OFT {
|
fn objective_mut(&mut self) -> &mut OF {
|
||||||
&mut self.objectives
|
&mut self.objective
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasExecutions for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasExecutions for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// The executions counter
|
/// The executions counter
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -380,14 +380,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasMaxSize for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasMaxSize for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
fn max_size(&self) -> usize {
|
fn max_size(&self) -> usize {
|
||||||
self.max_size
|
self.max_size
|
||||||
@ -398,14 +398,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> HasStartTime for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> HasStartTime for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// The starting time
|
/// The starting time
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -420,14 +420,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> IfInteresting<I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> IfInteresting<I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Evaluate if a set of observation channels has an interesting state
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<OT>(
|
||||||
@ -435,12 +435,12 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
self.feedbacks_mut()
|
self.feedback_mut()
|
||||||
.is_interesting_all(input, observers, exit_kind)
|
.is_interesting(input, observers, exit_kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds this input to the corpus, if it's intersting, and return the index
|
/// Adds this input to the corpus, if it's intersting, and return the index
|
||||||
@ -448,33 +448,33 @@ where
|
|||||||
fn add_if_interesting<CS>(
|
fn add_if_interesting<CS>(
|
||||||
&mut self,
|
&mut self,
|
||||||
input: &I,
|
input: &I,
|
||||||
fitness: u32,
|
is_interesting: bool,
|
||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<Option<usize>, Error>
|
) -> Result<Option<usize>, Error>
|
||||||
where
|
where
|
||||||
CS: CorpusScheduler<I, Self>,
|
CS: CorpusScheduler<I, Self>,
|
||||||
{
|
{
|
||||||
if fitness > 0 {
|
if is_interesting {
|
||||||
let mut testcase = Testcase::with_fitness(input.clone(), fitness);
|
let mut testcase = Testcase::new(input.clone());
|
||||||
self.feedbacks_mut().append_metadata_all(&mut testcase)?;
|
self.feedback_mut().append_metadata(&mut testcase)?;
|
||||||
let idx = self.corpus.add(testcase)?;
|
let idx = self.corpus.add(testcase)?;
|
||||||
scheduler.on_add(self, idx)?;
|
scheduler.on_add(self, idx)?;
|
||||||
Ok(Some(idx))
|
Ok(Some(idx))
|
||||||
} else {
|
} else {
|
||||||
self.feedbacks_mut().discard_metadata_all(&input)?;
|
self.feedback_mut().discard_metadata(&input)?;
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> Evaluator<I> for State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> Evaluator<I> for State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -485,7 +485,7 @@ where
|
|||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
scheduler: &CS,
|
scheduler: &CS,
|
||||||
) -> Result<(u32, Option<usize>), Error>
|
) -> Result<(bool, Option<usize>), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I>
|
E: Executor<I>
|
||||||
+ HasObservers<OT>
|
+ HasObservers<OT>
|
||||||
@ -496,19 +496,19 @@ where
|
|||||||
EM: EventManager<I, Self>,
|
EM: EventManager<I, Self>,
|
||||||
CS: CorpusScheduler<I, Self>,
|
CS: CorpusScheduler<I, Self>,
|
||||||
{
|
{
|
||||||
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
|
let (is_interesting, is_solution) = self.execute_input(&input, executor, manager)?;
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
|
|
||||||
if is_solution {
|
if is_solution {
|
||||||
// If the input is a solution, add it to the respective corpus
|
// If the input is a solution, add it to the respective corpus
|
||||||
let mut testcase = Testcase::new(input.clone());
|
let mut testcase = Testcase::new(input.clone());
|
||||||
self.objectives_mut().append_metadata_all(&mut testcase)?;
|
self.objective_mut().append_metadata(&mut testcase)?;
|
||||||
self.solutions_mut().add(testcase)?;
|
self.solutions_mut().add(testcase)?;
|
||||||
} else {
|
} else {
|
||||||
self.objectives_mut().discard_metadata_all(&input)?;
|
self.objective_mut().discard_metadata(&input)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let corpus_idx = self.add_if_interesting(&input, fitness, scheduler)?;
|
let corpus_idx = self.add_if_interesting(&input, is_interesting, scheduler)?;
|
||||||
if corpus_idx.is_some() {
|
if corpus_idx.is_some() {
|
||||||
let observers_buf = manager.serialize_observers(observers)?;
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
manager.fire(
|
manager.fire(
|
||||||
@ -524,18 +524,18 @@ where
|
|||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((fitness, corpus_idx))
|
Ok((is_interesting, corpus_idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<C, FT, OFT, R, SC> State<C, FT, BytesInput, OFT, R, SC>
|
impl<C, F, OF, R, SC> State<C, F, BytesInput, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<BytesInput>,
|
C: Corpus<BytesInput>,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<BytesInput>,
|
F: Feedback<BytesInput>,
|
||||||
SC: Corpus<BytesInput>,
|
SC: Corpus<BytesInput>,
|
||||||
OFT: FeedbacksTuple<BytesInput>,
|
OF: Feedback<BytesInput>,
|
||||||
{
|
{
|
||||||
pub fn load_from_directory<CS, E, OT, EM>(
|
pub fn load_from_directory<CS, E, OT, EM>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -568,9 +568,10 @@ where
|
|||||||
println!("Loading file {:?} ...", &path);
|
println!("Loading file {:?} ...", &path);
|
||||||
let bytes = fs::read(&path)?;
|
let bytes = fs::read(&path)?;
|
||||||
let input = BytesInput::new(bytes);
|
let input = BytesInput::new(bytes);
|
||||||
let (fitness, is_solution) = self.execute_input(&input, executor, manager)?;
|
let (is_interesting, is_solution) =
|
||||||
|
self.execute_input(&input, executor, manager)?;
|
||||||
if self
|
if self
|
||||||
.add_if_interesting(&input, fitness, scheduler)?
|
.add_if_interesting(&input, is_interesting, scheduler)?
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
println!("File {:?} was not interesting, skipped.", &path);
|
||||||
@ -618,14 +619,14 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, FT, I, OFT, R, SC> State<C, FT, I, OFT, R, SC>
|
impl<C, F, I, OF, R, SC> State<C, F, I, OF, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbacksTuple<I>,
|
F: Feedback<I>,
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
OFT: FeedbacksTuple<I>,
|
OF: Feedback<I>,
|
||||||
{
|
{
|
||||||
/// Runs the input and triggers observers and feedback
|
/// Runs the input and triggers observers and feedback
|
||||||
pub fn execute_input<E, EM, OT>(
|
pub fn execute_input<E, EM, OT>(
|
||||||
@ -633,7 +634,7 @@ where
|
|||||||
input: &I,
|
input: &I,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
) -> Result<(u32, bool), Error>
|
) -> Result<(bool, bool), Error>
|
||||||
where
|
where
|
||||||
E: Executor<I>
|
E: Executor<I>
|
||||||
+ HasObservers<OT>
|
+ HasObservers<OT>
|
||||||
@ -653,15 +654,14 @@ where
|
|||||||
executor.post_exec_observers(self, event_mgr, input)?;
|
executor.post_exec_observers(self, event_mgr, input)?;
|
||||||
|
|
||||||
let observers = executor.observers();
|
let observers = executor.observers();
|
||||||
let fitness = self
|
let is_interesting = self
|
||||||
.feedbacks_mut()
|
.feedback_mut()
|
||||||
.is_interesting_all(&input, observers, &exit_kind)?;
|
.is_interesting(&input, observers, &exit_kind)?;
|
||||||
|
|
||||||
let is_solution = self
|
let is_solution = self
|
||||||
.objectives_mut()
|
.objective_mut()
|
||||||
.is_interesting_all(&input, observers, &exit_kind)?
|
.is_interesting(&input, observers, &exit_kind)?;
|
||||||
> 0;
|
Ok((is_interesting, is_solution))
|
||||||
Ok((fitness, is_solution))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_initial_inputs<CS, G, E, OT, EM>(
|
pub fn generate_initial_inputs<CS, G, E, OT, EM>(
|
||||||
@ -686,8 +686,8 @@ where
|
|||||||
let mut added = 0;
|
let mut added = 0;
|
||||||
for _ in 0..num {
|
for _ in 0..num {
|
||||||
let input = generator.generate(self.rand_mut())?;
|
let input = generator.generate(self.rand_mut())?;
|
||||||
let (fitness, _) = self.evaluate_input(input, executor, manager, scheduler)?;
|
let (is_interesting, _) = self.evaluate_input(input, executor, manager, scheduler)?;
|
||||||
if fitness > 0 {
|
if is_interesting {
|
||||||
added += 1;
|
added += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -703,16 +703,16 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(rand: R, corpus: C, feedbacks: FT, solutions: SC, objectives: OFT) -> Self {
|
pub fn new(rand: R, corpus: C, feedback: F, solutions: SC, objective: OF) -> Self {
|
||||||
Self {
|
Self {
|
||||||
rand,
|
rand,
|
||||||
executions: 0,
|
executions: 0,
|
||||||
start_time: Duration::from_millis(0),
|
start_time: Duration::from_millis(0),
|
||||||
metadata: SerdeAnyMap::default(),
|
metadata: SerdeAnyMap::default(),
|
||||||
corpus,
|
corpus,
|
||||||
feedbacks,
|
feedback,
|
||||||
solutions,
|
solutions,
|
||||||
objectives,
|
objective,
|
||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_frida"
|
name = "libafl_frida"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
authors = ["s1341 <github@shmarya.net>"]
|
authors = ["s1341 <github@shmarya.net>"]
|
||||||
description = "Frida backend library for LibAFL"
|
description = "Frida backend library for LibAFL"
|
||||||
documentation = "https://docs.rs/libafl_frida"
|
documentation = "https://docs.rs/libafl_frida"
|
||||||
@ -13,7 +13,7 @@ edition = "2018"
|
|||||||
cc = { version = "1.0", features = ["parallel"] }
|
cc = { version = "1.0", features = ["parallel"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.1.0", features = ["std", "libafl_derive"] }
|
libafl = { path = "../libafl", version = "0.2.0", features = ["std", "libafl_derive"] }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.1.0" }
|
libafl_targets = { path = "../libafl_targets", version = "0.1.0" }
|
||||||
nix = "0.20.0"
|
nix = "0.20.0"
|
||||||
libc = "0.2.92"
|
libc = "0.2.92"
|
||||||
|
@ -1687,18 +1687,18 @@ where
|
|||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<u32, Error> {
|
) -> Result<bool, Error> {
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_first_type::<AsanErrorsObserver>()
|
.match_first_type::<AsanErrorsObserver>()
|
||||||
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
||||||
match observer.errors() {
|
match observer.errors() {
|
||||||
None => Ok(0),
|
None => Ok(false),
|
||||||
Some(errors) => {
|
Some(errors) => {
|
||||||
if !errors.errors.is_empty() {
|
if !errors.errors.is_empty() {
|
||||||
self.errors = Some(errors.clone());
|
self.errors = Some(errors.clone());
|
||||||
Ok(1)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
Ok(0)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user