Configurations (#162)
* print sender id * storing sender id to env * executor in llmp handle_in_client * compile the lib * compiling generic_inmemory * fix forkserver * adapt from fuzzers * instrospection fix * exitkind in NewTestcase * fix libafl_frida * fix firda_libpng * send conf with Newtestcase event * bump to 0.4.0 * no_std fix * fmt * fix libfuzzer_libmozjpeg Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
parent
5c5a1cf2e9
commit
bdb5efbf5b
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "baby_fuzzer"
|
name = "baby_fuzzer"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "forkserver_simple"
|
name = "forkserver_simple"
|
||||||
version = "0.1.0"
|
version = "0.4.0"
|
||||||
authors = ["tokatoka <tokazerkje@outlook.com>"]
|
authors = ["tokatoka <tokazerkje@outlook.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "frida_libpng"
|
name = "frida_libpng"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
@ -24,8 +24,8 @@ which = "4.1"
|
|||||||
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression", "llmp_bind_public" ] } #, "llmp_small_maps", "llmp_debug"]}
|
libafl = { path = "../../libafl/", features = [ "std", "llmp_compression", "llmp_bind_public" ] } #, "llmp_small_maps", "llmp_debug"]}
|
||||||
capstone = "0.8.0"
|
capstone = "0.8.0"
|
||||||
frida-gum = { version = "0.5.2", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] }
|
frida-gum = { version = "0.5.2", features = [ "auto-download", "backtrace", "event-sink", "invocation-listener"] }
|
||||||
libafl_frida = { path = "../../libafl_frida", version = "0.3.2", features = ["cmplog"] }
|
libafl_frida = { path = "../../libafl_frida", version = "0.4.0", features = ["cmplog"] }
|
||||||
libafl_targets = { path = "../../libafl_targets", version = "0.3.2" , features = ["sancov_cmplog"] }
|
libafl_targets = { path = "../../libafl_targets", version = "0.4.0" , features = ["sancov_cmplog"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libloading = "0.7.0"
|
libloading = "0.7.0"
|
||||||
|
@ -20,8 +20,8 @@ use libafl::{
|
|||||||
QueueCorpusScheduler,
|
QueueCorpusScheduler,
|
||||||
},
|
},
|
||||||
executors::{
|
executors::{
|
||||||
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind,
|
inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasObservers,
|
||||||
HasExecHooksTuple, HasObservers, HasObserversHooks, ShadowExecutor,
|
ShadowExecutor,
|
||||||
},
|
},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
@ -65,7 +65,7 @@ where
|
|||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
base: TimeoutExecutor<InProcessExecutor<'a, H, I, OT, S>>,
|
base: TimeoutExecutor<InProcessExecutor<'a, H, I, OT, S>>,
|
||||||
/// Frida's dynamic rewriting engine
|
/// Frida's dynamic rewriting engine
|
||||||
@ -82,7 +82,7 @@ where
|
|||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
/// Instruct the target about the input and run
|
/// Instruct the target about the input and run
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -120,13 +120,13 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers<OT>
|
impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers<I, OT, S>
|
||||||
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
|
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -139,22 +139,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c, EM, FH, H, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z>
|
|
||||||
for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
|
|
||||||
where
|
|
||||||
FH: FridaHelper<'b>,
|
|
||||||
H: FnMut(&I) -> ExitKind,
|
|
||||||
I: Input + HasTargetBytes,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, 'c, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
|
impl<'a, 'b, 'c, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S>
|
||||||
where
|
where
|
||||||
FH: FridaHelper<'b>,
|
FH: FridaHelper<'b>,
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gum: &'a Gum,
|
gum: &'a Gum,
|
||||||
@ -205,6 +195,12 @@ pub fn main() {
|
|||||||
.required(true)
|
.required(true)
|
||||||
.index(3),
|
.index(3),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("configuration")
|
||||||
|
.required(false)
|
||||||
|
.value_name("CONF")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("output")
|
Arg::with_name("output")
|
||||||
.short("o")
|
.short("o")
|
||||||
@ -252,6 +248,10 @@ pub fn main() {
|
|||||||
&cores,
|
&cores,
|
||||||
matches.value_of("output"),
|
matches.value_of("output"),
|
||||||
broker_addr,
|
broker_addr,
|
||||||
|
matches
|
||||||
|
.value_of("configuration")
|
||||||
|
.unwrap_or("default launcher")
|
||||||
|
.to_string(),
|
||||||
)
|
)
|
||||||
.expect("An error occurred while fuzzing");
|
.expect("An error occurred while fuzzing");
|
||||||
}
|
}
|
||||||
@ -269,6 +269,7 @@ fn fuzz(
|
|||||||
_cores: &[usize],
|
_cores: &[usize],
|
||||||
_stdout_file: Option<&str>,
|
_stdout_file: Option<&str>,
|
||||||
_broker_addr: Option<SocketAddr>,
|
_broker_addr: Option<SocketAddr>,
|
||||||
|
_configuration: String,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
todo!("Example not supported on Windows");
|
todo!("Example not supported on Windows");
|
||||||
}
|
}
|
||||||
@ -286,6 +287,7 @@ unsafe fn fuzz(
|
|||||||
cores: &[usize],
|
cores: &[usize],
|
||||||
stdout_file: Option<&str>,
|
stdout_file: Option<&str>,
|
||||||
broker_addr: Option<SocketAddr>,
|
broker_addr: Option<SocketAddr>,
|
||||||
|
configuration: String,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
// 'While the stats are state, they are usually used in the broker - which is likely never restarted
|
||||||
let stats = MultiStats::new(|s| println!("{}", s));
|
let stats = MultiStats::new(|s| println!("{}", s));
|
||||||
@ -443,6 +445,7 @@ unsafe fn fuzz(
|
|||||||
};
|
};
|
||||||
|
|
||||||
Launcher::builder()
|
Launcher::builder()
|
||||||
|
.configuration(configuration)
|
||||||
.shmem_provider(shmem_provider)
|
.shmem_provider(shmem_provider)
|
||||||
.stats(stats)
|
.stats(stats)
|
||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fuzzbench"
|
name = "fuzzbench"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "generic_inmemory"
|
name = "generic_inmemory"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||||
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
|
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
|
||||||
abort();
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -233,6 +233,7 @@ pub fn main() {
|
|||||||
|
|
||||||
Launcher::builder()
|
Launcher::builder()
|
||||||
.shmem_provider(shmem_provider)
|
.shmem_provider(shmem_provider)
|
||||||
|
.configuration("launcher default".into())
|
||||||
.stats(stats)
|
.stats(stats)
|
||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(&cores)
|
.cores(&cores)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libmozjpeg"
|
name = "libfuzzer_libmozjpeg"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -60,7 +60,8 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
|
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
let (state, mut restarting_mgr) =
|
let (state, mut restarting_mgr) =
|
||||||
setup_restarting_mgr_std(stats, broker_port).expect("Failed to setup the restarter");
|
setup_restarting_mgr_std(stats, broker_port, "default".into())
|
||||||
|
.expect("Failed to setup the restarter");
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libpng"
|
name = "libfuzzer_libpng"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -54,17 +54,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
let stats = MultiStats::new(|s| println!("{}", s));
|
let stats = MultiStats::new(|s| println!("{}", s));
|
||||||
|
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) {
|
let (state, mut restarting_mgr) =
|
||||||
Ok(res) => res,
|
match setup_restarting_mgr_std(stats, broker_port, "default".into()) {
|
||||||
Err(err) => match err {
|
Ok(res) => res,
|
||||||
Error::ShuttingDown => {
|
Err(err) => match err {
|
||||||
return Ok(());
|
Error::ShuttingDown => {
|
||||||
}
|
return Ok(());
|
||||||
_ => {
|
}
|
||||||
panic!("Failed to setup the restarter: {}", err);
|
_ => {
|
||||||
}
|
panic!("Failed to setup the restarter: {}", err);
|
||||||
},
|
}
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libpng_launcher"
|
name = "libfuzzer_libpng_launcher"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -167,6 +167,7 @@ pub fn main() {
|
|||||||
|
|
||||||
Launcher::builder()
|
Launcher::builder()
|
||||||
.shmem_provider(shmem_provider)
|
.shmem_provider(shmem_provider)
|
||||||
|
.configuration("launcher default".into())
|
||||||
.stats(stats)
|
.stats(stats)
|
||||||
.run_client(&mut run_client)
|
.run_client(&mut run_client)
|
||||||
.cores(&cores)
|
.cores(&cores)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_reachability"
|
name = "libfuzzer_reachability"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
|
||||||
|
@ -51,17 +51,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
let stats = SimpleStats::new(|s| println!("{}", s));
|
let stats = SimpleStats::new(|s| println!("{}", s));
|
||||||
|
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) {
|
let (state, mut restarting_mgr) =
|
||||||
Ok(res) => res,
|
match setup_restarting_mgr_std(stats, broker_port, "default".into()) {
|
||||||
Err(err) => match err {
|
Ok(res) => res,
|
||||||
Error::ShuttingDown => {
|
Err(err) => match err {
|
||||||
return Ok(());
|
Error::ShuttingDown => {
|
||||||
}
|
return Ok(());
|
||||||
_ => {
|
}
|
||||||
panic!("Failed to setup the restarter: {}", err);
|
_ => {
|
||||||
}
|
panic!("Failed to setup the restarter: {}", err);
|
||||||
},
|
}
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_stb_image"
|
name = "libfuzzer_stb_image"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
|
@ -52,17 +52,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
let stats = MultiStats::new(|s| println!("{}", s));
|
let stats = MultiStats::new(|s| println!("{}", s));
|
||||||
|
|
||||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||||
let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) {
|
let (state, mut restarting_mgr) =
|
||||||
Ok(res) => res,
|
match setup_restarting_mgr_std(stats, broker_port, "default".into()) {
|
||||||
Err(err) => match err {
|
Ok(res) => res,
|
||||||
Error::ShuttingDown => {
|
Err(err) => match err {
|
||||||
return Ok(());
|
Error::ShuttingDown => {
|
||||||
}
|
return Ok(());
|
||||||
_ => {
|
}
|
||||||
panic!("Failed to setup the restarter: {}", err);
|
_ => {
|
||||||
}
|
panic!("Failed to setup the restarter: {}", err);
|
||||||
},
|
}
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
// We don't use the hitcounts (see the Cargo.toml, we use pcguard_edges)
|
// We don't use the hitcounts (see the Cargo.toml, we use pcguard_edges)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl"
|
name = "libafl"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
@ -53,7 +53,7 @@ path = "./examples/llmp_test/main.rs"
|
|||||||
required-features = ["std"]
|
required-features = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl_derive = { optional = true, path = "../libafl_derive", version = "0.3.2" }
|
libafl_derive = { optional = true, path = "../libafl_derive", version = "0.4.0" }
|
||||||
tuple_list = "0.1.2"
|
tuple_list = "0.1.2"
|
||||||
hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"] } # A faster hashmap, nostd compatible
|
hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"] } # A faster hashmap, nostd compatible
|
||||||
num = "0.4.0"
|
num = "0.4.0"
|
||||||
|
@ -46,13 +46,15 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
{
|
{
|
||||||
/// The ShmemProvider to use
|
/// The ShmemProvider to use
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
/// The stats instance to use
|
/// The stats instance to use
|
||||||
stats: ST,
|
stats: ST,
|
||||||
|
/// The configuration
|
||||||
|
configuration: String,
|
||||||
/// The 'main' function to run for each client forked. This probably shouldn't return
|
/// The 'main' function to run for each client forked. This probably shouldn't return
|
||||||
run_client: LauncherClientFnRef<'a, I, OT, S, SP>,
|
run_client: LauncherClientFnRef<'a, I, OT, S, SP>,
|
||||||
/// The broker port to use (or to attach to, in case [`Self::with_broker`] is `false`)
|
/// The broker port to use (or to attach to, in case [`Self::with_broker`] is `false`)
|
||||||
@ -79,7 +81,7 @@ where
|
|||||||
impl<'a, I, OT, S, SP, ST> Launcher<'a, I, OT, S, SP, ST>
|
impl<'a, I, OT, S, SP, ST> Launcher<'a, I, OT, S, SP, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
ST: Stats + Clone,
|
ST: Stats + Clone,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
@ -126,6 +128,7 @@ where
|
|||||||
.kind(ManagerKind::Client {
|
.kind(ManagerKind::Client {
|
||||||
cpu_core: Some(*bind_to),
|
cpu_core: Some(*bind_to),
|
||||||
})
|
})
|
||||||
|
.configuration(self.configuration.clone())
|
||||||
.build()
|
.build()
|
||||||
.launch()?;
|
.launch()?;
|
||||||
|
|
||||||
@ -140,13 +143,14 @@ where
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("I am broker!!.");
|
println!("I am broker!!.");
|
||||||
|
|
||||||
// TODO we don't want always a broker here, thing 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::<I, OT, S, SP, ST>::builder()
|
RestartingMgr::<I, OT, S, SP, ST>::builder()
|
||||||
.shmem_provider(self.shmem_provider.clone())
|
.shmem_provider(self.shmem_provider.clone())
|
||||||
.stats(Some(self.stats.clone()))
|
.stats(Some(self.stats.clone()))
|
||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.kind(ManagerKind::Broker)
|
.kind(ManagerKind::Broker)
|
||||||
.remote_broker_addr(self.remote_broker_addr)
|
.remote_broker_addr(self.remote_broker_addr)
|
||||||
|
.configuration(self.configuration.clone())
|
||||||
.build()
|
.build()
|
||||||
.launch()?;
|
.launch()?;
|
||||||
|
|
||||||
@ -191,6 +195,7 @@ where
|
|||||||
id: core_conf.parse()?,
|
id: core_conf.parse()?,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
.configuration(self.configuration.clone())
|
||||||
.build()
|
.build()
|
||||||
.launch()?;
|
.launch()?;
|
||||||
|
|
||||||
@ -246,6 +251,7 @@ where
|
|||||||
.broker_port(self.broker_port)
|
.broker_port(self.broker_port)
|
||||||
.kind(ManagerKind::Broker)
|
.kind(ManagerKind::Broker)
|
||||||
.remote_broker_addr(self.remote_broker_addr)
|
.remote_broker_addr(self.remote_broker_addr)
|
||||||
|
.configuration(self.configuration.clone())
|
||||||
.build()
|
.build()
|
||||||
.launch()?;
|
.launch()?;
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ unsafe fn _llmp_next_msg_ptr(last_msg: *const LlmpMsg) -> *mut LlmpMsg {
|
|||||||
/// May be used to restore the map by id.
|
/// May be used to restore the map by id.
|
||||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct LlmpDescription {
|
pub struct LlmpDescription {
|
||||||
/// Info about the SharedMap in use
|
/// Info about the ShredMap in use
|
||||||
shmem: ShMemDescription,
|
shmem: ShMemDescription,
|
||||||
/// The last message sent or received, depnding on page type
|
/// The last message sent or received, depnding on page type
|
||||||
last_message_offset: Option<u64>,
|
last_message_offset: Option<u64>,
|
||||||
@ -751,15 +751,36 @@ where
|
|||||||
self.last_msg_sent = ptr::null_mut();
|
self.last_msg_sent = ptr::null_mut();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads the stored sender / client id for the given `env_name` (by appending `_CLIENT_ID`).
|
||||||
|
/// If the content of the env is `_NULL`, returns [`Option::None`].
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[inline]
|
||||||
|
fn client_id_from_env(env_name: &str) -> Result<Option<ClientId>, Error> {
|
||||||
|
let client_id_str = env::var(&format!("{}_CLIENT_ID", env_name))?;
|
||||||
|
Ok(if client_id_str == _NULL_ENV_STR {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(client_id_str.parse()?)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes the `id` to an env var
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
fn client_id_to_env(env_name: &str, id: ClientId) {
|
||||||
|
env::set_var(&format!("{}_CLIENT_ID", env_name), &format!("{}", id));
|
||||||
|
}
|
||||||
|
|
||||||
/// Reattach to a vacant `out_map`, to with a previous sender stored the information in an env before.
|
/// Reattach to a vacant `out_map`, to with a previous sender stored the information in an env before.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn on_existing_from_env(mut shmem_provider: SP, env_name: &str) -> Result<Self, Error> {
|
pub fn on_existing_from_env(mut shmem_provider: SP, env_name: &str) -> Result<Self, Error> {
|
||||||
let msg_sent_offset = msg_offset_from_env(env_name)?;
|
let msg_sent_offset = msg_offset_from_env(env_name)?;
|
||||||
Self::on_existing_map(
|
let mut ret = Self::on_existing_map(
|
||||||
shmem_provider.clone(),
|
shmem_provider.clone(),
|
||||||
shmem_provider.existing_from_env(env_name)?,
|
shmem_provider.existing_from_env(env_name)?,
|
||||||
msg_sent_offset,
|
msg_sent_offset,
|
||||||
)
|
)?;
|
||||||
|
ret.id = Self::client_id_from_env(env_name)?.unwrap_or_default();
|
||||||
|
Ok(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Store the info to this sender to env.
|
/// Store the info to this sender to env.
|
||||||
@ -768,6 +789,7 @@ where
|
|||||||
pub fn to_env(&self, env_name: &str) -> Result<(), Error> {
|
pub fn to_env(&self, env_name: &str) -> Result<(), Error> {
|
||||||
let current_out_map = self.out_maps.last().unwrap();
|
let current_out_map = self.out_maps.last().unwrap();
|
||||||
current_out_map.shmem.write_to_env(env_name)?;
|
current_out_map.shmem.write_to_env(env_name)?;
|
||||||
|
Self::client_id_to_env(env_name, self.id);
|
||||||
unsafe { current_out_map.msg_to_env(self.last_msg_sent, env_name) }
|
unsafe { current_out_map.msg_to_env(self.last_msg_sent, env_name) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
//! LLMP-backed event manager for scalable multi-processed fuzzing
|
//! LLMP-backed event manager for scalable multi-processed fuzzing
|
||||||
|
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
|
vec::Vec,
|
||||||
|
};
|
||||||
use core::{marker::PhantomData, time::Duration};
|
use core::{marker::PhantomData, time::Duration};
|
||||||
use core_affinity::CoreId;
|
use core_affinity::CoreId;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
@ -23,9 +26,8 @@ use crate::{
|
|||||||
shmem::ShMemProvider,
|
shmem::ShMemProvider,
|
||||||
},
|
},
|
||||||
events::{BrokerEventResult, Event, EventFirer, EventManager, EventProcessor, EventRestarter},
|
events::{BrokerEventResult, Event, EventFirer, EventManager, EventProcessor, EventRestarter},
|
||||||
executors::Executor,
|
executors::{Executor, HasObservers},
|
||||||
executors::ExitKind,
|
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
||||||
fuzzer::{IfInteresting, IsInteresting},
|
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
stats::Stats,
|
stats::Stats,
|
||||||
@ -162,6 +164,7 @@ where
|
|||||||
Event::NewTestcase {
|
Event::NewTestcase {
|
||||||
input: _,
|
input: _,
|
||||||
client_config: _,
|
client_config: _,
|
||||||
|
exit_kind: _,
|
||||||
corpus_size,
|
corpus_size,
|
||||||
observers_buf: _,
|
observers_buf: _,
|
||||||
time,
|
time,
|
||||||
@ -245,20 +248,21 @@ where
|
|||||||
pub struct LlmpEventManager<I, OT, S, SP>
|
pub struct LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
llmp: llmp::LlmpClient<SP>,
|
llmp: llmp::LlmpClient<SP>,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
|
configuration: String,
|
||||||
phantom: PhantomData<(I, OT, S)>,
|
phantom: PhantomData<(I, OT, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP> Drop for LlmpEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> Drop for LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// LLMP clients will have to wait until their pages are mapped by somebody.
|
/// LLMP clients will have to wait until their pages are mapped by somebody.
|
||||||
@ -270,15 +274,16 @@ where
|
|||||||
impl<I, OT, S, SP> LlmpEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Create a manager from a raw llmp client
|
/// Create a manager from a raw llmp client
|
||||||
pub fn new(llmp: llmp::LlmpClient<SP>) -> Result<Self, Error> {
|
pub fn new(llmp: llmp::LlmpClient<SP>, configuration: String) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
llmp,
|
llmp,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
configuration,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -287,24 +292,32 @@ where
|
|||||||
/// If the port is not yet bound, it will act as broker
|
/// If the port is not yet bound, it will act as broker
|
||||||
/// Else, it will act as client.
|
/// Else, it will act as client.
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn new_on_port(shmem_provider: SP, port: u16) -> Result<Self, Error> {
|
pub fn new_on_port(
|
||||||
|
shmem_provider: SP,
|
||||||
|
port: u16,
|
||||||
|
configuration: String,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
llmp: llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?,
|
llmp: llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
|
configuration,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`].
|
/// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`].
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn existing_client_from_env(shmem_provider: SP, env_name: &str) -> Result<Self, Error> {
|
pub fn existing_client_from_env(
|
||||||
|
shmem_provider: SP,
|
||||||
|
env_name: &str,
|
||||||
|
configuration: String,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
llmp: LlmpClient::on_existing_from_env(shmem_provider, env_name)?,
|
llmp: LlmpClient::on_existing_from_env(shmem_provider, env_name)?,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
// Inserting a nop-stats element here so rust won't complain.
|
configuration,
|
||||||
// In any case, the client won't currently use it.
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -318,13 +331,13 @@ where
|
|||||||
pub fn existing_client_from_description(
|
pub fn existing_client_from_description(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
description: &LlmpClientDescription,
|
description: &LlmpClientDescription,
|
||||||
|
configuration: String,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
llmp: llmp::LlmpClient::existing_client_from_description(shmem_provider, description)?,
|
llmp: llmp::LlmpClient::existing_client_from_description(shmem_provider, description)?,
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::new(COMPRESS_THRESHOLD),
|
||||||
// Inserting a nop-stats element here so rust won't complain.
|
configuration,
|
||||||
// In any case, the client won't currently use it.
|
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -340,40 +353,41 @@ where
|
|||||||
fn handle_in_client<E, Z>(
|
fn handle_in_client<E, Z>(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
_executor: &mut E,
|
executor: &mut E,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
_sender_id: u32,
|
_sender_id: u32,
|
||||||
event: Event<I>,
|
event: Event<I>,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
E: Executor<Self, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
Z: IfInteresting<I, S> + IsInteresting<I, OT, S>,
|
E: Executor<Self, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
|
Z: ExecutionProcessor<I, OT, S> + EvaluatorObservers<I, OT, S>,
|
||||||
{
|
{
|
||||||
match event {
|
match event {
|
||||||
Event::NewTestcase {
|
Event::NewTestcase {
|
||||||
input,
|
input,
|
||||||
client_config: _,
|
client_config,
|
||||||
|
exit_kind,
|
||||||
corpus_size: _,
|
corpus_size: _,
|
||||||
observers_buf,
|
observers_buf,
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
} => {
|
} => {
|
||||||
// TODO: here u should match client_config, if equal to the current one do not re-execute
|
|
||||||
// we need to pass engine to process() too, TODO
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("Received new Testcase from {}", _sender_id);
|
println!(
|
||||||
|
"Received new Testcase from {} ({}) {:?}",
|
||||||
|
_sender_id, client_config, input
|
||||||
|
);
|
||||||
|
|
||||||
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
let res = if client_config == self.configuration {
|
||||||
// TODO include ExitKind in NewTestcase
|
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
||||||
// TODO check for objective too
|
fuzzer.process_execution(state, self, input, &observers, &exit_kind, false)?
|
||||||
let is_interesting =
|
} else {
|
||||||
fuzzer.is_interesting(state, self, &input, &observers, &ExitKind::Ok)?;
|
fuzzer.evaluate_input_with_observers(state, executor, self, input, false)?
|
||||||
if fuzzer
|
};
|
||||||
.add_if_interesting(state, &input, is_interesting)?
|
#[cfg(feature = "std")]
|
||||||
.is_some()
|
if let Some(item) = res.1 {
|
||||||
{
|
println!("Added received Testcase as item #{}", item);
|
||||||
#[cfg(feature = "std")]
|
|
||||||
println!("Added received Testcase");
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -388,7 +402,7 @@ where
|
|||||||
impl<I, OT, S, SP> EventFirer<I, S> for LlmpEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> EventFirer<I, S> for LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -418,12 +432,16 @@ where
|
|||||||
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
|
self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn configuration(&self) -> &str {
|
||||||
|
&self.configuration
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP> EventRestarter<S> for LlmpEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> EventRestarter<S> for LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -435,21 +453,25 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, I, OT, S, SP, Z> EventProcessor<E, S, Z> for LlmpEventManager<I, OT, S, SP>
|
impl<E, I, OT, S, SP, Z> EventProcessor<E, I, S, Z> for LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
E: Executor<Self, I, S, Z>,
|
E: Executor<Self, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
Z: IfInteresting<I, S> + IsInteresting<I, OT, S>, //CE: CustomEvent<I>,
|
Z: ExecutionProcessor<I, OT, S> + EvaluatorObservers<I, OT, S>, //CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
// TODO: Get around local event copy by moving handle_in_client
|
// TODO: Get around local event copy by moving handle_in_client
|
||||||
let mut events = vec![];
|
let mut events = vec![];
|
||||||
|
let self_id = self.llmp.sender.id;
|
||||||
while let Some((sender_id, tag, _flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
while let Some((sender_id, tag, _flags, msg)) = self.llmp.recv_buf_with_flags()? {
|
||||||
if tag == _LLMP_TAG_EVENT_TO_BROKER {
|
if tag == _LLMP_TAG_EVENT_TO_BROKER {
|
||||||
panic!("EVENT_TO_BROKER parcel should not have arrived in the client!");
|
panic!("EVENT_TO_BROKER parcel should not have arrived in the client!");
|
||||||
}
|
}
|
||||||
|
if sender_id == self_id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
#[cfg(not(feature = "llmp_compression"))]
|
||||||
let event_bytes = msg;
|
let event_bytes = msg;
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
@ -475,10 +497,10 @@ where
|
|||||||
impl<E, I, OT, S, SP, Z> EventManager<E, I, S, Z> for LlmpEventManager<I, OT, S, SP>
|
impl<E, I, OT, S, SP, Z> EventManager<E, I, S, Z> for LlmpEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
E: Executor<Self, I, S, Z>,
|
E: Executor<Self, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
Z: IfInteresting<I, S> + IsInteresting<I, OT, S>, //CE: CustomEvent<I>,
|
Z: ExecutionProcessor<I, OT, S> + EvaluatorObservers<I, OT, S>, //CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -491,7 +513,7 @@ pub fn serialize_state_mgr<I, OT, S, SP>(
|
|||||||
) -> Result<Vec<u8>, Error>
|
) -> Result<Vec<u8>, Error>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
@ -503,17 +525,22 @@ where
|
|||||||
pub fn deserialize_state_mgr<I, OT, S, SP>(
|
pub fn deserialize_state_mgr<I, OT, S, SP>(
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
state_corpus_serialized: &[u8],
|
state_corpus_serialized: &[u8],
|
||||||
|
configuration: String,
|
||||||
) -> Result<(S, LlmpEventManager<I, OT, S, SP>), Error>
|
) -> Result<(S, LlmpEventManager<I, OT, S, SP>), Error>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
let tuple: (S, _) = postcard::from_bytes(state_corpus_serialized)?;
|
let tuple: (S, _) = postcard::from_bytes(state_corpus_serialized)?;
|
||||||
Ok((
|
Ok((
|
||||||
tuple.0,
|
tuple.0,
|
||||||
LlmpEventManager::existing_client_from_description(shmem_provider, &tuple.1)?,
|
LlmpEventManager::existing_client_from_description(
|
||||||
|
shmem_provider,
|
||||||
|
&tuple.1,
|
||||||
|
configuration,
|
||||||
|
)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,7 +549,7 @@ where
|
|||||||
pub struct LlmpRestartingEventManager<I, OT, S, SP>
|
pub struct LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -535,7 +562,7 @@ where
|
|||||||
impl<I, OT, S, SP> EventFirer<I, S> for LlmpRestartingEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> EventFirer<I, S> for LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
@ -544,12 +571,16 @@ where
|
|||||||
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
// Check if we are going to crash in the event, in which case we store our current state for the next runner
|
||||||
self.llmp_mgr.fire(state, event)
|
self.llmp_mgr.fire(state, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn configuration(&self) -> &str {
|
||||||
|
self.llmp_mgr.configuration()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT, S, SP> EventRestarter<S> for LlmpRestartingEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> EventRestarter<S> for LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
@ -573,12 +604,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, I, OT, S, SP, Z> EventProcessor<E, S, Z> for LlmpRestartingEventManager<I, OT, S, SP>
|
impl<E, I, OT, S, SP, Z> EventProcessor<E, I, S, Z> for LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
E: Executor<LlmpEventManager<I, OT, S, SP>, I, S, Z>,
|
E: Executor<LlmpEventManager<I, OT, S, SP>, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
Z: IfInteresting<I, S> + IsInteresting<I, OT, S>,
|
Z: ExecutionProcessor<I, OT, S> + EvaluatorObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -589,11 +620,11 @@ where
|
|||||||
|
|
||||||
impl<E, I, OT, S, SP, Z> EventManager<E, I, S, Z> for LlmpRestartingEventManager<I, OT, S, SP>
|
impl<E, I, OT, S, SP, Z> EventManager<E, I, S, Z> for LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
E: Executor<LlmpEventManager<I, OT, S, SP>, I, S, Z>,
|
E: Executor<LlmpEventManager<I, OT, S, SP>, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
Z: IfInteresting<I, S> + IsInteresting<I, OT, S>,
|
Z: ExecutionProcessor<I, OT, S> + EvaluatorObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -608,7 +639,7 @@ const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
|||||||
impl<I, OT, S, SP> LlmpRestartingEventManager<I, OT, S, SP>
|
impl<I, OT, S, SP> LlmpRestartingEventManager<I, OT, S, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
//CE: CustomEvent<I>,
|
//CE: CustomEvent<I>,
|
||||||
{
|
{
|
||||||
@ -647,6 +678,7 @@ pub enum ManagerKind {
|
|||||||
pub fn setup_restarting_mgr_std<I, OT, S, ST>(
|
pub fn setup_restarting_mgr_std<I, OT, S, ST>(
|
||||||
stats: ST,
|
stats: ST,
|
||||||
broker_port: u16,
|
broker_port: u16,
|
||||||
|
configuration: String,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
(
|
(
|
||||||
Option<S>,
|
Option<S>,
|
||||||
@ -658,7 +690,7 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
ST: Stats + Clone,
|
ST: Stats + Clone,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
@ -668,6 +700,7 @@ where
|
|||||||
.shmem_provider(StdShMemProvider::new()?)
|
.shmem_provider(StdShMemProvider::new()?)
|
||||||
.stats(Some(stats))
|
.stats(Some(stats))
|
||||||
.broker_port(broker_port)
|
.broker_port(broker_port)
|
||||||
|
.configuration(configuration)
|
||||||
.build()
|
.build()
|
||||||
.launch()
|
.launch()
|
||||||
}
|
}
|
||||||
@ -681,7 +714,7 @@ where
|
|||||||
pub struct RestartingMgr<I, OT, S, SP, ST>
|
pub struct RestartingMgr<I, OT, S, SP, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
ST: Stats,
|
ST: Stats,
|
||||||
@ -690,6 +723,8 @@ where
|
|||||||
/// The shared memory provider to use for the broker or client spawned by the restarting
|
/// The shared memory provider to use for the broker or client spawned by the restarting
|
||||||
/// manager.
|
/// manager.
|
||||||
shmem_provider: SP,
|
shmem_provider: SP,
|
||||||
|
/// The configuration
|
||||||
|
configuration: String,
|
||||||
/// The stats to use
|
/// The stats to use
|
||||||
#[builder(default = None)]
|
#[builder(default = None)]
|
||||||
stats: Option<ST>,
|
stats: Option<ST>,
|
||||||
@ -711,7 +746,7 @@ where
|
|||||||
impl<I, OT, S, SP, ST> RestartingMgr<I, OT, S, SP, ST>
|
impl<I, OT, S, SP, ST> RestartingMgr<I, OT, S, SP, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
S: DeserializeOwned,
|
S: DeserializeOwned,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
ST: Stats + Clone,
|
ST: Stats + Clone,
|
||||||
@ -757,7 +792,10 @@ where
|
|||||||
return Err(Error::ShuttingDown);
|
return Err(Error::ShuttingDown);
|
||||||
}
|
}
|
||||||
LlmpConnection::IsClient { client } => {
|
LlmpConnection::IsClient { client } => {
|
||||||
let mgr = LlmpEventManager::<I, OT, S, SP>::new(client)?;
|
let mgr = LlmpEventManager::<I, OT, S, SP>::new(
|
||||||
|
client,
|
||||||
|
self.configuration.clone(),
|
||||||
|
)?;
|
||||||
(mgr, None)
|
(mgr, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -778,6 +816,7 @@ where
|
|||||||
let mgr = LlmpEventManager::<I, OT, S, SP>::new_on_port(
|
let mgr = LlmpEventManager::<I, OT, S, SP>::new_on_port(
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
self.broker_port,
|
self.broker_port,
|
||||||
|
self.configuration.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
(mgr, cpu_core)
|
(mgr, cpu_core)
|
||||||
@ -874,6 +913,7 @@ where
|
|||||||
let mgr = LlmpEventManager::<I, OT, S, SP>::existing_client_from_env(
|
let mgr = LlmpEventManager::<I, OT, S, SP>::existing_client_from_env(
|
||||||
new_shmem_provider,
|
new_shmem_provider,
|
||||||
_ENV_FUZZER_BROKER_CLIENT_INITIAL,
|
_ENV_FUZZER_BROKER_CLIENT_INITIAL,
|
||||||
|
self.configuration.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
(None, LlmpRestartingEventManager::new(mgr, sender))
|
(None, LlmpRestartingEventManager::new(mgr, sender))
|
||||||
@ -882,7 +922,7 @@ where
|
|||||||
Some((_sender, _tag, msg)) => {
|
Some((_sender, _tag, msg)) => {
|
||||||
println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len());
|
println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len());
|
||||||
let (state, mgr): (S, LlmpEventManager<I, OT, S, SP>) =
|
let (state, mgr): (S, LlmpEventManager<I, OT, S, SP>) =
|
||||||
deserialize_state_mgr(new_shmem_provider, msg)?;
|
deserialize_state_mgr(new_shmem_provider, msg, self.configuration.clone())?;
|
||||||
|
|
||||||
(Some(state), LlmpRestartingEventManager::new(mgr, sender))
|
(Some(state), LlmpRestartingEventManager::new(mgr, sender))
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@ use alloc::{string::String, vec::Vec};
|
|||||||
use core::{fmt, marker::PhantomData, time::Duration};
|
use core::{fmt, marker::PhantomData, time::Duration};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{inputs::Input, observers::ObserversTuple, stats::UserStats, Error};
|
use crate::{
|
||||||
|
executors::ExitKind, inputs::Input, observers::ObserversTuple, stats::UserStats, Error,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
use crate::stats::ClientPerfStats;
|
use crate::stats::ClientPerfStats;
|
||||||
@ -79,6 +81,8 @@ where
|
|||||||
input: I,
|
input: I,
|
||||||
/// The state of the observers when this testcase was found
|
/// The state of the observers when this testcase was found
|
||||||
observers_buf: Vec<u8>,
|
observers_buf: Vec<u8>,
|
||||||
|
/// The exit kind
|
||||||
|
exit_kind: ExitKind,
|
||||||
/// The new corpus size of this client
|
/// The new corpus size of this client
|
||||||
corpus_size: usize,
|
corpus_size: usize,
|
||||||
/// The client config for this observers/testcase combination
|
/// The client config for this observers/testcase combination
|
||||||
@ -151,6 +155,7 @@ where
|
|||||||
input: _,
|
input: _,
|
||||||
client_config: _,
|
client_config: _,
|
||||||
corpus_size: _,
|
corpus_size: _,
|
||||||
|
exit_kind: _,
|
||||||
observers_buf: _,
|
observers_buf: _,
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
@ -192,6 +197,19 @@ where
|
|||||||
{
|
{
|
||||||
/// Send off an event to the broker
|
/// Send off an event to the broker
|
||||||
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
|
fn fire(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Serialize all observers for this type and manager
|
||||||
|
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
||||||
|
where
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
Ok(postcard::to_allocvec(observers)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the configuration
|
||||||
|
fn configuration(&self) -> &str {
|
||||||
|
"<default>"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait EventRestarter<S> {
|
pub trait EventRestarter<S> {
|
||||||
@ -207,23 +225,15 @@ pub trait EventRestarter<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// [`EventProcessor`] process all the incoming messages
|
/// [`EventProcessor`] process all the incoming messages
|
||||||
pub trait EventProcessor<E, S, Z> {
|
pub trait EventProcessor<E, I, S, Z> {
|
||||||
/// Lookup for incoming events and process them.
|
/// Lookup for incoming events and process them.
|
||||||
/// Return the number of processes events or an error
|
/// Return the number of processes events or an error
|
||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error>;
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error>;
|
||||||
|
|
||||||
/// Serialize all observers for this type and manager
|
|
||||||
fn serialize_observers<OT>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
|
||||||
where
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
|
||||||
Ok(postcard::to_allocvec(observers)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize all observers for this type and manager
|
/// Deserialize all observers for this type and manager
|
||||||
fn deserialize_observers<OT>(&mut self, observers_buf: &[u8]) -> Result<OT, Error>
|
fn deserialize_observers<OT>(&mut self, observers_buf: &[u8]) -> Result<OT, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
Ok(postcard::from_bytes(observers_buf)?)
|
Ok(postcard::from_bytes(observers_buf)?)
|
||||||
}
|
}
|
||||||
@ -232,7 +242,7 @@ pub trait EventProcessor<E, S, Z> {
|
|||||||
/// [`EventManager`] is the main communications hub.
|
/// [`EventManager`] is the main communications hub.
|
||||||
/// For the "normal" multi-processed mode, you may want to look into `RestartingEventManager`
|
/// For the "normal" multi-processed mode, you may want to look into `RestartingEventManager`
|
||||||
pub trait EventManager<E, I, S, Z>:
|
pub trait EventManager<E, I, S, Z>:
|
||||||
EventFirer<I, S> + EventProcessor<E, S, Z> + EventRestarter<S>
|
EventFirer<I, S> + EventProcessor<E, I, S, Z> + EventRestarter<S>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
@ -253,7 +263,7 @@ where
|
|||||||
|
|
||||||
impl<S> EventRestarter<S> for NopEventManager {}
|
impl<S> EventRestarter<S> for NopEventManager {}
|
||||||
|
|
||||||
impl<E, S, Z> EventProcessor<E, S, Z> for NopEventManager {
|
impl<E, I, S, Z> EventProcessor<E, I, S, Z> for NopEventManager {
|
||||||
fn process(
|
fn process(
|
||||||
&mut self,
|
&mut self,
|
||||||
_fuzzer: &mut Z,
|
_fuzzer: &mut Z,
|
||||||
@ -277,6 +287,7 @@ mod tests {
|
|||||||
tuples::{tuple_list, Named},
|
tuples::{tuple_list, Named},
|
||||||
},
|
},
|
||||||
events::Event,
|
events::Event,
|
||||||
|
executors::ExitKind,
|
||||||
inputs::bytes::BytesInput,
|
inputs::bytes::BytesInput,
|
||||||
observers::StdMapObserver,
|
observers::StdMapObserver,
|
||||||
};
|
};
|
||||||
@ -293,6 +304,7 @@ mod tests {
|
|||||||
let e = Event::NewTestcase {
|
let e = Event::NewTestcase {
|
||||||
input: i,
|
input: i,
|
||||||
observers_buf,
|
observers_buf,
|
||||||
|
exit_kind: ExitKind::Ok,
|
||||||
corpus_size: 123,
|
corpus_size: 123,
|
||||||
client_config: "conf".into(),
|
client_config: "conf".into(),
|
||||||
time: current_time(),
|
time: current_time(),
|
||||||
@ -307,6 +319,7 @@ mod tests {
|
|||||||
input: _,
|
input: _,
|
||||||
observers_buf,
|
observers_buf,
|
||||||
corpus_size: _,
|
corpus_size: _,
|
||||||
|
exit_kind: _,
|
||||||
client_config: _,
|
client_config: _,
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
|
@ -69,7 +69,7 @@ where
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, I, S, ST, Z> EventProcessor<E, S, Z> for SimpleEventManager<I, ST>
|
impl<E, I, S, ST, Z> EventProcessor<E, I, S, Z> for SimpleEventManager<I, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
ST: Stats, //CE: CustomEvent<I, OT>,
|
ST: Stats, //CE: CustomEvent<I, OT>,
|
||||||
@ -116,6 +116,7 @@ where
|
|||||||
Event::NewTestcase {
|
Event::NewTestcase {
|
||||||
input: _,
|
input: _,
|
||||||
client_config: _,
|
client_config: _,
|
||||||
|
exit_kind: _,
|
||||||
corpus_size,
|
corpus_size,
|
||||||
observers_buf: _,
|
observers_buf: _,
|
||||||
time,
|
time,
|
||||||
@ -249,7 +250,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<E, I, S, SP, ST, Z> EventProcessor<E, S, Z> for SimpleRestartingEventManager<I, S, SP, ST>
|
impl<E, I, S, SP, ST, Z> EventProcessor<E, I, S, Z> for SimpleRestartingEventManager<I, S, SP, ST>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: Serialize,
|
S: Serialize,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! A `CombinedExecutor` wraps a primary executor and a secondary one
|
//! A `CombinedExecutor` wraps a primary executor and a secondary one
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
@ -52,10 +52,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, OT> HasObservers<OT> for CombinedExecutor<A, B>
|
impl<A, B, I, OT, S> HasObservers<I, OT, S> for CombinedExecutor<A, B>
|
||||||
where
|
where
|
||||||
A: HasObservers<OT>,
|
A: HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -67,11 +67,3 @@ where
|
|||||||
self.primary.observers_mut()
|
self.primary.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for CombinedExecutor<A, B>
|
|
||||||
where
|
|
||||||
A: HasObservers<OT>,
|
|
||||||
I: Input,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@ -13,7 +13,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::os::{dup2, pipes::Pipe},
|
bolts::os::{dup2, pipes::Pipe},
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
@ -411,23 +411,23 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This [`Executor`] can run binaries compiled for AFL/AFL++ that make use of a forkserver.
|
/// This [`Executor`] can run binaries compiled for AFL/AFL++ that make use of a forkserver.
|
||||||
pub struct ForkserverExecutor<I, OT>
|
pub struct ForkserverExecutor<I, OT, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
target: String,
|
target: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
out_file: OutFile,
|
out_file: OutFile,
|
||||||
forkserver: Forkserver,
|
forkserver: Forkserver,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<(I, S)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT> ForkserverExecutor<I, OT>
|
impl<I, OT, S> ForkserverExecutor<I, OT, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
pub fn new(target: String, arguments: &[String], observers: OT) -> Result<Self, Error> {
|
pub fn new(target: String, arguments: &[String], observers: OT) -> Result<Self, Error> {
|
||||||
let mut args = Vec::<String>::new();
|
let mut args = Vec::<String>::new();
|
||||||
@ -493,10 +493,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, I, OT, S, Z> Executor<EM, I, S, Z> for ForkserverExecutor<I, OT>
|
impl<EM, I, OT, S, Z> Executor<EM, I, S, Z> for ForkserverExecutor<I, OT, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
@ -554,10 +554,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, OT> HasObservers<OT> for ForkserverExecutor<I, OT>
|
impl<I, OT, S> HasObservers<I, OT, S> for ForkserverExecutor<I, OT, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -570,17 +570,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for ForkserverExecutor<I, OT>
|
impl<I, OT, S> HasForkserver for ForkserverExecutor<I, OT, S>
|
||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, OT> HasForkserver for ForkserverExecutor<I, OT>
|
|
||||||
where
|
|
||||||
I: Input + HasTargetBytes,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn forkserver(&self) -> &Forkserver {
|
fn forkserver(&self) -> &Forkserver {
|
||||||
@ -603,10 +596,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, OT> HasObservers<OT> for TimeoutForkserverExecutor<E>
|
impl<E, I, OT, S> HasObservers<I, OT, S> for TimeoutForkserverExecutor<E>
|
||||||
where
|
where
|
||||||
E: HasObservers<OT>,
|
E: HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -619,14 +612,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for TimeoutForkserverExecutor<E>
|
|
||||||
where
|
|
||||||
E: HasObservers<OT>,
|
|
||||||
I: Input,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -657,7 +642,7 @@ mod tests {
|
|||||||
&mut shmem_map,
|
&mut shmem_map,
|
||||||
));
|
));
|
||||||
|
|
||||||
let executor = ForkserverExecutor::<NopInput, _>::new(
|
let executor = ForkserverExecutor::<NopInput, _, ()>::new(
|
||||||
bin.to_string(),
|
bin.to_string(),
|
||||||
&args,
|
&args,
|
||||||
tuple_list!(edges_observer),
|
tuple_list!(edges_observer),
|
||||||
|
@ -23,7 +23,7 @@ pub use windows_exception_handler::{nop_handler, HandlerFuncPtr};
|
|||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
events::{EventFirer, EventRestarter},
|
events::{EventFirer, EventRestarter},
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
fuzzer::HasObjective,
|
fuzzer::HasObjective,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
@ -37,7 +37,7 @@ pub struct InProcessExecutor<'a, H, I, OT, S>
|
|||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
/// The harness function, being executed for each fuzzing loop execution
|
/// The harness function, being executed for each fuzzing loop execution
|
||||||
harness_fn: &'a mut H,
|
harness_fn: &'a mut H,
|
||||||
@ -56,7 +56,7 @@ impl<'a, EM, H, I, OT, S, Z> Executor<EM, I, S, Z> for InProcessExecutor<'a, H,
|
|||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn run_target(
|
fn run_target(
|
||||||
@ -130,11 +130,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, H, I, OT, S> HasObservers<OT> for InProcessExecutor<'a, H, I, OT, S>
|
impl<'a, H, I, OT, S> HasObservers<I, OT, S> for InProcessExecutor<'a, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -147,20 +147,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, EM, H, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z>
|
|
||||||
for InProcessExecutor<'a, H, I, OT, S>
|
|
||||||
where
|
|
||||||
H: FnMut(&I) -> ExitKind,
|
|
||||||
I: Input,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, H, I, OT, S> InProcessExecutor<'a, H, I, OT, S>
|
impl<'a, H, I, OT, S> InProcessExecutor<'a, H, I, OT, S>
|
||||||
where
|
where
|
||||||
H: FnMut(&I) -> ExitKind,
|
H: FnMut(&I) -> ExitKind,
|
||||||
I: Input,
|
I: Input,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
/// Create a new in mem executor.
|
/// Create a new in mem executor.
|
||||||
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
/// Caution: crash and restart in one of them will lead to odd behavior if multiple are used,
|
||||||
@ -349,7 +340,7 @@ mod unix_signal_handler {
|
|||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
EM: EventFirer<I, S> + EventRestarter<S>,
|
EM: EventFirer<I, S> + EventRestarter<S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OF: Feedback<I, S>,
|
OF: Feedback<I, S>,
|
||||||
S: HasSolutions<OC, I>,
|
S: HasSolutions<OC, I>,
|
||||||
@ -423,7 +414,7 @@ mod unix_signal_handler {
|
|||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
EM: EventFirer<I, S> + EventRestarter<S>,
|
EM: EventFirer<I, S> + EventRestarter<S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OF: Feedback<I, S>,
|
OF: Feedback<I, S>,
|
||||||
S: HasSolutions<OC, I>,
|
S: HasSolutions<OC, I>,
|
||||||
@ -634,7 +625,7 @@ mod windows_exception_handler {
|
|||||||
data: &mut InProcessExecutorHandlerData,
|
data: &mut InProcessExecutorHandlerData,
|
||||||
) where
|
) where
|
||||||
EM: EventFirer<I, S> + EventRestarter<S>,
|
EM: EventFirer<I, S> + EventRestarter<S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
OC: Corpus<I>,
|
OC: Corpus<I>,
|
||||||
OF: Feedback<I, S>,
|
OF: Feedback<I, S>,
|
||||||
S: HasSolutions<OC, I>,
|
S: HasSolutions<OC, I>,
|
||||||
|
@ -17,19 +17,15 @@ pub mod shadow;
|
|||||||
pub use shadow::{HasShadowObserverHooks, ShadowExecutor};
|
pub use shadow::{HasShadowObserverHooks, ShadowExecutor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::serdeany::SerdeAny,
|
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// A `CustomExitKind` for exits that do not fit to one of the default `ExitKind`.
|
|
||||||
pub trait CustomExitKind: core::fmt::Debug + SerdeAny + 'static {}
|
|
||||||
|
|
||||||
/// How an execution finished.
|
/// How an execution finished.
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub enum ExitKind {
|
pub enum ExitKind {
|
||||||
/// The run exited normally.
|
/// The run exited normally.
|
||||||
Ok,
|
Ok,
|
||||||
@ -39,112 +35,14 @@ pub enum ExitKind {
|
|||||||
Oom,
|
Oom,
|
||||||
/// The run timed out
|
/// The run timed out
|
||||||
Timeout,
|
Timeout,
|
||||||
/// The run resulted in a custom `ExitKind`.
|
// The run resulted in a custom `ExitKind`.
|
||||||
Custom(Box<dyn CustomExitKind>),
|
// Custom(Box<dyn SerdeAny>),
|
||||||
}
|
|
||||||
|
|
||||||
/// Pre and post exec hooks
|
|
||||||
pub trait HasExecHooks<EM, I, S, Z> {
|
|
||||||
/// Called right before exexution starts
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Called right after execution finished.
|
|
||||||
#[inline]
|
|
||||||
fn post_exec(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A haskell-style tuple of objects that have pre and post exec hooks
|
|
||||||
pub trait HasExecHooksTuple<EM, I, S, Z> {
|
|
||||||
/// This is called right before the next execution.
|
|
||||||
fn pre_exec_all(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
|
|
||||||
/// This is called right after the last execution
|
|
||||||
fn post_exec_all(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<EM, I, S, Z> HasExecHooksTuple<EM, I, S, Z> for () {
|
|
||||||
fn pre_exec_all(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_exec_all(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<EM, I, S, Z, Head, Tail> HasExecHooksTuple<EM, I, S, Z> for (Head, Tail)
|
|
||||||
where
|
|
||||||
Head: HasExecHooks<EM, I, S, Z>,
|
|
||||||
Tail: HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
fn pre_exec_all(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.0.pre_exec(fuzzer, state, mgr, input)?;
|
|
||||||
self.1.pre_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn post_exec_all(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.0.post_exec(fuzzer, state, mgr, input)?;
|
|
||||||
self.1.post_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds a tuple of Observers
|
/// Holds a tuple of Observers
|
||||||
pub trait HasObservers<OT>
|
pub trait HasObservers<I, OT, S>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
/// Get the linked observers
|
/// Get the linked observers
|
||||||
fn observers(&self) -> &OT;
|
fn observers(&self) -> &OT;
|
||||||
@ -153,37 +51,6 @@ where
|
|||||||
fn observers_mut(&mut self) -> &mut OT;
|
fn observers_mut(&mut self) -> &mut OT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute the exec hooks of the observers if they all implement [`HasExecHooks`].
|
|
||||||
pub trait HasObserversHooks<EM, I, OT, S, Z>: HasObservers<OT>
|
|
||||||
where
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
/// Run the pre exec hook for all [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.observers_mut().pre_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the post exec hook for all the [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
|
||||||
#[inline]
|
|
||||||
fn post_exec_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.observers_mut()
|
|
||||||
.post_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An executor takes the given inputs, and runs the harness/target.
|
/// An executor takes the given inputs, and runs the harness/target.
|
||||||
pub trait Executor<EM, I, S, Z>
|
pub trait Executor<EM, I, S, Z>
|
||||||
where
|
where
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
//! A `ShadowExecutor` wraps an executor to have shadow observer that will not be considered by the feedbacks and the manager
|
//! A `ShadowExecutor` wraps an executor to have shadow observer that will not be considered by the feedbacks and the manager
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
@ -28,36 +30,22 @@ pub trait HasShadowObserverHooks<EM, I, S, SOT, Z> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers
|
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers
|
||||||
pub struct ShadowExecutor<E, SOT> {
|
pub struct ShadowExecutor<E, I, S, SOT> {
|
||||||
executor: E,
|
executor: E,
|
||||||
shadow_observers: SOT,
|
shadow_observers: SOT,
|
||||||
// Enable the execution of the shadow observers hooks with the regular observers hooks
|
phantom: PhantomData<(I, S)>,
|
||||||
shadow_hooks: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, SOT> ShadowExecutor<E, SOT>
|
impl<E, I, S, SOT> ShadowExecutor<E, I, S, SOT>
|
||||||
where
|
where
|
||||||
SOT: ObserversTuple,
|
SOT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
||||||
pub fn new(executor: E, shadow_observers: SOT) -> Self {
|
pub fn new(executor: E, shadow_observers: SOT) -> Self {
|
||||||
Self {
|
Self {
|
||||||
executor,
|
executor,
|
||||||
shadow_observers,
|
shadow_observers,
|
||||||
shadow_hooks: false,
|
phantom: PhantomData,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new `ShadowExecutor`, wrapping the given `executor`.
|
|
||||||
pub fn with_shadow_hooks<EM, I, S, Z>(
|
|
||||||
executor: E,
|
|
||||||
shadow_observers: SOT,
|
|
||||||
shadow_hooks: bool,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
executor,
|
|
||||||
shadow_observers,
|
|
||||||
shadow_hooks,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,51 +58,13 @@ where
|
|||||||
pub fn shadow_observers_mut(&mut self) -> &mut SOT {
|
pub fn shadow_observers_mut(&mut self) -> &mut SOT {
|
||||||
&mut self.shadow_observers
|
&mut self.shadow_observers
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shadow_hooks(&self) -> &bool {
|
|
||||||
&self.shadow_hooks
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shadow_hooks_mut(&mut self) -> &mut bool {
|
|
||||||
&mut self.shadow_hooks
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, S, SOT, Z> HasShadowObserverHooks<EM, I, S, SOT, Z> for ShadowExecutor<E, SOT>
|
impl<E, EM, I, S, SOT, Z> Executor<EM, I, S, Z> for ShadowExecutor<E, I, S, SOT>
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec_shadow_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.shadow_observers
|
|
||||||
.pre_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn post_exec_shadow_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.shadow_observers
|
|
||||||
.post_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E, EM, I, S, SOT, Z> Executor<EM, I, S, Z> for ShadowExecutor<E, SOT>
|
|
||||||
where
|
where
|
||||||
E: Executor<EM, I, S, Z>,
|
E: Executor<EM, I, S, Z>,
|
||||||
I: Input,
|
I: Input,
|
||||||
SOT: ObserversTuple,
|
SOT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
fn run_target(
|
fn run_target(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -127,11 +77,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, OT, SOT> HasObservers<OT> for ShadowExecutor<E, SOT>
|
impl<E, I, OT, S, SOT> HasObservers<I, OT, S> for ShadowExecutor<E, I, S, SOT>
|
||||||
where
|
where
|
||||||
E: HasObservers<OT>,
|
E: HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
SOT: ObserversTuple,
|
SOT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -143,44 +93,3 @@ where
|
|||||||
self.executor.observers_mut()
|
self.executor.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, OT, S, SOT, Z> HasObserversHooks<EM, I, OT, S, Z> for ShadowExecutor<E, SOT>
|
|
||||||
where
|
|
||||||
E: HasObservers<OT>,
|
|
||||||
I: Input,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
/// Run the pre exec hook for all [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
|
||||||
#[inline]
|
|
||||||
fn pre_exec_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if self.shadow_hooks {
|
|
||||||
self.shadow_observers
|
|
||||||
.pre_exec_all(fuzzer, state, mgr, input)?;
|
|
||||||
}
|
|
||||||
self.observers_mut().pre_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run the post exec hook for all the [`crate::observers::Observer`]`s` linked to this [`Executor`].
|
|
||||||
#[inline]
|
|
||||||
fn post_exec_observers(
|
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if self.shadow_hooks {
|
|
||||||
self.shadow_observers
|
|
||||||
.post_exec_all(fuzzer, state, mgr, input)?;
|
|
||||||
}
|
|
||||||
self.observers_mut()
|
|
||||||
.post_exec_all(fuzzer, state, mgr, input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
Error,
|
Error,
|
||||||
@ -129,10 +129,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, OT> HasObservers<OT> for TimeoutExecutor<E>
|
impl<E, I, OT, S> HasObservers<I, OT, S> for TimeoutExecutor<E>
|
||||||
where
|
where
|
||||||
E: HasObservers<OT>,
|
E: HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers(&self) -> &OT {
|
fn observers(&self) -> &OT {
|
||||||
@ -144,11 +144,3 @@ where
|
|||||||
self.executor.observers_mut()
|
self.executor.observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, I, OT, S, Z> HasObserversHooks<EM, I, OT, S, Z> for TimeoutExecutor<E>
|
|
||||||
where
|
|
||||||
E: HasObservers<OT>,
|
|
||||||
I: Input,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
@ -22,9 +22,9 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// A [`MapFeedback`] that strives to maximize the map contents.
|
/// A [`MapFeedback`] that strives to maximize the map contents.
|
||||||
pub type MaxMapFeedback<FT, O, S, T> = MapFeedback<FT, O, MaxReducer, S, T>;
|
pub type MaxMapFeedback<FT, I, O, S, T> = MapFeedback<FT, I, O, MaxReducer, S, T>;
|
||||||
/// A [`MapFeedback`] that strives to minimize the map contents.
|
/// A [`MapFeedback`] that strives to minimize the map contents.
|
||||||
pub type MinMapFeedback<FT, O, S, T> = MapFeedback<FT, O, MinReducer, S, T>;
|
pub type MinMapFeedback<FT, I, O, S, T> = MapFeedback<FT, I, O, MinReducer, 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>: Serialize + serde::de::DeserializeOwned + 'static
|
pub trait Reducer<T>: Serialize + serde::de::DeserializeOwned + 'static
|
||||||
@ -185,7 +185,7 @@ where
|
|||||||
/// The most common AFL-like feedback type
|
/// The most common AFL-like feedback type
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||||
pub struct MapFeedback<FT, O, R, S, T>
|
pub struct MapFeedback<FT, I, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -202,10 +202,10 @@ where
|
|||||||
/// Name identifier of the observer
|
/// Name identifier of the observer
|
||||||
observer_name: String,
|
observer_name: String,
|
||||||
/// Phantom Data of Reducer
|
/// Phantom Data of Reducer
|
||||||
phantom: PhantomData<(FT, S, R, O, T)>,
|
phantom: PhantomData<(FT, I, S, R, O, T)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, FT, O, R, S, T> Feedback<I, S> for MapFeedback<FT, O, R, S, T>
|
impl<I, FT, O, R, S, T> Feedback<I, S> for MapFeedback<FT, I, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -224,7 +224,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let mut interesting = false;
|
let mut interesting = false;
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
@ -312,7 +312,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FT, O, R, S, T> Named for MapFeedback<FT, O, R, S, T>
|
impl<FT, I, O, R, S, T> Named for MapFeedback<FT, I, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -326,7 +326,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FT, O, R, S, T> MapFeedback<FT, O, R, S, T>
|
impl<FT, I, O, R, S, T> MapFeedback<FT, I, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
@ -441,7 +441,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers.match_name::<O>(&self.name).unwrap();
|
let observer = observers.match_name::<O>(&self.name).unwrap();
|
||||||
|
@ -40,7 +40,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple<I, S>;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@ -56,7 +56,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// Start a timer for this feedback
|
// Start a timer for this feedback
|
||||||
let start_time = crate::bolts::cpu::read_time_counter();
|
let start_time = crate::bolts::cpu::read_time_counter();
|
||||||
@ -168,7 +168,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
FL::is_pair_interesting(
|
FL::is_pair_interesting(
|
||||||
&mut self.first,
|
&mut self.first,
|
||||||
@ -194,7 +194,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
FL::is_pair_interesting_with_perf(
|
FL::is_pair_interesting_with_perf(
|
||||||
&mut self.first,
|
&mut self.first,
|
||||||
@ -241,7 +241,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple<I, S>;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
@ -258,7 +258,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple<I, S>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LogicEagerOr {}
|
pub struct LogicEagerOr {}
|
||||||
@ -287,7 +287,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
@ -308,7 +308,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = first.is_interesting_with_perf(
|
let a = first.is_interesting_with_perf(
|
||||||
@ -355,7 +355,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
if a {
|
if a {
|
||||||
@ -379,7 +379,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = first.is_interesting_with_perf(
|
let a = first.is_interesting_with_perf(
|
||||||
@ -429,7 +429,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
let b = second.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
@ -450,7 +450,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = first.is_interesting_with_perf(
|
let a = first.is_interesting_with_perf(
|
||||||
@ -497,7 +497,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
let a = first.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
if !a {
|
if !a {
|
||||||
@ -521,7 +521,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = first.is_interesting_with_perf(
|
let a = first.is_interesting_with_perf(
|
||||||
@ -596,7 +596,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
Ok(!self
|
Ok(!self
|
||||||
.first
|
.first
|
||||||
@ -707,7 +707,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
@ -738,7 +738,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
if let ExitKind::Crash = exit_kind {
|
if let ExitKind::Crash = exit_kind {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -787,7 +787,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
if let ExitKind::Timeout = exit_kind {
|
if let ExitKind::Timeout = exit_kind {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -841,7 +841,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
let observer = observers.match_name::<TimeObserver>(self.name()).unwrap();
|
let observer = observers.match_name::<TimeObserver>(self.name()).unwrap();
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
bolts::current_time,
|
bolts::current_time,
|
||||||
corpus::{Corpus, CorpusScheduler, Testcase},
|
corpus::{Corpus, CorpusScheduler, Testcase},
|
||||||
events::{Event, EventFirer, EventManager},
|
events::{Event, EventFirer, EventManager},
|
||||||
executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
mark_feature_time,
|
mark_feature_time,
|
||||||
@ -66,33 +66,44 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate if an input is interesting using the feedback
|
/// Evaluate if an input is interesting using the feedback
|
||||||
pub trait IsInteresting<I, OT, S>
|
pub trait ExecutionProcessor<I, OT, S>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// 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<EM>(
|
fn process_execution<EM>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: &I,
|
input: I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>;
|
EM: EventFirer<I, S>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add to the state if interesting
|
/// Evaluate an input modyfing the state of the fuzzer
|
||||||
pub trait IfInteresting<I, S> {
|
pub trait EvaluatorObservers<I, OT, S>: Sized
|
||||||
/// Adds this input to the corpus, if it's intersting, and return the index
|
where
|
||||||
fn add_if_interesting(
|
I: Input,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
{
|
||||||
|
/// Runs the input and triggers observers and feedback,
|
||||||
|
/// returns if is interesting an (option) the index of the new testcase in the corpus
|
||||||
|
fn evaluate_input_with_observers<E, EM>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
input: &I,
|
executor: &mut E,
|
||||||
is_interesting: bool,
|
manager: &mut EM,
|
||||||
) -> Result<Option<usize>, Error>;
|
input: I,
|
||||||
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error>
|
||||||
|
where
|
||||||
|
E: Executor<EM, I, S, Self> + HasObservers<I, OT, S>,
|
||||||
|
EM: EventManager<E, I, S, Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate an input modyfing the state of the fuzzer
|
/// Evaluate an input modyfing the state of the fuzzer
|
||||||
@ -105,7 +116,21 @@ pub trait Evaluator<E, EM, I, S> {
|
|||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: I,
|
input: I,
|
||||||
) -> Result<(bool, Option<usize>), Error>;
|
) -> Result<(ExecuteInputResult, Option<usize>), Error> {
|
||||||
|
self.evaluate_input_events(state, executor, manager, input, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs the input and triggers observers and feedback,
|
||||||
|
/// returns if is interesting an (option) the index of the new testcase in the corpus
|
||||||
|
/// This version has a boolean to decide if send events to the manager.
|
||||||
|
fn evaluate_input_events(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error>;
|
||||||
|
|
||||||
/// Runs the input and triggers observers and feedback.
|
/// Runs the input and triggers observers and feedback.
|
||||||
/// Adds an input, to the corpus even if it's not considered `interesting` by the `feedback`.
|
/// Adds an input, to the corpus even if it's not considered `interesting` by the `feedback`.
|
||||||
@ -200,9 +225,10 @@ pub trait Fuzzer<E, EM, I, S, ST> {
|
|||||||
) -> Result<Duration, Error>;
|
) -> Result<Duration, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum ExecuteInputResult {
|
pub enum ExecuteInputResult {
|
||||||
None,
|
None,
|
||||||
Interesting,
|
Corpus,
|
||||||
Solution,
|
Solution,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,97 +296,86 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, CS, F, I, OF, OT, S, SC> IsInteresting<I, OT, S> for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
impl<C, CS, F, I, OF, OT, S, SC> ExecutionProcessor<I, OT, S>
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
CS: CorpusScheduler<I, S>,
|
|
||||||
F: Feedback<I, S>,
|
|
||||||
I: Input,
|
|
||||||
OF: Feedback<I, S>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
S: HasCorpus<C, I>,
|
|
||||||
{
|
|
||||||
/// Evaluate if a set of observation channels has an interesting state
|
|
||||||
fn is_interesting<EM>(
|
|
||||||
&mut self,
|
|
||||||
state: &mut S,
|
|
||||||
manager: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
observers: &OT,
|
|
||||||
exit_kind: &ExitKind,
|
|
||||||
) -> Result<bool, Error>
|
|
||||||
where
|
|
||||||
EM: EventFirer<I, S>,
|
|
||||||
{
|
|
||||||
self.feedback_mut()
|
|
||||||
.is_interesting(state, manager, input, observers, exit_kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, CS, F, I, OF, OT, S, SC> IfInteresting<I, S> for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
|
||||||
where
|
|
||||||
C: Corpus<I>,
|
|
||||||
CS: CorpusScheduler<I, S>,
|
|
||||||
F: Feedback<I, S>,
|
|
||||||
I: Input,
|
|
||||||
OF: Feedback<I, S>,
|
|
||||||
OT: ObserversTuple,
|
|
||||||
S: HasCorpus<C, I>,
|
|
||||||
{
|
|
||||||
/// Adds this input to the corpus, if it's intersting, and return the index
|
|
||||||
#[inline]
|
|
||||||
fn add_if_interesting(
|
|
||||||
&mut self,
|
|
||||||
state: &mut S,
|
|
||||||
input: &I,
|
|
||||||
is_interesting: bool,
|
|
||||||
) -> Result<Option<usize>, Error> {
|
|
||||||
if is_interesting {
|
|
||||||
let mut testcase = Testcase::new(input.clone());
|
|
||||||
self.feedback_mut().append_metadata(state, &mut testcase)?;
|
|
||||||
let idx = state.corpus_mut().add(testcase)?;
|
|
||||||
self.scheduler_mut().on_add(state, idx)?;
|
|
||||||
Ok(Some(idx))
|
|
||||||
} else {
|
|
||||||
self.feedback_mut().discard_metadata(state, input)?;
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<C, CS, E, EM, F, I, OF, OT, S, SC> Evaluator<E, EM, I, S>
|
|
||||||
for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
|
SC: Corpus<I>,
|
||||||
CS: CorpusScheduler<I, S>,
|
CS: CorpusScheduler<I, S>,
|
||||||
E: Executor<EM, I, S, Self> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Self>,
|
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Self>,
|
|
||||||
EM: EventManager<E, I, S, Self>,
|
|
||||||
F: Feedback<I, S>,
|
F: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
OF: Feedback<I, S>,
|
OF: Feedback<I, S>,
|
||||||
S: HasExecutions + HasCorpus<C, I> + HasSolutions<SC, I> + HasClientPerfStats,
|
OT: ObserversTuple<I, S>,
|
||||||
SC: Corpus<I>,
|
S: HasCorpus<C, I> + HasSolutions<SC, I> + HasClientPerfStats + HasExecutions,
|
||||||
{
|
{
|
||||||
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
#[inline]
|
fn process_execution<EM>(
|
||||||
fn evaluate_input(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
executor: &mut E,
|
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: I,
|
input: I,
|
||||||
) -> Result<(bool, Option<usize>), Error> {
|
observers: &OT,
|
||||||
let result = self.execute_input(state, executor, manager, &input)?;
|
exit_kind: &ExitKind,
|
||||||
let observers = executor.observers();
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
{
|
||||||
|
let mut res = ExecuteInputResult::None;
|
||||||
|
|
||||||
match result {
|
start_timer!(state);
|
||||||
|
let is_solution = self
|
||||||
|
.objective_mut()
|
||||||
|
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
||||||
|
mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll);
|
||||||
|
|
||||||
|
if is_solution {
|
||||||
|
res = ExecuteInputResult::Solution;
|
||||||
|
} else {
|
||||||
|
#[cfg(not(feature = "introspection"))]
|
||||||
|
let is_corpus = self
|
||||||
|
.feedback_mut()
|
||||||
|
.is_interesting(state, manager, &input, observers, &exit_kind)?;
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
let is_corpus = {
|
||||||
|
// Init temporary feedback stats here. We can't use the typical pattern above
|
||||||
|
// since we need a `mut self` for `feedbacks_mut`, so we can't also hand a
|
||||||
|
// new `mut self` to `is_interesting_with_perf`. We use this stack
|
||||||
|
// variable to get the stats and then update the feedbacks directly
|
||||||
|
let mut feedback_stats = [0_u64; crate::stats::NUM_FEEDBACKS];
|
||||||
|
let feedback_index = 0;
|
||||||
|
let is_corpus = self.feedback_mut().is_interesting_with_perf(
|
||||||
|
state,
|
||||||
|
manager,
|
||||||
|
&input,
|
||||||
|
observers,
|
||||||
|
&exit_kind,
|
||||||
|
&mut feedback_stats,
|
||||||
|
feedback_index,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Update the feedback stats
|
||||||
|
state
|
||||||
|
.introspection_stats_mut()
|
||||||
|
.update_feedbacks(feedback_stats);
|
||||||
|
|
||||||
|
// Return the total fitness
|
||||||
|
is_corpus
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_corpus {
|
||||||
|
res = ExecuteInputResult::Corpus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match res {
|
||||||
ExecuteInputResult::None => {
|
ExecuteInputResult::None => {
|
||||||
self.feedback_mut().discard_metadata(state, &input)?;
|
self.feedback_mut().discard_metadata(state, &input)?;
|
||||||
self.objective_mut().discard_metadata(state, &input)?;
|
self.objective_mut().discard_metadata(state, &input)?;
|
||||||
Ok((false, None))
|
Ok((res, None))
|
||||||
}
|
}
|
||||||
ExecuteInputResult::Interesting => {
|
ExecuteInputResult::Corpus => {
|
||||||
// Not a solution
|
// Not a solution
|
||||||
self.objective_mut().discard_metadata(state, &input)?;
|
self.objective_mut().discard_metadata(state, &input)?;
|
||||||
|
|
||||||
@ -370,19 +385,22 @@ where
|
|||||||
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 = manager.serialize_observers(observers)?;
|
if send_events {
|
||||||
manager.fire(
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
state,
|
manager.fire(
|
||||||
Event::NewTestcase {
|
state,
|
||||||
input,
|
Event::NewTestcase {
|
||||||
observers_buf,
|
input,
|
||||||
corpus_size: state.corpus().count(),
|
observers_buf,
|
||||||
client_config: "TODO".into(),
|
exit_kind: exit_kind.clone(),
|
||||||
time: current_time(),
|
corpus_size: state.corpus().count(),
|
||||||
executions: *state.executions(),
|
client_config: manager.configuration().to_string(),
|
||||||
},
|
time: current_time(),
|
||||||
)?;
|
executions: *state.executions(),
|
||||||
Ok((true, Some(idx)))
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok((res, Some(idx)))
|
||||||
}
|
}
|
||||||
ExecuteInputResult::Solution => {
|
ExecuteInputResult::Solution => {
|
||||||
// Not interesting
|
// Not interesting
|
||||||
@ -392,17 +410,80 @@ where
|
|||||||
let mut testcase = Testcase::new(input);
|
let mut testcase = Testcase::new(input);
|
||||||
self.objective_mut().append_metadata(state, &mut testcase)?;
|
self.objective_mut().append_metadata(state, &mut testcase)?;
|
||||||
state.solutions_mut().add(testcase)?;
|
state.solutions_mut().add(testcase)?;
|
||||||
manager.fire(
|
|
||||||
state,
|
|
||||||
Event::Objective {
|
|
||||||
objective_size: state.solutions().count(),
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok((false, None))
|
if send_events {
|
||||||
|
manager.fire(
|
||||||
|
state,
|
||||||
|
Event::Objective {
|
||||||
|
objective_size: state.solutions().count(),
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((res, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, CS, F, I, OF, OT, S, SC> EvaluatorObservers<I, OT, S>
|
||||||
|
for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
CS: CorpusScheduler<I, S>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
F: Feedback<I, S>,
|
||||||
|
I: Input,
|
||||||
|
OF: Feedback<I, S>,
|
||||||
|
S: HasExecutions + HasCorpus<C, I> + HasSolutions<SC, I> + HasClientPerfStats,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
{
|
||||||
|
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
||||||
|
#[inline]
|
||||||
|
fn evaluate_input_with_observers<E, EM>(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error>
|
||||||
|
where
|
||||||
|
E: Executor<EM, I, S, Self> + HasObservers<I, OT, S>,
|
||||||
|
EM: EventManager<E, I, S, Self>,
|
||||||
|
{
|
||||||
|
let exit_kind = self.execute_input(state, executor, manager, &input)?;
|
||||||
|
let observers = executor.observers();
|
||||||
|
self.process_execution(state, manager, input, observers, &exit_kind, send_events)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, CS, E, EM, F, I, OF, OT, S, SC> Evaluator<E, EM, I, S>
|
||||||
|
for StdFuzzer<C, CS, F, I, OF, OT, S, SC>
|
||||||
|
where
|
||||||
|
C: Corpus<I>,
|
||||||
|
CS: CorpusScheduler<I, S>,
|
||||||
|
E: Executor<EM, I, S, Self> + HasObservers<I, OT, S>,
|
||||||
|
OT: ObserversTuple<I, S>,
|
||||||
|
EM: EventManager<E, I, S, Self>,
|
||||||
|
F: Feedback<I, S>,
|
||||||
|
I: Input,
|
||||||
|
OF: Feedback<I, S>,
|
||||||
|
S: HasExecutions + HasCorpus<C, I> + HasSolutions<SC, I> + HasClientPerfStats,
|
||||||
|
SC: Corpus<I>,
|
||||||
|
{
|
||||||
|
/// Process one input, adding to the respective corpuses if needed and firing the right events
|
||||||
|
#[inline]
|
||||||
|
fn evaluate_input_events(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
executor: &mut E,
|
||||||
|
manager: &mut EM,
|
||||||
|
input: I,
|
||||||
|
send_events: bool,
|
||||||
|
) -> Result<(ExecuteInputResult, Option<usize>), Error> {
|
||||||
|
self.evaluate_input_with_observers(state, executor, manager, input, send_events)
|
||||||
|
}
|
||||||
|
|
||||||
/// Adds an input, even if it's not conisered `interesting` by any of the executors
|
/// Adds an input, even if it's not conisered `interesting` by any of the executors
|
||||||
fn add_input(
|
fn add_input(
|
||||||
@ -412,7 +493,7 @@ where
|
|||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
input: I,
|
input: I,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
let _ = 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();
|
||||||
// Always consider this to be "interesting"
|
// Always consider this to be "interesting"
|
||||||
|
|
||||||
@ -431,8 +512,9 @@ where
|
|||||||
Event::NewTestcase {
|
Event::NewTestcase {
|
||||||
input,
|
input,
|
||||||
observers_buf,
|
observers_buf,
|
||||||
|
exit_kind,
|
||||||
corpus_size: state.corpus().count(),
|
corpus_size: state.corpus().count(),
|
||||||
client_config: "TODO".into(),
|
client_config: manager.configuration().to_string(),
|
||||||
time: current_time(),
|
time: current_time(),
|
||||||
executions: *state.executions(),
|
executions: *state.executions(),
|
||||||
},
|
},
|
||||||
@ -565,14 +647,13 @@ where
|
|||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
event_mgr: &mut EM,
|
event_mgr: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
) -> Result<ExecuteInputResult, Error>
|
) -> Result<ExitKind, Error>
|
||||||
where
|
where
|
||||||
E: Executor<EM, I, S, Self> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Self>,
|
E: Executor<EM, I, S, Self> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Self>,
|
OT: ObserversTuple<I, S>,
|
||||||
EM: EventManager<E, I, S, Self>,
|
|
||||||
{
|
{
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
executor.pre_exec_observers(self, state, event_mgr, input)?;
|
executor.observers_mut().pre_exec_all(state, input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
@ -582,57 +663,9 @@ where
|
|||||||
*state.executions_mut() += 1;
|
*state.executions_mut() += 1;
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
executor.post_exec_observers(self, state, event_mgr, input)?;
|
executor.observers_mut().post_exec_all(state, input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
||||||
|
|
||||||
let observers = executor.observers();
|
Ok(exit_kind)
|
||||||
|
|
||||||
start_timer!(state);
|
|
||||||
let is_solution = self
|
|
||||||
.objective_mut()
|
|
||||||
.is_interesting(state, event_mgr, input, observers, &exit_kind)?;
|
|
||||||
mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll);
|
|
||||||
|
|
||||||
if is_solution {
|
|
||||||
return Ok(ExecuteInputResult::Solution);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "introspection"))]
|
|
||||||
let is_interesting = self
|
|
||||||
.feedback_mut()
|
|
||||||
.is_interesting(state, event_mgr, &input, observers, &exit_kind)?;
|
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
|
||||||
let is_interesting = {
|
|
||||||
// Init temporary feedback stats here. We can't use the typical pattern above
|
|
||||||
// since we need a `mut self` for `feedbacks_mut`, so we can't also hand a
|
|
||||||
// new `mut self` to `is_interesting_with_perf`. We use this stack
|
|
||||||
// variable to get the stats and then update the feedbacks directly
|
|
||||||
let mut feedback_stats = [0_u64; crate::stats::NUM_FEEDBACKS];
|
|
||||||
let feedback_index = 0;
|
|
||||||
let is_interesting = self.feedback_mut().is_interesting_with_perf(
|
|
||||||
state,
|
|
||||||
event_mgr,
|
|
||||||
input,
|
|
||||||
observers,
|
|
||||||
&exit_kind,
|
|
||||||
&mut feedback_stats,
|
|
||||||
feedback_index,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Update the feedback stats
|
|
||||||
state
|
|
||||||
.introspection_stats_mut()
|
|
||||||
.update_feedbacks(feedback_stats);
|
|
||||||
|
|
||||||
// Return the total fitness
|
|
||||||
is_interesting
|
|
||||||
};
|
|
||||||
|
|
||||||
if is_interesting {
|
|
||||||
Ok(ExecuteInputResult::Interesting)
|
|
||||||
} else {
|
|
||||||
Ok(ExecuteInputResult::None)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{ownedref::OwnedRefMut, tuples::Named, AsSlice},
|
bolts::{ownedref::OwnedRefMut, tuples::Named, AsSlice},
|
||||||
executors::HasExecHooks,
|
|
||||||
observers::Observer,
|
observers::Observer,
|
||||||
state::HasMetadata,
|
state::HasMetadata,
|
||||||
Error,
|
Error,
|
||||||
@ -95,7 +94,7 @@ pub trait CmpMap: Serialize + DeserializeOwned {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A [`CmpObserver`] observes the traced comparisons during the current execution using a [`CmpMap`]
|
/// A [`CmpObserver`] observes the traced comparisons during the current execution using a [`CmpMap`]
|
||||||
pub trait CmpObserver<CM>: Observer
|
pub trait CmpObserver<CM, I, S>: Observer<I, S>
|
||||||
where
|
where
|
||||||
CM: CmpMap,
|
CM: CmpMap,
|
||||||
{
|
{
|
||||||
@ -110,7 +109,7 @@ where
|
|||||||
|
|
||||||
/// Add [`CmpValuesMetadata`] to the State including the logged values.
|
/// Add [`CmpValuesMetadata`] to the State including the logged values.
|
||||||
/// This routine does a basic loop filtering because loop index cmps are not interesting.
|
/// This routine does a basic loop filtering because loop index cmps are not interesting.
|
||||||
fn add_cmpvalues_meta<S>(&mut self, state: &mut S)
|
fn add_cmpvalues_meta(&mut self, state: &mut S)
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
{
|
{
|
||||||
@ -181,14 +180,14 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, CM> CmpObserver<CM> for StdCmpObserver<'a, CM>
|
impl<'a, CM, I, S> CmpObserver<CM, I, S> for StdCmpObserver<'a, CM>
|
||||||
where
|
where
|
||||||
CM: CmpMap,
|
CM: CmpMap,
|
||||||
{
|
{
|
||||||
/// 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 {
|
||||||
match &self.size {
|
match &self.size {
|
||||||
None => self.map().len(),
|
None => self.map.as_ref().len(),
|
||||||
Some(o) => *o.as_ref(),
|
Some(o) => *o.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -202,19 +201,11 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, CM> Observer for StdCmpObserver<'a, CM> where CM: CmpMap {}
|
impl<'a, CM, I, S> Observer<I, S> for StdCmpObserver<'a, CM>
|
||||||
|
|
||||||
impl<'a, CM, EM, I, S, Z> HasExecHooks<EM, I, S, Z> for StdCmpObserver<'a, CM>
|
|
||||||
where
|
where
|
||||||
CM: CmpMap,
|
CM: CmpMap,
|
||||||
{
|
{
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.map.as_mut().reset()?;
|
self.map.as_mut().reset()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,12 @@ use crate::{
|
|||||||
ownedref::{OwnedRefMut, OwnedSliceMut},
|
ownedref::{OwnedRefMut, OwnedSliceMut},
|
||||||
tuples::Named,
|
tuples::Named,
|
||||||
},
|
},
|
||||||
executors::HasExecHooks,
|
|
||||||
observers::Observer,
|
observers::Observer,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A [`MapObserver`] observes the static map, as oftentimes used for afl-like coverage information
|
/// A [`MapObserver`] observes the static map, as oftentimes used for afl-like coverage information
|
||||||
pub trait MapObserver<T>: Observer
|
pub trait MapObserver<T>: Named + serde::Serialize + serde::de::DeserializeOwned
|
||||||
where
|
where
|
||||||
T: Default + Copy,
|
T: Default + Copy,
|
||||||
{
|
{
|
||||||
@ -70,24 +69,13 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Observer for StdMapObserver<'a, T> where
|
impl<'a, I, S, T> Observer<I, S> for StdMapObserver<'a, T>
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, EM, I, S, T, Z> HasExecHooks<EM, I, S, Z> for StdMapObserver<'a, T>
|
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
Self: MapObserver<T>,
|
Self: MapObserver<T>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,24 +174,13 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T, const N: usize> Observer for ConstMapObserver<'a, T, N> where
|
impl<'a, I, S, T, const N: usize> Observer<I, S> for ConstMapObserver<'a, T, N>
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, EM, I, S, T, Z, const N: usize> HasExecHooks<EM, I, S, Z> for ConstMapObserver<'a, T, N>
|
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
Self: MapObserver<T>,
|
Self: MapObserver<T>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,23 +286,13 @@ where
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> Observer for VariableMapObserver<'a, T> where
|
impl<'a, I, S, T> Observer<I, S> for VariableMapObserver<'a, T>
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, EM, I, S, T, Z> HasExecHooks<EM, I, S, Z> for VariableMapObserver<'a, T>
|
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
|
Self: MapObserver<T>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.reset_map()
|
self.reset_map()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,36 +402,22 @@ static COUNT_CLASS_LOOKUP: [u8; 256] = [
|
|||||||
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl<M> Observer for HitcountsMapObserver<M> where M: MapObserver<u8> {}
|
impl<I, S, M> Observer<I, S> for HitcountsMapObserver<M>
|
||||||
|
|
||||||
impl<EM, I, S, M, Z> HasExecHooks<EM, I, S, Z> for HitcountsMapObserver<M>
|
|
||||||
where
|
where
|
||||||
M: MapObserver<u8> + HasExecHooks<EM, I, S, Z>,
|
M: MapObserver<u8> + Observer<I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
self.base.pre_exec(state, input)
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.base.pre_exec(fuzzer, state, mgr, input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn post_exec(
|
fn post_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
mgr: &mut EM,
|
|
||||||
input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let cnt = self.usable_count();
|
let cnt = self.usable_count();
|
||||||
for x in self.map_mut()[0..cnt].iter_mut() {
|
for x in self.map_mut()[0..cnt].iter_mut() {
|
||||||
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
*x = COUNT_CLASS_LOOKUP[*x as usize];
|
||||||
}
|
}
|
||||||
self.base.post_exec(fuzzer, state, mgr, input)
|
self.base.post_exec(state, input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,31 +15,65 @@ use crate::{
|
|||||||
current_time,
|
current_time,
|
||||||
tuples::{MatchName, Named},
|
tuples::{MatchName, Named},
|
||||||
},
|
},
|
||||||
executors::HasExecHooks,
|
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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: Named + serde::Serialize + serde::de::DeserializeOwned {
|
pub trait Observer<I, S>: Named + serde::Serialize + serde::de::DeserializeOwned {
|
||||||
/// The testcase finished execution, calculate any changes.
|
/// The testcase finished execution, calculate any changes.
|
||||||
/// Reserved for future use.
|
/// Reserved for future use.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn flush(&mut self) -> Result<(), Error> {
|
fn flush(&mut self) -> Result<(), Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Called right before exexution starts
|
||||||
|
#[inline]
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Called right after execution finished.
|
||||||
|
#[inline]
|
||||||
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A haskell-style tuple of observers
|
/// A haskell-style tuple of observers
|
||||||
pub trait ObserversTuple: MatchName + serde::Serialize + serde::de::DeserializeOwned {}
|
pub trait ObserversTuple<I, S>: MatchName + serde::Serialize + serde::de::DeserializeOwned {
|
||||||
|
/// This is called right before the next execution.
|
||||||
|
fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error>;
|
||||||
|
|
||||||
impl ObserversTuple for () {}
|
/// This is called right after the last execution
|
||||||
|
fn post_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error>;
|
||||||
|
}
|
||||||
|
|
||||||
impl<Head, Tail> ObserversTuple for (Head, Tail)
|
impl<I, S> ObserversTuple<I, S> for () {
|
||||||
|
fn pre_exec_all(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec_all(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Head, Tail, I, S> ObserversTuple<I, S> for (Head, Tail)
|
||||||
where
|
where
|
||||||
Head: Observer,
|
Head: Observer<I, S>,
|
||||||
Tail: ObserversTuple,
|
Tail: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
|
fn pre_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||||
|
self.0.pre_exec(state, input)?;
|
||||||
|
self.1.pre_exec_all(state, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_exec_all(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||||
|
self.0.post_exec(state, input)?;
|
||||||
|
self.1.post_exec_all(state, input)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple observer, just overlooking the runtime of the target.
|
/// A simple observer, just overlooking the runtime of the target.
|
||||||
@ -68,28 +102,14 @@ impl TimeObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Observer for TimeObserver {}
|
impl<I, S> Observer<I, S> for TimeObserver {
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
impl<EM, I, S, Z> HasExecHooks<EM, I, S, Z> for TimeObserver {
|
|
||||||
fn pre_exec(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.last_runtime = None;
|
self.last_runtime = None;
|
||||||
self.start_time = current_time();
|
self.start_time = current_time();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec(
|
fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.last_runtime = current_time().checked_sub(self.start_time);
|
self.last_runtime = current_time().checked_sub(self.start_time);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ use core::{marker::PhantomData, mem::drop};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
executors::{Executor, HasExecHooksTuple, HasObservers, HasObserversHooks, ShadowExecutor},
|
executors::{Executor, HasObservers, ShadowExecutor},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
mark_feature_time,
|
mark_feature_time,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
@ -21,8 +21,8 @@ pub struct TracingStage<C, EM, I, OT, S, TE, Z>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
TE: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
TE: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
tracer_executor: TE,
|
tracer_executor: TE,
|
||||||
@ -34,8 +34,8 @@ impl<E, C, EM, I, OT, S, TE, Z> Stage<E, EM, S, Z> for TracingStage<C, EM, I, OT
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
TE: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
TE: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -58,7 +58,8 @@ where
|
|||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
self.tracer_executor
|
self.tracer_executor
|
||||||
.pre_exec_observers(fuzzer, state, manager, &input)?;
|
.observers_mut()
|
||||||
|
.pre_exec_all(state, &input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
@ -72,7 +73,8 @@ where
|
|||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
self.tracer_executor
|
self.tracer_executor
|
||||||
.post_exec_observers(fuzzer, state, manager, &input)?;
|
.observers_mut()
|
||||||
|
.post_exec_all(state, &input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -83,8 +85,8 @@ impl<C, EM, I, OT, S, TE, Z> TracingStage<C, EM, I, OT, S, TE, Z>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
TE: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
TE: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
/// Creates a new default stage
|
/// Creates a new default stage
|
||||||
@ -103,21 +105,21 @@ pub struct ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z> {
|
|||||||
phantom: PhantomData<(C, E, EM, I, OT, S, SOT, Z)>,
|
phantom: PhantomData<(C, E, EM, I, OT, S, SOT, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, E, EM, I, OT, S, SOT, Z> Stage<ShadowExecutor<E, SOT>, EM, S, Z>
|
impl<C, E, EM, I, OT, S, SOT, Z> Stage<ShadowExecutor<E, I, S, SOT>, EM, S, Z>
|
||||||
for ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z>
|
for ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
SOT: ObserversTuple<I, S>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn perform(
|
fn perform(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
executor: &mut ShadowExecutor<E, SOT>,
|
executor: &mut ShadowExecutor<E, I, S, SOT>,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
corpus_idx: usize,
|
corpus_idx: usize,
|
||||||
@ -131,11 +133,11 @@ where
|
|||||||
.clone();
|
.clone();
|
||||||
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
mark_feature_time!(state, PerfFeature::GetInputFromCorpus);
|
||||||
|
|
||||||
let prev_shadow_hooks = *executor.shadow_hooks();
|
|
||||||
*executor.shadow_hooks_mut() = true;
|
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
executor.pre_exec_observers(fuzzer, state, manager, &input)?;
|
executor
|
||||||
|
.shadow_observers_mut()
|
||||||
|
.pre_exec_all(state, &input)?;
|
||||||
|
executor.observers_mut().pre_exec_all(state, &input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
mark_feature_time!(state, PerfFeature::PreExecObservers);
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
@ -145,11 +147,12 @@ where
|
|||||||
*state.executions_mut() += 1;
|
*state.executions_mut() += 1;
|
||||||
|
|
||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
executor.post_exec_observers(fuzzer, state, manager, &input)?;
|
executor
|
||||||
|
.shadow_observers_mut()
|
||||||
|
.post_exec_all(state, &input)?;
|
||||||
|
executor.observers_mut().post_exec_all(state, &input)?;
|
||||||
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
mark_feature_time!(state, PerfFeature::PostExecObservers);
|
||||||
|
|
||||||
*executor.shadow_hooks_mut() = prev_shadow_hooks;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,13 +161,13 @@ impl<C, E, EM, I, OT, S, SOT, Z> ShadowTracingStage<C, E, EM, I, OT, S, SOT, Z>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<EM, I, S, Z> + HasObservers<OT> + HasObserversHooks<EM, I, OT, S, Z>,
|
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
OT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
OT: ObserversTuple<I, S>,
|
||||||
SOT: ObserversTuple + HasExecHooksTuple<EM, I, S, Z>,
|
SOT: ObserversTuple<I, S>,
|
||||||
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
S: HasClientPerfStats + HasExecutions + HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
/// Creates a new default stage
|
/// Creates a new default stage
|
||||||
pub fn new(_executor: &mut ShadowExecutor<E, SOT>) -> Self {
|
pub fn new(_executor: &mut ShadowExecutor<E, I, S, SOT>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -14,9 +14,9 @@ use crate::{
|
|||||||
serdeany::{SerdeAny, SerdeAnyMap},
|
serdeany::{SerdeAny, SerdeAnyMap},
|
||||||
},
|
},
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
events::{Event, EventManager, LogSeverity},
|
events::{Event, EventFirer, LogSeverity},
|
||||||
feedbacks::FeedbackStatesTuple,
|
feedbacks::FeedbackStatesTuple,
|
||||||
fuzzer::Evaluator,
|
fuzzer::{Evaluator, ExecuteInputResult},
|
||||||
generators::Generator,
|
generators::Generator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
stats::ClientPerfStats,
|
stats::ClientPerfStats,
|
||||||
@ -385,9 +385,8 @@ where
|
|||||||
if forced {
|
if forced {
|
||||||
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
let _ = fuzzer.add_input(self, executor, manager, input)?;
|
||||||
} else {
|
} else {
|
||||||
let (is_interesting, _) =
|
let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
||||||
fuzzer.evaluate_input(self, executor, manager, input)?;
|
if res == ExecuteInputResult::None {
|
||||||
if !is_interesting {
|
|
||||||
println!("File {:?} was not interesting, skipped.", &path);
|
println!("File {:?} was not interesting, skipped.", &path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,7 +410,7 @@ where
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventFirer<I, Self>,
|
||||||
{
|
{
|
||||||
for in_dir in in_dirs {
|
for in_dir in in_dirs {
|
||||||
self.load_from_directory(fuzzer, executor, manager, in_dir, forced)?;
|
self.load_from_directory(fuzzer, executor, manager, in_dir, forced)?;
|
||||||
@ -424,7 +423,6 @@ where
|
|||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
manager.process(fuzzer, self, executor)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +438,7 @@ where
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventFirer<I, Self>,
|
||||||
{
|
{
|
||||||
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true)
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true)
|
||||||
}
|
}
|
||||||
@ -455,7 +453,7 @@ where
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventFirer<I, Self>,
|
||||||
{
|
{
|
||||||
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false)
|
self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false)
|
||||||
}
|
}
|
||||||
@ -481,13 +479,13 @@ where
|
|||||||
where
|
where
|
||||||
G: Generator<I, R>,
|
G: Generator<I, R>,
|
||||||
Z: Evaluator<E, EM, I, Self>,
|
Z: Evaluator<E, EM, I, Self>,
|
||||||
EM: EventManager<E, I, Self, Z>,
|
EM: EventFirer<I, Self>,
|
||||||
{
|
{
|
||||||
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 (is_interesting, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?;
|
||||||
if is_interesting {
|
if res != ExecuteInputResult::None {
|
||||||
added += 1;
|
added += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -499,7 +497,6 @@ where
|
|||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
manager.process(fuzzer, self, executor)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_cc"
|
name = "libafl_cc"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
||||||
description = "Commodity library to wrap compilers and link LibAFL"
|
description = "Commodity library to wrap compilers and link LibAFL"
|
||||||
documentation = "https://docs.rs/libafl_cc"
|
documentation = "https://docs.rs/libafl_cc"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_derive"
|
name = "libafl_derive"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
||||||
description = "Derive proc-macro crate for LibAFL"
|
description = "Derive proc-macro crate for LibAFL"
|
||||||
documentation = "https://docs.rs/libafl_derive"
|
documentation = "https://docs.rs/libafl_derive"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_frida"
|
name = "libafl_frida"
|
||||||
version = "0.3.2"
|
version = "0.4.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"
|
||||||
@ -19,8 +19,8 @@ cmplog = []
|
|||||||
cc = { version = "1.0", features = ["parallel"] }
|
cc = { version = "1.0", features = ["parallel"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.3.1", features = ["std", "libafl_derive"] }
|
libafl = { path = "../libafl", version = "0.4.0", features = ["std", "libafl_derive"] }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.3.2", features = ["sancov_cmplog"] }
|
libafl_targets = { path = "../libafl_targets", version = "0.4.0", features = ["sancov_cmplog"] }
|
||||||
nix = "0.20.0"
|
nix = "0.20.0"
|
||||||
libc = "0.2.92"
|
libc = "0.2.92"
|
||||||
hashbrown = "0.11"
|
hashbrown = "0.11"
|
||||||
|
@ -9,7 +9,7 @@ use libafl::{
|
|||||||
bolts::{ownedref::OwnedPtr, tuples::Named},
|
bolts::{ownedref::OwnedPtr, tuples::Named},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
events::EventFirer,
|
events::EventFirer,
|
||||||
executors::{ExitKind, HasExecHooks},
|
executors::ExitKind,
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
observers::{Observer, ObserversTuple},
|
observers::{Observer, ObserversTuple},
|
||||||
@ -447,16 +447,8 @@ pub struct AsanErrorsObserver {
|
|||||||
errors: OwnedPtr<Option<AsanErrors>>,
|
errors: OwnedPtr<Option<AsanErrors>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Observer for AsanErrorsObserver {}
|
impl<I, S> Observer<I, S> for AsanErrorsObserver {
|
||||||
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
impl<EM, I, S, Z> HasExecHooks<EM, I, S, Z> for AsanErrorsObserver {
|
|
||||||
fn pre_exec(
|
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if ASAN_ERRORS.is_some() {
|
if ASAN_ERRORS.is_some() {
|
||||||
ASAN_ERRORS.as_mut().unwrap().clear();
|
ASAN_ERRORS.as_mut().unwrap().clear();
|
||||||
@ -529,7 +521,7 @@ where
|
|||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
EM: EventFirer<I, S>,
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple<I, S>,
|
||||||
{
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<AsanErrorsObserver>("AsanErrors")
|
.match_name::<AsanErrorsObserver>("AsanErrors")
|
||||||
|
@ -1946,6 +1946,7 @@ impl AsanRuntime {
|
|||||||
let backtrace = Backtrace::new();
|
let backtrace = Backtrace::new();
|
||||||
|
|
||||||
let (stack_start, stack_end) = Self::current_stack();
|
let (stack_start, stack_end) = Self::current_stack();
|
||||||
|
#[allow(clippy::option_if_let_else)]
|
||||||
let error = if fault_address >= stack_start && fault_address < stack_end {
|
let error = if fault_address >= stack_start && fault_address < stack_end {
|
||||||
if insn.mnemonic().unwrap().starts_with('l') {
|
if insn.mnemonic().unwrap().starts_with('l') {
|
||||||
AsanError::StackOobRead((
|
AsanError::StackOobRead((
|
||||||
@ -1962,38 +1963,35 @@ impl AsanRuntime {
|
|||||||
backtrace,
|
backtrace,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(metadata) = self
|
||||||
#[allow(clippy::option_if_let_else)]
|
.allocator
|
||||||
if let Some(metadata) = self
|
.find_metadata(fault_address, self.regs[base_reg as usize])
|
||||||
.allocator
|
{
|
||||||
.find_metadata(fault_address, self.regs[base_reg as usize])
|
let asan_readwrite_error = AsanReadWriteError {
|
||||||
{
|
registers: self.regs,
|
||||||
let asan_readwrite_error = AsanReadWriteError {
|
pc: actual_pc,
|
||||||
registers: self.regs,
|
fault: (base_reg, index_reg, displacement as usize, fault_address),
|
||||||
pc: actual_pc,
|
metadata: metadata.clone(),
|
||||||
fault: (base_reg, index_reg, displacement as usize, fault_address),
|
backtrace,
|
||||||
metadata: metadata.clone(),
|
};
|
||||||
backtrace,
|
if insn.mnemonic().unwrap().starts_with('l') {
|
||||||
};
|
if metadata.freed {
|
||||||
if insn.mnemonic().unwrap().starts_with('l') {
|
AsanError::ReadAfterFree(asan_readwrite_error)
|
||||||
if metadata.freed {
|
|
||||||
AsanError::ReadAfterFree(asan_readwrite_error)
|
|
||||||
} else {
|
|
||||||
AsanError::OobRead(asan_readwrite_error)
|
|
||||||
}
|
|
||||||
} else if metadata.freed {
|
|
||||||
AsanError::WriteAfterFree(asan_readwrite_error)
|
|
||||||
} else {
|
} else {
|
||||||
AsanError::OobWrite(asan_readwrite_error)
|
AsanError::OobRead(asan_readwrite_error)
|
||||||
}
|
}
|
||||||
|
} else if metadata.freed {
|
||||||
|
AsanError::WriteAfterFree(asan_readwrite_error)
|
||||||
} else {
|
} else {
|
||||||
AsanError::Unknown((
|
AsanError::OobWrite(asan_readwrite_error)
|
||||||
self.regs,
|
|
||||||
actual_pc,
|
|
||||||
(base_reg, index_reg, displacement as usize, fault_address),
|
|
||||||
backtrace,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
AsanError::Unknown((
|
||||||
|
self.regs,
|
||||||
|
actual_pc,
|
||||||
|
(base_reg, index_reg, displacement as usize, fault_address),
|
||||||
|
backtrace,
|
||||||
|
))
|
||||||
};
|
};
|
||||||
AsanErrors::get_mut().report_error(error);
|
AsanErrors::get_mut().report_error(error);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_targets"
|
name = "libafl_targets"
|
||||||
version = "0.3.2"
|
version = "0.4.0"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>"]
|
||||||
description = "Common code for target instrumentation that can be used combined with LibAFL"
|
description = "Common code for target instrumentation that can be used combined with LibAFL"
|
||||||
documentation = "https://docs.rs/libafl_targets"
|
documentation = "https://docs.rs/libafl_targets"
|
||||||
@ -25,6 +25,6 @@ cc = { version = "1.0", features = ["parallel"] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rangemap = "0.1.10"
|
rangemap = "0.1.10"
|
||||||
libafl = { path = "../libafl", version = "0.3.2", features = [] }
|
libafl = { path = "../libafl", version = "0.4.0", features = [] }
|
||||||
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
|
||||||
serde-big-array = "0.3.2"
|
serde-big-array = "0.3.2"
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{ownedref::OwnedRefMut, tuples::Named},
|
bolts::{ownedref::OwnedRefMut, tuples::Named},
|
||||||
executors::HasExecHooks,
|
|
||||||
observers::{CmpMap, CmpObserver, CmpValues, Observer},
|
observers::{CmpMap, CmpObserver, CmpValues, Observer},
|
||||||
state::HasMetadata,
|
state::HasMetadata,
|
||||||
Error,
|
Error,
|
||||||
@ -146,11 +145,14 @@ pub struct CmpLogObserver<'a> {
|
|||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CmpObserver<CmpLogMap> for CmpLogObserver<'a> {
|
impl<'a, I, S> CmpObserver<CmpLogMap, I, S> for CmpLogObserver<'a>
|
||||||
|
where
|
||||||
|
S: 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 {
|
||||||
match &self.size {
|
match &self.size {
|
||||||
None => self.map().len(),
|
None => self.map.as_ref().len(),
|
||||||
Some(o) => *o.as_ref(),
|
Some(o) => *o.as_ref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,19 +166,12 @@ impl<'a> CmpObserver<CmpLogMap> for CmpLogObserver<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Observer for CmpLogObserver<'a> {}
|
impl<'a, I, S> Observer<I, S> for CmpLogObserver<'a>
|
||||||
|
|
||||||
impl<'a, EM, I, S, Z> HasExecHooks<EM, I, S, Z> for CmpLogObserver<'a>
|
|
||||||
where
|
where
|
||||||
S: HasMetadata,
|
S: HasMetadata,
|
||||||
|
Self: CmpObserver<CmpLogMap, I, S>,
|
||||||
{
|
{
|
||||||
fn pre_exec(
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
_state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
self.map.as_mut().reset()?;
|
self.map.as_mut().reset()?;
|
||||||
unsafe {
|
unsafe {
|
||||||
CMPLOG_ENABLED = 1;
|
CMPLOG_ENABLED = 1;
|
||||||
@ -184,13 +179,7 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn post_exec(
|
fn post_exec(&mut self, state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
_fuzzer: &mut Z,
|
|
||||||
state: &mut S,
|
|
||||||
_mgr: &mut EM,
|
|
||||||
_input: &I,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
CMPLOG_ENABLED = 0;
|
CMPLOG_ENABLED = 0;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_tests"
|
name = "libafl_tests"
|
||||||
version = "0.1.0"
|
version = "0.4.0"
|
||||||
authors = ["tokatoka <tokazerkje@outlook.com>"]
|
authors = ["tokatoka <tokazerkje@outlook.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user