diff --git a/fuzzers/baby_fuzzer/Cargo.toml b/fuzzers/baby_fuzzer/Cargo.toml index 1d8aedf13d..00f9d4401a 100644 --- a/fuzzers/baby_fuzzer/Cargo.toml +++ b/fuzzers/baby_fuzzer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "baby_fuzzer" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/forkserver_simple/Cargo.toml b/fuzzers/forkserver_simple/Cargo.toml index 6d6fe1ae89..d753b8f7f8 100644 --- a/fuzzers/forkserver_simple/Cargo.toml +++ b/fuzzers/forkserver_simple/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "forkserver_simple" -version = "0.1.0" +version = "0.4.0" authors = ["tokatoka "] edition = "2018" diff --git a/fuzzers/frida_libpng/Cargo.toml b/fuzzers/frida_libpng/Cargo.toml index cd4a2ee65c..c7835209c9 100644 --- a/fuzzers/frida_libpng/Cargo.toml +++ b/fuzzers/frida_libpng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "frida_libpng" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" 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"]} capstone = "0.8.0" 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_targets = { path = "../../libafl_targets", version = "0.3.2" , features = ["sancov_cmplog"] } +libafl_frida = { path = "../../libafl_frida", version = "0.4.0", features = ["cmplog"] } +libafl_targets = { path = "../../libafl_targets", version = "0.4.0" , features = ["sancov_cmplog"] } lazy_static = "1.4.0" libc = "0.2" libloading = "0.7.0" diff --git a/fuzzers/frida_libpng/src/fuzzer.rs b/fuzzers/frida_libpng/src/fuzzer.rs index c901b2e5fb..2908a64495 100644 --- a/fuzzers/frida_libpng/src/fuzzer.rs +++ b/fuzzers/frida_libpng/src/fuzzer.rs @@ -20,8 +20,8 @@ use libafl::{ QueueCorpusScheduler, }, executors::{ - inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, - HasExecHooksTuple, HasObservers, HasObserversHooks, ShadowExecutor, + inprocess::InProcessExecutor, timeout::TimeoutExecutor, Executor, ExitKind, HasObservers, + ShadowExecutor, }, feedback_or, feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback}, @@ -65,7 +65,7 @@ where FH: FridaHelper<'b>, H: FnMut(&I) -> ExitKind, I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { base: TimeoutExecutor>, /// Frida's dynamic rewriting engine @@ -82,7 +82,7 @@ where FH: FridaHelper<'b>, H: FnMut(&I) -> ExitKind, I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { /// Instruct the target about the input and run #[inline] @@ -120,13 +120,13 @@ where } } -impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers +impl<'a, 'b, 'c, FH, H, I, OT, S> HasObservers for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> where FH: FridaHelper<'b>, H: FnMut(&I) -> ExitKind, I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -139,22 +139,12 @@ where } } -impl<'a, 'b, 'c, EM, FH, H, I, OT, S, Z> HasObserversHooks - for FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> -where - FH: FridaHelper<'b>, - H: FnMut(&I) -> ExitKind, - I: Input + HasTargetBytes, - OT: ObserversTuple + HasExecHooksTuple, -{ -} - impl<'a, 'b, 'c, FH, H, I, OT, S> FridaInProcessExecutor<'a, 'b, 'c, FH, H, I, OT, S> where FH: FridaHelper<'b>, H: FnMut(&I) -> ExitKind, I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { pub fn new( gum: &'a Gum, @@ -205,6 +195,12 @@ pub fn main() { .required(true) .index(3), ) + .arg( + Arg::with_name("configuration") + .required(false) + .value_name("CONF") + .takes_value(true), + ) .arg( Arg::with_name("output") .short("o") @@ -252,6 +248,10 @@ pub fn main() { &cores, matches.value_of("output"), broker_addr, + matches + .value_of("configuration") + .unwrap_or("default launcher") + .to_string(), ) .expect("An error occurred while fuzzing"); } @@ -269,6 +269,7 @@ fn fuzz( _cores: &[usize], _stdout_file: Option<&str>, _broker_addr: Option, + _configuration: String, ) -> Result<(), ()> { todo!("Example not supported on Windows"); } @@ -286,6 +287,7 @@ unsafe fn fuzz( cores: &[usize], stdout_file: Option<&str>, broker_addr: Option, + configuration: String, ) -> Result<(), Error> { // 'While the stats are state, they are usually used in the broker - which is likely never restarted let stats = MultiStats::new(|s| println!("{}", s)); @@ -443,6 +445,7 @@ unsafe fn fuzz( }; Launcher::builder() + .configuration(configuration) .shmem_provider(shmem_provider) .stats(stats) .run_client(&mut run_client) diff --git a/fuzzers/fuzzbench/Cargo.toml b/fuzzers/fuzzbench/Cargo.toml index f44e86f079..b0c9fac9ed 100644 --- a/fuzzers/fuzzbench/Cargo.toml +++ b/fuzzers/fuzzbench/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "fuzzbench" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" build = "build.rs" diff --git a/fuzzers/generic_inmemory/Cargo.toml b/fuzzers/generic_inmemory/Cargo.toml index 1780bf34d9..3151acd764 100644 --- a/fuzzers/generic_inmemory/Cargo.toml +++ b/fuzzers/generic_inmemory/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "generic_inmemory" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/generic_inmemory/fuzz.c b/fuzzers/generic_inmemory/fuzz.c index 7eea9f3b30..3f4a38f939 100644 --- a/fuzzers/generic_inmemory/fuzz.c +++ b/fuzzers/generic_inmemory/fuzz.c @@ -3,7 +3,8 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd) - abort(); + return 1; + return 0; } /* diff --git a/fuzzers/generic_inmemory/src/lib.rs b/fuzzers/generic_inmemory/src/lib.rs index dc21430a8a..38eb6940ff 100644 --- a/fuzzers/generic_inmemory/src/lib.rs +++ b/fuzzers/generic_inmemory/src/lib.rs @@ -233,6 +233,7 @@ pub fn main() { Launcher::builder() .shmem_provider(shmem_provider) + .configuration("launcher default".into()) .stats(stats) .run_client(&mut run_client) .cores(&cores) diff --git a/fuzzers/libfuzzer_libmozjpeg/Cargo.toml b/fuzzers/libfuzzer_libmozjpeg/Cargo.toml index 6137d50894..dcb8892ba7 100644 --- a/fuzzers/libfuzzer_libmozjpeg/Cargo.toml +++ b/fuzzers/libfuzzer_libmozjpeg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfuzzer_libmozjpeg" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/libfuzzer_libmozjpeg/src/lib.rs b/fuzzers/libfuzzer_libmozjpeg/src/lib.rs index 7f68c7ed63..ab51f75dad 100644 --- a/fuzzers/libfuzzer_libmozjpeg/src/lib.rs +++ b/fuzzers/libfuzzer_libmozjpeg/src/lib.rs @@ -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. 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 let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; diff --git a/fuzzers/libfuzzer_libpng/Cargo.toml b/fuzzers/libfuzzer_libpng/Cargo.toml index ea42326b89..22c8fba04a 100644 --- a/fuzzers/libfuzzer_libpng/Cargo.toml +++ b/fuzzers/libfuzzer_libpng/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfuzzer_libpng" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/libfuzzer_libpng/src/lib.rs b/fuzzers/libfuzzer_libpng/src/lib.rs index 57d6d309b1..52741af001 100644 --- a/fuzzers/libfuzzer_libpng/src/lib.rs +++ b/fuzzers/libfuzzer_libpng/src/lib.rs @@ -54,17 +54,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re 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. - let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) { - Ok(res) => res, - Err(err) => match err { - Error::ShuttingDown => { - return Ok(()); - } - _ => { - panic!("Failed to setup the restarter: {}", err); - } - }, - }; + let (state, mut restarting_mgr) = + match setup_restarting_mgr_std(stats, broker_port, "default".into()) { + Ok(res) => res, + Err(err) => match err { + Error::ShuttingDown => { + return Ok(()); + } + _ => { + panic!("Failed to setup the restarter: {}", err); + } + }, + }; // Create an observation channel using the coverage map let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; diff --git a/fuzzers/libfuzzer_libpng_launcher/Cargo.toml b/fuzzers/libfuzzer_libpng_launcher/Cargo.toml index b8466488f2..9fdebf8089 100644 --- a/fuzzers/libfuzzer_libpng_launcher/Cargo.toml +++ b/fuzzers/libfuzzer_libpng_launcher/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfuzzer_libpng_launcher" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/libfuzzer_libpng_launcher/src/lib.rs index 996ec170bb..7d8acdf6e0 100644 --- a/fuzzers/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/libfuzzer_libpng_launcher/src/lib.rs @@ -167,6 +167,7 @@ pub fn main() { Launcher::builder() .shmem_provider(shmem_provider) + .configuration("launcher default".into()) .stats(stats) .run_client(&mut run_client) .cores(&cores) diff --git a/fuzzers/libfuzzer_reachability/Cargo.toml b/fuzzers/libfuzzer_reachability/Cargo.toml index c04a484e59..6febec092f 100644 --- a/fuzzers/libfuzzer_reachability/Cargo.toml +++ b/fuzzers/libfuzzer_reachability/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfuzzer_reachability" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" diff --git a/fuzzers/libfuzzer_reachability/src/lib.rs b/fuzzers/libfuzzer_reachability/src/lib.rs index 7c0141461f..095c7ecab4 100644 --- a/fuzzers/libfuzzer_reachability/src/lib.rs +++ b/fuzzers/libfuzzer_reachability/src/lib.rs @@ -51,17 +51,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re 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. - let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) { - Ok(res) => res, - Err(err) => match err { - Error::ShuttingDown => { - return Ok(()); - } - _ => { - panic!("Failed to setup the restarter: {}", err); - } - }, - }; + let (state, mut restarting_mgr) = + match setup_restarting_mgr_std(stats, broker_port, "default".into()) { + Ok(res) => res, + Err(err) => match err { + Error::ShuttingDown => { + return Ok(()); + } + _ => { + panic!("Failed to setup the restarter: {}", err); + } + }, + }; // Create an observation channel using the coverage map let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; diff --git a/fuzzers/libfuzzer_stb_image/Cargo.toml b/fuzzers/libfuzzer_stb_image/Cargo.toml index ea49909a65..f0249f03c1 100644 --- a/fuzzers/libfuzzer_stb_image/Cargo.toml +++ b/fuzzers/libfuzzer_stb_image/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfuzzer_stb_image" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] edition = "2018" build = "build.rs" diff --git a/fuzzers/libfuzzer_stb_image/src/main.rs b/fuzzers/libfuzzer_stb_image/src/main.rs index 16eb76ae28..503da528e6 100644 --- a/fuzzers/libfuzzer_stb_image/src/main.rs +++ b/fuzzers/libfuzzer_stb_image/src/main.rs @@ -52,17 +52,18 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re 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. - let (state, mut restarting_mgr) = match setup_restarting_mgr_std(stats, broker_port) { - Ok(res) => res, - Err(err) => match err { - Error::ShuttingDown => { - return Ok(()); - } - _ => { - panic!("Failed to setup the restarter: {}", err); - } - }, - }; + let (state, mut restarting_mgr) = + match setup_restarting_mgr_std(stats, broker_port, "default".into()) { + Ok(res) => res, + Err(err) => match err { + Error::ShuttingDown => { + return Ok(()); + } + _ => { + panic!("Failed to setup the restarter: {}", err); + } + }, + }; // Create an observation channel using the coverage map // We don't use the hitcounts (see the Cargo.toml, we use pcguard_edges) diff --git a/libafl/Cargo.toml b/libafl/Cargo.toml index 4b77be289e..0310a9b778 100644 --- a/libafl/Cargo.toml +++ b/libafl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi ", "Dominik Maier "] description = "Slot your own fuzzers together and extend their features using Rust" documentation = "https://docs.rs/libafl" @@ -53,7 +53,7 @@ path = "./examples/llmp_test/main.rs" required-features = ["std"] [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" hashbrown = { version = "0.9", features = ["serde", "ahash-compile-time-rng"] } # A faster hashmap, nostd compatible num = "0.4.0" diff --git a/libafl/src/bolts/launcher.rs b/libafl/src/bolts/launcher.rs index bcacf31796..2e7880b843 100644 --- a/libafl/src/bolts/launcher.rs +++ b/libafl/src/bolts/launcher.rs @@ -46,13 +46,15 @@ where I: Input, ST: Stats, SP: ShMemProvider + 'static, - OT: ObserversTuple, + OT: ObserversTuple, S: DeserializeOwned, { /// The ShmemProvider to use shmem_provider: SP, /// The stats instance to use stats: ST, + /// The configuration + configuration: String, /// The 'main' function to run for each client forked. This probably shouldn't return run_client: LauncherClientFnRef<'a, I, OT, S, SP>, /// 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> where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, ST: Stats + Clone, SP: ShMemProvider + 'static, S: DeserializeOwned, @@ -126,6 +128,7 @@ where .kind(ManagerKind::Client { cpu_core: Some(*bind_to), }) + .configuration(self.configuration.clone()) .build() .launch()?; @@ -140,13 +143,14 @@ where #[cfg(feature = "std")] 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::::builder() .shmem_provider(self.shmem_provider.clone()) .stats(Some(self.stats.clone())) .broker_port(self.broker_port) .kind(ManagerKind::Broker) .remote_broker_addr(self.remote_broker_addr) + .configuration(self.configuration.clone()) .build() .launch()?; @@ -191,6 +195,7 @@ where id: core_conf.parse()?, }), }) + .configuration(self.configuration.clone()) .build() .launch()?; @@ -246,6 +251,7 @@ where .broker_port(self.broker_port) .kind(ManagerKind::Broker) .remote_broker_addr(self.remote_broker_addr) + .configuration(self.configuration.clone()) .build() .launch()?; diff --git a/libafl/src/bolts/llmp.rs b/libafl/src/bolts/llmp.rs index 20584e7290..ff92c47379 100644 --- a/libafl/src/bolts/llmp.rs +++ b/libafl/src/bolts/llmp.rs @@ -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. #[derive(Copy, Clone, Debug, Serialize, Deserialize)] pub struct LlmpDescription { - /// Info about the SharedMap in use + /// Info about the ShredMap in use shmem: ShMemDescription, /// The last message sent or received, depnding on page type last_message_offset: Option, @@ -751,15 +751,36 @@ where 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, 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. #[cfg(feature = "std")] pub fn on_existing_from_env(mut shmem_provider: SP, env_name: &str) -> Result { 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.existing_from_env(env_name)?, 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. @@ -768,6 +789,7 @@ where pub fn to_env(&self, env_name: &str) -> Result<(), Error> { let current_out_map = self.out_maps.last().unwrap(); 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) } } diff --git a/libafl/src/events/llmp.rs b/libafl/src/events/llmp.rs index 56553bf7d6..699999f966 100644 --- a/libafl/src/events/llmp.rs +++ b/libafl/src/events/llmp.rs @@ -1,6 +1,9 @@ //! 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_affinity::CoreId; use serde::{de::DeserializeOwned, Serialize}; @@ -23,9 +26,8 @@ use crate::{ shmem::ShMemProvider, }, events::{BrokerEventResult, Event, EventFirer, EventManager, EventProcessor, EventRestarter}, - executors::Executor, - executors::ExitKind, - fuzzer::{IfInteresting, IsInteresting}, + executors::{Executor, HasObservers}, + fuzzer::{EvaluatorObservers, ExecutionProcessor}, inputs::Input, observers::ObserversTuple, stats::Stats, @@ -162,6 +164,7 @@ where Event::NewTestcase { input: _, client_config: _, + exit_kind: _, corpus_size, observers_buf: _, time, @@ -245,20 +248,21 @@ where pub struct LlmpEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider + 'static, //CE: CustomEvent, { llmp: llmp::LlmpClient, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor, + configuration: String, phantom: PhantomData<(I, OT, S)>, } impl Drop for LlmpEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider + 'static, { /// LLMP clients will have to wait until their pages are mapped by somebody. @@ -270,15 +274,16 @@ where impl LlmpEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider + 'static, { /// Create a manager from a raw llmp client - pub fn new(llmp: llmp::LlmpClient) -> Result { + pub fn new(llmp: llmp::LlmpClient, configuration: String) -> Result { Ok(Self { llmp, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::new(COMPRESS_THRESHOLD), + configuration, phantom: PhantomData, }) } @@ -287,24 +292,32 @@ where /// If the port is not yet bound, it will act as broker /// Else, it will act as client. #[cfg(feature = "std")] - pub fn new_on_port(shmem_provider: SP, port: u16) -> Result { + pub fn new_on_port( + shmem_provider: SP, + port: u16, + configuration: String, + ) -> Result { Ok(Self { llmp: llmp::LlmpClient::create_attach_to_tcp(shmem_provider, port)?, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::new(COMPRESS_THRESHOLD), + configuration, phantom: PhantomData, }) } /// If a client respawns, it may reuse the existing connection, previously stored by [`LlmpClient::to_env()`]. #[cfg(feature = "std")] - pub fn existing_client_from_env(shmem_provider: SP, env_name: &str) -> Result { + pub fn existing_client_from_env( + shmem_provider: SP, + env_name: &str, + configuration: String, + ) -> Result { Ok(Self { llmp: LlmpClient::on_existing_from_env(shmem_provider, env_name)?, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::new(COMPRESS_THRESHOLD), - // Inserting a nop-stats element here so rust won't complain. - // In any case, the client won't currently use it. + configuration, phantom: PhantomData, }) } @@ -318,13 +331,13 @@ where pub fn existing_client_from_description( shmem_provider: SP, description: &LlmpClientDescription, + configuration: String, ) -> Result { Ok(Self { llmp: llmp::LlmpClient::existing_client_from_description(shmem_provider, description)?, #[cfg(feature = "llmp_compression")] compressor: GzipCompressor::new(COMPRESS_THRESHOLD), - // Inserting a nop-stats element here so rust won't complain. - // In any case, the client won't currently use it. + configuration, phantom: PhantomData, }) } @@ -340,40 +353,41 @@ where fn handle_in_client( &mut self, fuzzer: &mut Z, - _executor: &mut E, + executor: &mut E, state: &mut S, _sender_id: u32, event: Event, ) -> Result<(), Error> where - E: Executor, - Z: IfInteresting + IsInteresting, + OT: ObserversTuple, + E: Executor + HasObservers, + Z: ExecutionProcessor + EvaluatorObservers, { match event { Event::NewTestcase { input, - client_config: _, + client_config, + exit_kind, corpus_size: _, observers_buf, time: _, 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")] - 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)?; - // TODO include ExitKind in NewTestcase - // TODO check for objective too - let is_interesting = - fuzzer.is_interesting(state, self, &input, &observers, &ExitKind::Ok)?; - if fuzzer - .add_if_interesting(state, &input, is_interesting)? - .is_some() - { - #[cfg(feature = "std")] - println!("Added received Testcase"); + let res = if client_config == self.configuration { + let observers: OT = postcard::from_bytes(&observers_buf)?; + fuzzer.process_execution(state, self, input, &observers, &exit_kind, false)? + } else { + fuzzer.evaluate_input_with_observers(state, executor, self, input, false)? + }; + #[cfg(feature = "std")] + if let Some(item) = res.1 { + println!("Added received Testcase as item #{}", item); } Ok(()) } @@ -388,7 +402,7 @@ where impl EventFirer for LlmpEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider, //CE: CustomEvent, { @@ -418,12 +432,16 @@ where self.llmp.send_buf(LLMP_TAG_EVENT_TO_BOTH, &serialized)?; Ok(()) } + + fn configuration(&self) -> &str { + &self.configuration + } } impl EventRestarter for LlmpEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider, //CE: CustomEvent, { @@ -435,21 +453,25 @@ where } } -impl EventProcessor for LlmpEventManager +impl EventProcessor for LlmpEventManager where SP: ShMemProvider, - E: Executor, + E: Executor + HasObservers, I: Input, - OT: ObserversTuple, - Z: IfInteresting + IsInteresting, //CE: CustomEvent, + OT: ObserversTuple, + Z: ExecutionProcessor + EvaluatorObservers, //CE: CustomEvent, { fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result { // TODO: Get around local event copy by moving handle_in_client 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()? { if tag == _LLMP_TAG_EVENT_TO_BROKER { panic!("EVENT_TO_BROKER parcel should not have arrived in the client!"); } + if sender_id == self_id { + continue; + } #[cfg(not(feature = "llmp_compression"))] let event_bytes = msg; #[cfg(feature = "llmp_compression")] @@ -475,10 +497,10 @@ where impl EventManager for LlmpEventManager where SP: ShMemProvider, - E: Executor, + E: Executor + HasObservers, I: Input, - OT: ObserversTuple, - Z: IfInteresting + IsInteresting, //CE: CustomEvent, + OT: ObserversTuple, + Z: ExecutionProcessor + EvaluatorObservers, //CE: CustomEvent, { } @@ -491,7 +513,7 @@ pub fn serialize_state_mgr( ) -> Result, Error> where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: Serialize, SP: ShMemProvider, { @@ -503,17 +525,22 @@ where pub fn deserialize_state_mgr( shmem_provider: SP, state_corpus_serialized: &[u8], + configuration: String, ) -> Result<(S, LlmpEventManager), Error> where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: DeserializeOwned, SP: ShMemProvider, { let tuple: (S, _) = postcard::from_bytes(state_corpus_serialized)?; Ok(( 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 where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider + 'static, //CE: CustomEvent, { @@ -535,7 +562,7 @@ where impl EventFirer for LlmpRestartingEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: Serialize, SP: ShMemProvider, //CE: CustomEvent, @@ -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 self.llmp_mgr.fire(state, event) } + + fn configuration(&self) -> &str { + self.llmp_mgr.configuration() + } } impl EventRestarter for LlmpRestartingEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: Serialize, SP: ShMemProvider, //CE: CustomEvent, @@ -573,12 +604,12 @@ where } } -impl EventProcessor for LlmpRestartingEventManager +impl EventProcessor for LlmpRestartingEventManager where - E: Executor, I, S, Z>, + E: Executor, I, S, Z> + HasObservers, I: Input, - Z: IfInteresting + IsInteresting, - OT: ObserversTuple, + Z: ExecutionProcessor + EvaluatorObservers, + OT: ObserversTuple, SP: ShMemProvider + 'static, //CE: CustomEvent, { @@ -589,11 +620,11 @@ where impl EventManager for LlmpRestartingEventManager where - E: Executor, I, S, Z>, + E: Executor, I, S, Z> + HasObservers, I: Input, S: Serialize, - Z: IfInteresting + IsInteresting, - OT: ObserversTuple, + Z: ExecutionProcessor + EvaluatorObservers, + OT: ObserversTuple, SP: ShMemProvider + 'static, //CE: CustomEvent, { @@ -608,7 +639,7 @@ const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT"; impl LlmpRestartingEventManager where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, SP: ShMemProvider + 'static, //CE: CustomEvent, { @@ -647,6 +678,7 @@ pub enum ManagerKind { pub fn setup_restarting_mgr_std( stats: ST, broker_port: u16, + configuration: String, ) -> Result< ( Option, @@ -658,7 +690,7 @@ where I: Input, S: DeserializeOwned, ST: Stats + Clone, - OT: ObserversTuple, + OT: ObserversTuple, S: DeserializeOwned, { #[cfg(target_os = "android")] @@ -668,6 +700,7 @@ where .shmem_provider(StdShMemProvider::new()?) .stats(Some(stats)) .broker_port(broker_port) + .configuration(configuration) .build() .launch() } @@ -681,7 +714,7 @@ where pub struct RestartingMgr where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: DeserializeOwned, SP: ShMemProvider + 'static, ST: Stats, @@ -690,6 +723,8 @@ where /// The shared memory provider to use for the broker or client spawned by the restarting /// manager. shmem_provider: SP, + /// The configuration + configuration: String, /// The stats to use #[builder(default = None)] stats: Option, @@ -711,7 +746,7 @@ where impl RestartingMgr where I: Input, - OT: ObserversTuple, + OT: ObserversTuple, S: DeserializeOwned, SP: ShMemProvider, ST: Stats + Clone, @@ -757,7 +792,10 @@ where return Err(Error::ShuttingDown); } LlmpConnection::IsClient { client } => { - let mgr = LlmpEventManager::::new(client)?; + let mgr = LlmpEventManager::::new( + client, + self.configuration.clone(), + )?; (mgr, None) } } @@ -778,6 +816,7 @@ where let mgr = LlmpEventManager::::new_on_port( self.shmem_provider.clone(), self.broker_port, + self.configuration.clone(), )?; (mgr, cpu_core) @@ -874,6 +913,7 @@ where let mgr = LlmpEventManager::::existing_client_from_env( new_shmem_provider, _ENV_FUZZER_BROKER_CLIENT_INITIAL, + self.configuration.clone(), )?; (None, LlmpRestartingEventManager::new(mgr, sender)) @@ -882,7 +922,7 @@ where Some((_sender, _tag, msg)) => { println!("Subsequent run. Let's load all data from shmem (received {} bytes from previous instance)", msg.len()); let (state, mgr): (S, LlmpEventManager) = - deserialize_state_mgr(new_shmem_provider, msg)?; + deserialize_state_mgr(new_shmem_provider, msg, self.configuration.clone())?; (Some(state), LlmpRestartingEventManager::new(mgr, sender)) } diff --git a/libafl/src/events/mod.rs b/libafl/src/events/mod.rs index bbbbfe1998..14b54afcd2 100644 --- a/libafl/src/events/mod.rs +++ b/libafl/src/events/mod.rs @@ -9,7 +9,9 @@ use alloc::{string::String, vec::Vec}; use core::{fmt, marker::PhantomData, time::Duration}; 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")] use crate::stats::ClientPerfStats; @@ -79,6 +81,8 @@ where input: I, /// The state of the observers when this testcase was found observers_buf: Vec, + /// The exit kind + exit_kind: ExitKind, /// The new corpus size of this client corpus_size: usize, /// The client config for this observers/testcase combination @@ -151,6 +155,7 @@ where input: _, client_config: _, corpus_size: _, + exit_kind: _, observers_buf: _, time: _, executions: _, @@ -192,6 +197,19 @@ where { /// Send off an event to the broker fn fire(&mut self, state: &mut S, event: Event) -> Result<(), Error>; + + /// Serialize all observers for this type and manager + fn serialize_observers(&mut self, observers: &OT) -> Result, Error> + where + OT: ObserversTuple, + { + Ok(postcard::to_allocvec(observers)?) + } + + /// Get the configuration + fn configuration(&self) -> &str { + "" + } } pub trait EventRestarter { @@ -207,23 +225,15 @@ pub trait EventRestarter { } /// [`EventProcessor`] process all the incoming messages -pub trait EventProcessor { +pub trait EventProcessor { /// Lookup for incoming events and process them. /// Return the number of processes events or an error fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result; - /// Serialize all observers for this type and manager - fn serialize_observers(&mut self, observers: &OT) -> Result, Error> - where - OT: ObserversTuple, - { - Ok(postcard::to_allocvec(observers)?) - } - /// Deserialize all observers for this type and manager fn deserialize_observers(&mut self, observers_buf: &[u8]) -> Result where - OT: ObserversTuple, + OT: ObserversTuple, { Ok(postcard::from_bytes(observers_buf)?) } @@ -232,7 +242,7 @@ pub trait EventProcessor { /// [`EventManager`] is the main communications hub. /// For the "normal" multi-processed mode, you may want to look into `RestartingEventManager` pub trait EventManager: - EventFirer + EventProcessor + EventRestarter + EventFirer + EventProcessor + EventRestarter where I: Input, { @@ -253,7 +263,7 @@ where impl EventRestarter for NopEventManager {} -impl EventProcessor for NopEventManager { +impl EventProcessor for NopEventManager { fn process( &mut self, _fuzzer: &mut Z, @@ -277,6 +287,7 @@ mod tests { tuples::{tuple_list, Named}, }, events::Event, + executors::ExitKind, inputs::bytes::BytesInput, observers::StdMapObserver, }; @@ -293,6 +304,7 @@ mod tests { let e = Event::NewTestcase { input: i, observers_buf, + exit_kind: ExitKind::Ok, corpus_size: 123, client_config: "conf".into(), time: current_time(), @@ -307,6 +319,7 @@ mod tests { input: _, observers_buf, corpus_size: _, + exit_kind: _, client_config: _, time: _, executions: _, diff --git a/libafl/src/events/simple.rs b/libafl/src/events/simple.rs index 82975e034b..e20c31f8dd 100644 --- a/libafl/src/events/simple.rs +++ b/libafl/src/events/simple.rs @@ -69,7 +69,7 @@ where { } -impl EventProcessor for SimpleEventManager +impl EventProcessor for SimpleEventManager where I: Input, ST: Stats, //CE: CustomEvent, @@ -116,6 +116,7 @@ where Event::NewTestcase { input: _, client_config: _, + exit_kind: _, corpus_size, observers_buf: _, time, @@ -249,7 +250,7 @@ where } #[cfg(feature = "std")] -impl EventProcessor for SimpleRestartingEventManager +impl EventProcessor for SimpleRestartingEventManager where I: Input, S: Serialize, diff --git a/libafl/src/executors/combined.rs b/libafl/src/executors/combined.rs index 9d1b3225e8..49ebb294dc 100644 --- a/libafl/src/executors/combined.rs +++ b/libafl/src/executors/combined.rs @@ -1,7 +1,7 @@ //! A `CombinedExecutor` wraps a primary executor and a secondary one use crate::{ - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, inputs::Input, observers::ObserversTuple, Error, @@ -52,10 +52,10 @@ where } } -impl HasObservers for CombinedExecutor +impl HasObservers for CombinedExecutor where - A: HasObservers, - OT: ObserversTuple, + A: HasObservers, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -67,11 +67,3 @@ where self.primary.observers_mut() } } - -impl HasObserversHooks for CombinedExecutor -where - A: HasObservers, - I: Input, - OT: ObserversTuple + HasExecHooksTuple, -{ -} diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index d92df92c5b..13460509c3 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -13,7 +13,7 @@ use std::{ use crate::{ bolts::os::{dup2, pipes::Pipe}, - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, inputs::{HasTargetBytes, Input}, observers::ObserversTuple, Error, @@ -411,23 +411,23 @@ where } /// This [`Executor`] can run binaries compiled for AFL/AFL++ that make use of a forkserver. -pub struct ForkserverExecutor +pub struct ForkserverExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { target: String, args: Vec, out_file: OutFile, forkserver: Forkserver, observers: OT, - phantom: PhantomData, + phantom: PhantomData<(I, S)>, } -impl ForkserverExecutor +impl ForkserverExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { pub fn new(target: String, arguments: &[String], observers: OT) -> Result { let mut args = Vec::::new(); @@ -493,10 +493,10 @@ where } } -impl Executor for ForkserverExecutor +impl Executor for ForkserverExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn run_target( @@ -554,10 +554,10 @@ where } } -impl HasObservers for ForkserverExecutor +impl HasObservers for ForkserverExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -570,17 +570,10 @@ where } } -impl HasObserversHooks for ForkserverExecutor +impl HasForkserver for ForkserverExecutor where I: Input + HasTargetBytes, - OT: ObserversTuple + HasExecHooksTuple, -{ -} - -impl HasForkserver for ForkserverExecutor -where - I: Input + HasTargetBytes, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn forkserver(&self) -> &Forkserver { @@ -603,10 +596,10 @@ where } } -impl HasObservers for TimeoutForkserverExecutor +impl HasObservers for TimeoutForkserverExecutor where - E: HasObservers, - OT: ObserversTuple, + E: HasObservers, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -619,14 +612,6 @@ where } } -impl HasObserversHooks for TimeoutForkserverExecutor -where - E: HasObservers, - I: Input, - OT: ObserversTuple + HasExecHooksTuple, -{ -} - #[cfg(test)] mod tests { use crate::{ @@ -657,7 +642,7 @@ mod tests { &mut shmem_map, )); - let executor = ForkserverExecutor::::new( + let executor = ForkserverExecutor::::new( bin.to_string(), &args, tuple_list!(edges_observer), diff --git a/libafl/src/executors/inprocess.rs b/libafl/src/executors/inprocess.rs index d46d30a337..f68ee24c72 100644 --- a/libafl/src/executors/inprocess.rs +++ b/libafl/src/executors/inprocess.rs @@ -23,7 +23,7 @@ pub use windows_exception_handler::{nop_handler, HandlerFuncPtr}; use crate::{ corpus::Corpus, events::{EventFirer, EventRestarter}, - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, feedbacks::Feedback, fuzzer::HasObjective, inputs::Input, @@ -37,7 +37,7 @@ pub struct InProcessExecutor<'a, H, I, OT, S> where H: FnMut(&I) -> ExitKind, I: Input, - OT: ObserversTuple, + OT: ObserversTuple, { /// The harness function, being executed for each fuzzing loop execution harness_fn: &'a mut H, @@ -56,7 +56,7 @@ impl<'a, EM, H, I, OT, S, Z> Executor for InProcessExecutor<'a, H, where H: FnMut(&I) -> ExitKind, I: Input, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn run_target( @@ -130,11 +130,11 @@ where } } -impl<'a, H, I, OT, S> HasObservers for InProcessExecutor<'a, H, I, OT, S> +impl<'a, H, I, OT, S> HasObservers for InProcessExecutor<'a, H, I, OT, S> where H: FnMut(&I) -> ExitKind, I: Input, - OT: ObserversTuple, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -147,20 +147,11 @@ where } } -impl<'a, EM, H, I, OT, S, Z> HasObserversHooks - for InProcessExecutor<'a, H, I, OT, S> -where - H: FnMut(&I) -> ExitKind, - I: Input, - OT: ObserversTuple + HasExecHooksTuple, -{ -} - impl<'a, H, I, OT, S> InProcessExecutor<'a, H, I, OT, S> where H: FnMut(&I) -> ExitKind, I: Input, - OT: ObserversTuple, + OT: ObserversTuple, { /// Create a new in mem executor. /// 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, ) where EM: EventFirer + EventRestarter, - OT: ObserversTuple, + OT: ObserversTuple, OC: Corpus, OF: Feedback, S: HasSolutions, @@ -423,7 +414,7 @@ mod unix_signal_handler { data: &mut InProcessExecutorHandlerData, ) where EM: EventFirer + EventRestarter, - OT: ObserversTuple, + OT: ObserversTuple, OC: Corpus, OF: Feedback, S: HasSolutions, @@ -634,7 +625,7 @@ mod windows_exception_handler { data: &mut InProcessExecutorHandlerData, ) where EM: EventFirer + EventRestarter, - OT: ObserversTuple, + OT: ObserversTuple, OC: Corpus, OF: Feedback, S: HasSolutions, diff --git a/libafl/src/executors/mod.rs b/libafl/src/executors/mod.rs index 4dfa0d4cdc..8044a43d75 100644 --- a/libafl/src/executors/mod.rs +++ b/libafl/src/executors/mod.rs @@ -17,19 +17,15 @@ pub mod shadow; pub use shadow::{HasShadowObserverHooks, ShadowExecutor}; use crate::{ - bolts::serdeany::SerdeAny, inputs::{HasTargetBytes, Input}, observers::ObserversTuple, Error, }; -use alloc::boxed::Box; - -/// A `CustomExitKind` for exits that do not fit to one of the default `ExitKind`. -pub trait CustomExitKind: core::fmt::Debug + SerdeAny + 'static {} +use serde::{Deserialize, Serialize}; /// How an execution finished. -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum ExitKind { /// The run exited normally. Ok, @@ -39,112 +35,14 @@ pub enum ExitKind { Oom, /// The run timed out Timeout, - /// The run resulted in a custom `ExitKind`. - Custom(Box), -} - -/// Pre and post exec hooks -pub trait HasExecHooks { - /// 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 { - /// 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 HasExecHooksTuple 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 HasExecHooksTuple for (Head, Tail) -where - Head: HasExecHooks, - Tail: HasExecHooksTuple, -{ - 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) - } + // The run resulted in a custom `ExitKind`. + // Custom(Box), } /// Holds a tuple of Observers -pub trait HasObservers +pub trait HasObservers where - OT: ObserversTuple, + OT: ObserversTuple, { /// Get the linked observers fn observers(&self) -> &OT; @@ -153,37 +51,6 @@ where fn observers_mut(&mut self) -> &mut OT; } -/// Execute the exec hooks of the observers if they all implement [`HasExecHooks`]. -pub trait HasObserversHooks: HasObservers -where - OT: ObserversTuple + HasExecHooksTuple, -{ - /// 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. pub trait Executor where diff --git a/libafl/src/executors/shadow.rs b/libafl/src/executors/shadow.rs index 2f15dc1888..f6a93f0323 100644 --- a/libafl/src/executors/shadow.rs +++ b/libafl/src/executors/shadow.rs @@ -1,7 +1,9 @@ //! 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::{ - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, inputs::Input, observers::ObserversTuple, Error, @@ -28,36 +30,22 @@ pub trait HasShadowObserverHooks { } /// A [`ShadowExecutor`] wraps an executor and a set of shadow observers -pub struct ShadowExecutor { +pub struct ShadowExecutor { executor: E, shadow_observers: SOT, - // Enable the execution of the shadow observers hooks with the regular observers hooks - shadow_hooks: bool, + phantom: PhantomData<(I, S)>, } -impl ShadowExecutor +impl ShadowExecutor where - SOT: ObserversTuple, + SOT: ObserversTuple, { /// Create a new `ShadowExecutor`, wrapping the given `executor`. pub fn new(executor: E, shadow_observers: SOT) -> Self { Self { executor, shadow_observers, - shadow_hooks: false, - } - } - - /// Create a new `ShadowExecutor`, wrapping the given `executor`. - pub fn with_shadow_hooks( - executor: E, - shadow_observers: SOT, - shadow_hooks: bool, - ) -> Self { - Self { - executor, - shadow_observers, - shadow_hooks, + phantom: PhantomData, } } @@ -70,51 +58,13 @@ where pub fn shadow_observers_mut(&mut self) -> &mut SOT { &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 HasShadowObserverHooks for ShadowExecutor -where - I: Input, - SOT: ObserversTuple + HasExecHooksTuple, -{ - #[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 Executor for ShadowExecutor +impl Executor for ShadowExecutor where E: Executor, I: Input, - SOT: ObserversTuple, + SOT: ObserversTuple, { fn run_target( &mut self, @@ -127,11 +77,11 @@ where } } -impl HasObservers for ShadowExecutor +impl HasObservers for ShadowExecutor where - E: HasObservers, - OT: ObserversTuple, - SOT: ObserversTuple, + E: HasObservers, + OT: ObserversTuple, + SOT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -143,44 +93,3 @@ where self.executor.observers_mut() } } - -impl HasObserversHooks for ShadowExecutor -where - E: HasObservers, - I: Input, - OT: ObserversTuple + HasExecHooksTuple, - SOT: ObserversTuple + HasExecHooksTuple, -{ - /// 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) - } -} diff --git a/libafl/src/executors/timeout.rs b/libafl/src/executors/timeout.rs index 9986e12773..998f0e6549 100644 --- a/libafl/src/executors/timeout.rs +++ b/libafl/src/executors/timeout.rs @@ -3,7 +3,7 @@ use core::time::Duration; use crate::{ - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, inputs::Input, observers::ObserversTuple, Error, @@ -129,10 +129,10 @@ where } } -impl HasObservers for TimeoutExecutor +impl HasObservers for TimeoutExecutor where - E: HasObservers, - OT: ObserversTuple, + E: HasObservers, + OT: ObserversTuple, { #[inline] fn observers(&self) -> &OT { @@ -144,11 +144,3 @@ where self.executor.observers_mut() } } - -impl HasObserversHooks for TimeoutExecutor -where - E: HasObservers, - I: Input, - OT: ObserversTuple + HasExecHooksTuple, -{ -} diff --git a/libafl/src/feedbacks/map.rs b/libafl/src/feedbacks/map.rs index 0bea825c66..27204bd6c6 100644 --- a/libafl/src/feedbacks/map.rs +++ b/libafl/src/feedbacks/map.rs @@ -22,9 +22,9 @@ use crate::{ }; /// A [`MapFeedback`] that strives to maximize the map contents. -pub type MaxMapFeedback = MapFeedback; +pub type MaxMapFeedback = MapFeedback; /// A [`MapFeedback`] that strives to minimize the map contents. -pub type MinMapFeedback = MapFeedback; +pub type MinMapFeedback = MapFeedback; /// A Reducer function is used to aggregate values for the novelty search pub trait Reducer: Serialize + serde::de::DeserializeOwned + 'static @@ -185,7 +185,7 @@ where /// The most common AFL-like feedback type #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(bound = "T: serde::de::DeserializeOwned")] -pub struct MapFeedback +pub struct MapFeedback where T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, R: Reducer, @@ -202,10 +202,10 @@ where /// Name identifier of the observer observer_name: String, /// Phantom Data of Reducer - phantom: PhantomData<(FT, S, R, O, T)>, + phantom: PhantomData<(FT, I, S, R, O, T)>, } -impl Feedback for MapFeedback +impl Feedback for MapFeedback where T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, R: Reducer, @@ -224,7 +224,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let mut interesting = false; // TODO Replace with match_name_type when stable @@ -312,7 +312,7 @@ where } } -impl Named for MapFeedback +impl Named for MapFeedback where T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, R: Reducer, @@ -326,7 +326,7 @@ where } } -impl MapFeedback +impl MapFeedback where T: Integer + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, R: Reducer, @@ -441,7 +441,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // TODO Replace with match_name_type when stable let observer = observers.match_name::(&self.name).unwrap(); diff --git a/libafl/src/feedbacks/mod.rs b/libafl/src/feedbacks/mod.rs index bbf8142a7b..2d21045c8a 100644 --- a/libafl/src/feedbacks/mod.rs +++ b/libafl/src/feedbacks/mod.rs @@ -40,7 +40,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple; + OT: ObserversTuple; #[cfg(feature = "introspection")] #[allow(clippy::too_many_arguments)] @@ -56,7 +56,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // Start a timer for this feedback let start_time = crate::bolts::cpu::read_time_counter(); @@ -168,7 +168,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { FL::is_pair_interesting( &mut self.first, @@ -194,7 +194,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { FL::is_pair_interesting_with_perf( &mut self.first, @@ -241,7 +241,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple; + OT: ObserversTuple; #[cfg(feature = "introspection")] #[allow(clippy::too_many_arguments)] @@ -258,7 +258,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple; + OT: ObserversTuple; } pub struct LogicEagerOr {} @@ -287,7 +287,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let a = first.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 where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // Execute this feedback let a = first.is_interesting_with_perf( @@ -355,7 +355,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; if a { @@ -379,7 +379,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // Execute this feedback let a = first.is_interesting_with_perf( @@ -429,7 +429,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let a = first.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 where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // Execute this feedback let a = first.is_interesting_with_perf( @@ -497,7 +497,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let a = first.is_interesting(state, manager, input, observers, exit_kind)?; if !a { @@ -521,7 +521,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // Execute this feedback let a = first.is_interesting_with_perf( @@ -596,7 +596,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { Ok(!self .first @@ -707,7 +707,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { Ok(false) } @@ -738,7 +738,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { if let ExitKind::Crash = exit_kind { Ok(true) @@ -787,7 +787,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { if let ExitKind::Timeout = exit_kind { Ok(true) @@ -841,7 +841,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { // TODO Replace with match_name_type when stable let observer = observers.match_name::(self.name()).unwrap(); diff --git a/libafl/src/fuzzer.rs b/libafl/src/fuzzer.rs index e9191548ab..63a3225196 100644 --- a/libafl/src/fuzzer.rs +++ b/libafl/src/fuzzer.rs @@ -4,7 +4,7 @@ use crate::{ bolts::current_time, corpus::{Corpus, CorpusScheduler, Testcase}, events::{Event, EventFirer, EventManager}, - executors::{Executor, ExitKind, HasExecHooksTuple, HasObservers, HasObserversHooks}, + executors::{Executor, ExitKind, HasObservers}, feedbacks::Feedback, inputs::Input, mark_feature_time, @@ -66,33 +66,44 @@ where } /// Evaluate if an input is interesting using the feedback -pub trait IsInteresting +pub trait ExecutionProcessor where - OT: ObserversTuple, + OT: ObserversTuple, I: Input, { /// Evaluate if a set of observation channels has an interesting state - fn is_interesting( + fn process_execution( &mut self, state: &mut S, manager: &mut EM, - input: &I, + input: I, observers: &OT, exit_kind: &ExitKind, - ) -> Result + send_events: bool, + ) -> Result<(ExecuteInputResult, Option), Error> where EM: EventFirer; } -/// Add to the state if interesting -pub trait IfInteresting { - /// Adds this input to the corpus, if it's intersting, and return the index - fn add_if_interesting( +/// Evaluate an input modyfing the state of the fuzzer +pub trait EvaluatorObservers: Sized +where + I: Input, + OT: ObserversTuple, +{ + /// 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( &mut self, state: &mut S, - input: &I, - is_interesting: bool, - ) -> Result, Error>; + executor: &mut E, + manager: &mut EM, + input: I, + send_events: bool, + ) -> Result<(ExecuteInputResult, Option), Error> + where + E: Executor + HasObservers, + EM: EventManager; } /// Evaluate an input modyfing the state of the fuzzer @@ -105,7 +116,21 @@ pub trait Evaluator { executor: &mut E, manager: &mut EM, input: I, - ) -> Result<(bool, Option), Error>; + ) -> Result<(ExecuteInputResult, Option), 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), Error>; /// Runs the input and triggers observers and feedback. /// Adds an input, to the corpus even if it's not considered `interesting` by the `feedback`. @@ -200,9 +225,10 @@ pub trait Fuzzer { ) -> Result; } +#[derive(Debug, PartialEq)] pub enum ExecuteInputResult { None, - Interesting, + Corpus, Solution, } @@ -270,97 +296,86 @@ where } } -impl IsInteresting for StdFuzzer -where - C: Corpus, - CS: CorpusScheduler, - F: Feedback, - I: Input, - OF: Feedback, - OT: ObserversTuple, - S: HasCorpus, -{ - /// Evaluate if a set of observation channels has an interesting state - fn is_interesting( - &mut self, - state: &mut S, - manager: &mut EM, - input: &I, - observers: &OT, - exit_kind: &ExitKind, - ) -> Result - where - EM: EventFirer, - { - self.feedback_mut() - .is_interesting(state, manager, input, observers, exit_kind) - } -} - -impl IfInteresting for StdFuzzer -where - C: Corpus, - CS: CorpusScheduler, - F: Feedback, - I: Input, - OF: Feedback, - OT: ObserversTuple, - S: HasCorpus, -{ - /// 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, 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 Evaluator +impl ExecutionProcessor for StdFuzzer where C: Corpus, + SC: Corpus, CS: CorpusScheduler, - E: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, - EM: EventManager, F: Feedback, I: Input, OF: Feedback, - S: HasExecutions + HasCorpus + HasSolutions + HasClientPerfStats, - SC: Corpus, + OT: ObserversTuple, + S: HasCorpus + HasSolutions + HasClientPerfStats + HasExecutions, { - /// Process one input, adding to the respective corpuses if needed and firing the right events - #[inline] - fn evaluate_input( + /// Evaluate if a set of observation channels has an interesting state + fn process_execution( &mut self, state: &mut S, - executor: &mut E, manager: &mut EM, input: I, - ) -> Result<(bool, Option), Error> { - let result = self.execute_input(state, executor, manager, &input)?; - let observers = executor.observers(); + observers: &OT, + exit_kind: &ExitKind, + send_events: bool, + ) -> Result<(ExecuteInputResult, Option), Error> + where + EM: EventFirer, + { + 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 => { self.feedback_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 self.objective_mut().discard_metadata(state, &input)?; @@ -370,19 +385,22 @@ where let idx = state.corpus_mut().add(testcase)?; self.scheduler_mut().on_add(state, idx)?; - let observers_buf = manager.serialize_observers(observers)?; - manager.fire( - state, - Event::NewTestcase { - input, - observers_buf, - corpus_size: state.corpus().count(), - client_config: "TODO".into(), - time: current_time(), - executions: *state.executions(), - }, - )?; - Ok((true, Some(idx))) + if send_events { + let observers_buf = manager.serialize_observers(observers)?; + manager.fire( + state, + Event::NewTestcase { + input, + observers_buf, + exit_kind: exit_kind.clone(), + corpus_size: state.corpus().count(), + client_config: manager.configuration().to_string(), + time: current_time(), + executions: *state.executions(), + }, + )?; + } + Ok((res, Some(idx))) } ExecuteInputResult::Solution => { // Not interesting @@ -392,17 +410,80 @@ where let mut testcase = Testcase::new(input); self.objective_mut().append_metadata(state, &mut 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 EvaluatorObservers + for StdFuzzer +where + C: Corpus, + CS: CorpusScheduler, + OT: ObserversTuple, + F: Feedback, + I: Input, + OF: Feedback, + S: HasExecutions + HasCorpus + HasSolutions + HasClientPerfStats, + SC: Corpus, +{ + /// Process one input, adding to the respective corpuses if needed and firing the right events + #[inline] + fn evaluate_input_with_observers( + &mut self, + state: &mut S, + executor: &mut E, + manager: &mut EM, + input: I, + send_events: bool, + ) -> Result<(ExecuteInputResult, Option), Error> + where + E: Executor + HasObservers, + EM: EventManager, + { + 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 Evaluator + for StdFuzzer +where + C: Corpus, + CS: CorpusScheduler, + E: Executor + HasObservers, + OT: ObserversTuple, + EM: EventManager, + F: Feedback, + I: Input, + OF: Feedback, + S: HasExecutions + HasCorpus + HasSolutions + HasClientPerfStats, + SC: Corpus, +{ + /// 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), 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 fn add_input( @@ -412,7 +493,7 @@ where manager: &mut EM, input: I, ) -> Result { - let _ = self.execute_input(state, executor, manager, &input)?; + let exit_kind = self.execute_input(state, executor, manager, &input)?; let observers = executor.observers(); // Always consider this to be "interesting" @@ -431,8 +512,9 @@ where Event::NewTestcase { input, observers_buf, + exit_kind, corpus_size: state.corpus().count(), - client_config: "TODO".into(), + client_config: manager.configuration().to_string(), time: current_time(), executions: *state.executions(), }, @@ -565,14 +647,13 @@ where executor: &mut E, event_mgr: &mut EM, input: &I, - ) -> Result + ) -> Result where - E: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, - EM: EventManager, + E: Executor + HasObservers, + OT: ObserversTuple, { 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); start_timer!(state); @@ -582,57 +663,9 @@ where *state.executions_mut() += 1; 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); - let observers = executor.observers(); - - 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) - } + Ok(exit_kind) } } diff --git a/libafl/src/observers/cmp.rs b/libafl/src/observers/cmp.rs index 0c3d34e9a9..3c7cb53061 100644 --- a/libafl/src/observers/cmp.rs +++ b/libafl/src/observers/cmp.rs @@ -9,7 +9,6 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; use crate::{ bolts::{ownedref::OwnedRefMut, tuples::Named, AsSlice}, - executors::HasExecHooks, observers::Observer, state::HasMetadata, Error, @@ -95,7 +94,7 @@ pub trait CmpMap: Serialize + DeserializeOwned { } /// A [`CmpObserver`] observes the traced comparisons during the current execution using a [`CmpMap`] -pub trait CmpObserver: Observer +pub trait CmpObserver: Observer where CM: CmpMap, { @@ -110,7 +109,7 @@ where /// Add [`CmpValuesMetadata`] to the State including the logged values. /// This routine does a basic loop filtering because loop index cmps are not interesting. - fn add_cmpvalues_meta(&mut self, state: &mut S) + fn add_cmpvalues_meta(&mut self, state: &mut S) where S: HasMetadata, { @@ -181,14 +180,14 @@ where name: String, } -impl<'a, CM> CmpObserver for StdCmpObserver<'a, CM> +impl<'a, CM, I, S> CmpObserver for StdCmpObserver<'a, CM> where CM: CmpMap, { /// Get the number of usable cmps (all by default) fn usable_count(&self) -> usize { match &self.size { - None => self.map().len(), + None => self.map.as_ref().len(), Some(o) => *o.as_ref(), } } @@ -202,19 +201,11 @@ where } } -impl<'a, CM> Observer for StdCmpObserver<'a, CM> where CM: CmpMap {} - -impl<'a, CM, EM, I, S, Z> HasExecHooks for StdCmpObserver<'a, CM> +impl<'a, CM, I, S> Observer for StdCmpObserver<'a, CM> where CM: CmpMap, { - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.map.as_mut().reset()?; Ok(()) } diff --git a/libafl/src/observers/map.rs b/libafl/src/observers/map.rs index 622f9321a1..8fb6aac66e 100644 --- a/libafl/src/observers/map.rs +++ b/libafl/src/observers/map.rs @@ -12,13 +12,12 @@ use crate::{ ownedref::{OwnedRefMut, OwnedSliceMut}, tuples::Named, }, - executors::HasExecHooks, observers::Observer, Error, }; /// A [`MapObserver`] observes the static map, as oftentimes used for afl-like coverage information -pub trait MapObserver: Observer +pub trait MapObserver: Named + serde::Serialize + serde::de::DeserializeOwned where T: Default + Copy, { @@ -70,24 +69,13 @@ where name: String, } -impl<'a, T> Observer for StdMapObserver<'a, T> where - T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned -{ -} - -impl<'a, EM, I, S, T, Z> HasExecHooks for StdMapObserver<'a, T> +impl<'a, I, S, T> Observer for StdMapObserver<'a, T> where T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, Self: MapObserver, { #[inline] - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.reset_map() } } @@ -186,24 +174,13 @@ where name: String, } -impl<'a, T, const N: usize> Observer for ConstMapObserver<'a, T, N> where - T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned -{ -} - -impl<'a, EM, I, S, T, Z, const N: usize> HasExecHooks for ConstMapObserver<'a, T, N> +impl<'a, I, S, T, const N: usize> Observer for ConstMapObserver<'a, T, N> where T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, Self: MapObserver, { #[inline] - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.reset_map() } } @@ -309,23 +286,13 @@ where name: String, } -impl<'a, T> Observer for VariableMapObserver<'a, T> where - T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned -{ -} - -impl<'a, EM, I, S, T, Z> HasExecHooks for VariableMapObserver<'a, T> +impl<'a, I, S, T> Observer for VariableMapObserver<'a, T> where T: Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned, + Self: MapObserver, { #[inline] - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { 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, ]; -impl Observer for HitcountsMapObserver where M: MapObserver {} - -impl HasExecHooks for HitcountsMapObserver +impl Observer for HitcountsMapObserver where - M: MapObserver + HasExecHooks, + M: MapObserver + Observer, { #[inline] - fn pre_exec( - &mut self, - fuzzer: &mut Z, - state: &mut S, - mgr: &mut EM, - input: &I, - ) -> Result<(), Error> { - self.base.pre_exec(fuzzer, state, mgr, input) + fn pre_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> { + self.base.pre_exec(state, input) } #[inline] - fn post_exec( - &mut self, - fuzzer: &mut Z, - state: &mut S, - mgr: &mut EM, - input: &I, - ) -> Result<(), Error> { + fn post_exec(&mut self, state: &mut S, input: &I) -> Result<(), Error> { let cnt = self.usable_count(); for x in self.map_mut()[0..cnt].iter_mut() { *x = COUNT_CLASS_LOOKUP[*x as usize]; } - self.base.post_exec(fuzzer, state, mgr, input) + self.base.post_exec(state, input) } } diff --git a/libafl/src/observers/mod.rs b/libafl/src/observers/mod.rs index b5804b7c8c..427695d4d4 100644 --- a/libafl/src/observers/mod.rs +++ b/libafl/src/observers/mod.rs @@ -15,31 +15,65 @@ use crate::{ current_time, tuples::{MatchName, Named}, }, - executors::HasExecHooks, Error, }; /// Observers observe different information about the target. /// They can then be used by various sorts of feedback. -pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned { +pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned { /// The testcase finished execution, calculate any changes. /// Reserved for future use. #[inline] fn flush(&mut self) -> Result<(), Error> { 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 -pub trait ObserversTuple: MatchName + serde::Serialize + serde::de::DeserializeOwned {} +pub trait ObserversTuple: 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 ObserversTuple for (Head, Tail) +impl ObserversTuple 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 ObserversTuple for (Head, Tail) where - Head: Observer, - Tail: ObserversTuple, + Head: Observer, + Tail: ObserversTuple, { + 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. @@ -68,28 +102,14 @@ impl TimeObserver { } } -impl Observer for TimeObserver {} - -impl HasExecHooks for TimeObserver { - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { +impl Observer for TimeObserver { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.last_runtime = None; self.start_time = current_time(); Ok(()) } - fn post_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn post_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.last_runtime = current_time().checked_sub(self.start_time); Ok(()) } diff --git a/libafl/src/stages/tracing.rs b/libafl/src/stages/tracing.rs index 1a564c116e..7539ebeb4e 100644 --- a/libafl/src/stages/tracing.rs +++ b/libafl/src/stages/tracing.rs @@ -2,7 +2,7 @@ use core::{marker::PhantomData, mem::drop}; use crate::{ corpus::Corpus, - executors::{Executor, HasExecHooksTuple, HasObservers, HasObserversHooks, ShadowExecutor}, + executors::{Executor, HasObservers, ShadowExecutor}, inputs::Input, mark_feature_time, observers::ObserversTuple, @@ -21,8 +21,8 @@ pub struct TracingStage where I: Input, C: Corpus, - TE: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, + TE: Executor + HasObservers, + OT: ObserversTuple, S: HasClientPerfStats + HasExecutions + HasCorpus, { tracer_executor: TE, @@ -34,8 +34,8 @@ impl Stage for TracingStage, - TE: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, + TE: Executor + HasObservers, + OT: ObserversTuple, S: HasClientPerfStats + HasExecutions + HasCorpus, { #[inline] @@ -58,7 +58,8 @@ where start_timer!(state); self.tracer_executor - .pre_exec_observers(fuzzer, state, manager, &input)?; + .observers_mut() + .pre_exec_all(state, &input)?; mark_feature_time!(state, PerfFeature::PreExecObservers); start_timer!(state); @@ -72,7 +73,8 @@ where start_timer!(state); self.tracer_executor - .post_exec_observers(fuzzer, state, manager, &input)?; + .observers_mut() + .post_exec_all(state, &input)?; mark_feature_time!(state, PerfFeature::PostExecObservers); Ok(()) @@ -83,8 +85,8 @@ impl TracingStage where I: Input, C: Corpus, - TE: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, + TE: Executor + HasObservers, + OT: ObserversTuple, S: HasClientPerfStats + HasExecutions + HasCorpus, { /// Creates a new default stage @@ -103,21 +105,21 @@ pub struct ShadowTracingStage { phantom: PhantomData<(C, E, EM, I, OT, S, SOT, Z)>, } -impl Stage, EM, S, Z> +impl Stage, EM, S, Z> for ShadowTracingStage where I: Input, C: Corpus, - E: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, - SOT: ObserversTuple + HasExecHooksTuple, + E: Executor + HasObservers, + OT: ObserversTuple, + SOT: ObserversTuple, S: HasClientPerfStats + HasExecutions + HasCorpus, { #[inline] fn perform( &mut self, fuzzer: &mut Z, - executor: &mut ShadowExecutor, + executor: &mut ShadowExecutor, state: &mut S, manager: &mut EM, corpus_idx: usize, @@ -131,11 +133,11 @@ where .clone(); mark_feature_time!(state, PerfFeature::GetInputFromCorpus); - let prev_shadow_hooks = *executor.shadow_hooks(); - *executor.shadow_hooks_mut() = true; - 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); start_timer!(state); @@ -145,11 +147,12 @@ where *state.executions_mut() += 1; 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); - *executor.shadow_hooks_mut() = prev_shadow_hooks; - Ok(()) } } @@ -158,13 +161,13 @@ impl ShadowTracingStage where I: Input, C: Corpus, - E: Executor + HasObservers + HasObserversHooks, - OT: ObserversTuple + HasExecHooksTuple, - SOT: ObserversTuple + HasExecHooksTuple, + E: Executor + HasObservers, + OT: ObserversTuple, + SOT: ObserversTuple, S: HasClientPerfStats + HasExecutions + HasCorpus, { /// Creates a new default stage - pub fn new(_executor: &mut ShadowExecutor) -> Self { + pub fn new(_executor: &mut ShadowExecutor) -> Self { Self { phantom: PhantomData, } diff --git a/libafl/src/state/mod.rs b/libafl/src/state/mod.rs index 5a387fd17f..326f894568 100644 --- a/libafl/src/state/mod.rs +++ b/libafl/src/state/mod.rs @@ -14,9 +14,9 @@ use crate::{ serdeany::{SerdeAny, SerdeAnyMap}, }, corpus::Corpus, - events::{Event, EventManager, LogSeverity}, + events::{Event, EventFirer, LogSeverity}, feedbacks::FeedbackStatesTuple, - fuzzer::Evaluator, + fuzzer::{Evaluator, ExecuteInputResult}, generators::Generator, inputs::Input, stats::ClientPerfStats, @@ -385,9 +385,8 @@ where if forced { let _ = fuzzer.add_input(self, executor, manager, input)?; } else { - let (is_interesting, _) = - fuzzer.evaluate_input(self, executor, manager, input)?; - if !is_interesting { + let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?; + if res == ExecuteInputResult::None { println!("File {:?} was not interesting, skipped.", &path); } } @@ -411,7 +410,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventManager, + EM: EventFirer, { for in_dir in in_dirs { self.load_from_directory(fuzzer, executor, manager, in_dir, forced)?; @@ -424,7 +423,6 @@ where phantom: PhantomData, }, )?; - manager.process(fuzzer, self, executor)?; Ok(()) } @@ -440,7 +438,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventManager, + EM: EventFirer, { self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, true) } @@ -455,7 +453,7 @@ where ) -> Result<(), Error> where Z: Evaluator, - EM: EventManager, + EM: EventFirer, { self.load_initial_inputs_internal(fuzzer, executor, manager, in_dirs, false) } @@ -481,13 +479,13 @@ where where G: Generator, Z: Evaluator, - EM: EventManager, + EM: EventFirer, { let mut added = 0; for _ in 0..num { let input = generator.generate(self.rand_mut())?; - let (is_interesting, _) = fuzzer.evaluate_input(self, executor, manager, input)?; - if is_interesting { + let (res, _) = fuzzer.evaluate_input(self, executor, manager, input)?; + if res != ExecuteInputResult::None { added += 1; } } @@ -499,7 +497,6 @@ where phantom: PhantomData, }, )?; - manager.process(fuzzer, self, executor)?; Ok(()) } diff --git a/libafl_cc/Cargo.toml b/libafl_cc/Cargo.toml index 302402bb0f..098655f0b7 100644 --- a/libafl_cc/Cargo.toml +++ b/libafl_cc/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_cc" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi "] description = "Commodity library to wrap compilers and link LibAFL" documentation = "https://docs.rs/libafl_cc" diff --git a/libafl_derive/Cargo.toml b/libafl_derive/Cargo.toml index 36ef86f99f..a26e265596 100644 --- a/libafl_derive/Cargo.toml +++ b/libafl_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_derive" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi "] description = "Derive proc-macro crate for LibAFL" documentation = "https://docs.rs/libafl_derive" diff --git a/libafl_frida/Cargo.toml b/libafl_frida/Cargo.toml index b8871b08de..37f14f999f 100644 --- a/libafl_frida/Cargo.toml +++ b/libafl_frida/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_frida" -version = "0.3.2" +version = "0.4.0" authors = ["s1341 "] description = "Frida backend library for LibAFL" documentation = "https://docs.rs/libafl_frida" @@ -19,8 +19,8 @@ cmplog = [] cc = { version = "1.0", features = ["parallel"] } [dependencies] -libafl = { path = "../libafl", version = "0.3.1", features = ["std", "libafl_derive"] } -libafl_targets = { path = "../libafl_targets", version = "0.3.2", features = ["sancov_cmplog"] } +libafl = { path = "../libafl", version = "0.4.0", features = ["std", "libafl_derive"] } +libafl_targets = { path = "../libafl_targets", version = "0.4.0", features = ["sancov_cmplog"] } nix = "0.20.0" libc = "0.2.92" hashbrown = "0.11" diff --git a/libafl_frida/src/asan_errors.rs b/libafl_frida/src/asan_errors.rs index 3b04f5eb44..54746d93b5 100644 --- a/libafl_frida/src/asan_errors.rs +++ b/libafl_frida/src/asan_errors.rs @@ -9,7 +9,7 @@ use libafl::{ bolts::{ownedref::OwnedPtr, tuples::Named}, corpus::Testcase, events::EventFirer, - executors::{ExitKind, HasExecHooks}, + executors::ExitKind, feedbacks::Feedback, inputs::{HasTargetBytes, Input}, observers::{Observer, ObserversTuple}, @@ -447,16 +447,8 @@ pub struct AsanErrorsObserver { errors: OwnedPtr>, } -impl Observer for AsanErrorsObserver {} - -impl HasExecHooks for AsanErrorsObserver { - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { +impl Observer for AsanErrorsObserver { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { unsafe { if ASAN_ERRORS.is_some() { ASAN_ERRORS.as_mut().unwrap().clear(); @@ -529,7 +521,7 @@ where ) -> Result where EM: EventFirer, - OT: ObserversTuple, + OT: ObserversTuple, { let observer = observers .match_name::("AsanErrors") diff --git a/libafl_frida/src/asan_rt.rs b/libafl_frida/src/asan_rt.rs index e0febf11cc..a7596f69b8 100644 --- a/libafl_frida/src/asan_rt.rs +++ b/libafl_frida/src/asan_rt.rs @@ -1946,6 +1946,7 @@ impl AsanRuntime { let backtrace = Backtrace::new(); 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 { if insn.mnemonic().unwrap().starts_with('l') { AsanError::StackOobRead(( @@ -1962,38 +1963,35 @@ impl AsanRuntime { backtrace, )) } - } else { - #[allow(clippy::option_if_let_else)] - if let Some(metadata) = self - .allocator - .find_metadata(fault_address, self.regs[base_reg as usize]) - { - let asan_readwrite_error = AsanReadWriteError { - registers: self.regs, - pc: actual_pc, - fault: (base_reg, index_reg, displacement as usize, fault_address), - metadata: metadata.clone(), - backtrace, - }; - if insn.mnemonic().unwrap().starts_with('l') { - if metadata.freed { - AsanError::ReadAfterFree(asan_readwrite_error) - } else { - AsanError::OobRead(asan_readwrite_error) - } - } else if metadata.freed { - AsanError::WriteAfterFree(asan_readwrite_error) + } else if let Some(metadata) = self + .allocator + .find_metadata(fault_address, self.regs[base_reg as usize]) + { + let asan_readwrite_error = AsanReadWriteError { + registers: self.regs, + pc: actual_pc, + fault: (base_reg, index_reg, displacement as usize, fault_address), + metadata: metadata.clone(), + backtrace, + }; + if insn.mnemonic().unwrap().starts_with('l') { + if metadata.freed { + AsanError::ReadAfterFree(asan_readwrite_error) } else { - AsanError::OobWrite(asan_readwrite_error) + AsanError::OobRead(asan_readwrite_error) } + } else if metadata.freed { + AsanError::WriteAfterFree(asan_readwrite_error) } else { - AsanError::Unknown(( - self.regs, - actual_pc, - (base_reg, index_reg, displacement as usize, fault_address), - backtrace, - )) + AsanError::OobWrite(asan_readwrite_error) } + } else { + AsanError::Unknown(( + self.regs, + actual_pc, + (base_reg, index_reg, displacement as usize, fault_address), + backtrace, + )) }; AsanErrors::get_mut().report_error(error); } diff --git a/libafl_targets/Cargo.toml b/libafl_targets/Cargo.toml index c1f4eb9ded..9f064f6398 100644 --- a/libafl_targets/Cargo.toml +++ b/libafl_targets/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_targets" -version = "0.3.2" +version = "0.4.0" authors = ["Andrea Fioraldi "] description = "Common code for target instrumentation that can be used combined with LibAFL" documentation = "https://docs.rs/libafl_targets" @@ -25,6 +25,6 @@ cc = { version = "1.0", features = ["parallel"] } [dependencies] 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-big-array = "0.3.2" diff --git a/libafl_targets/src/cmplog.rs b/libafl_targets/src/cmplog.rs index 4db2b1a654..f923b6899d 100644 --- a/libafl_targets/src/cmplog.rs +++ b/libafl_targets/src/cmplog.rs @@ -3,7 +3,6 @@ use libafl::{ bolts::{ownedref::OwnedRefMut, tuples::Named}, - executors::HasExecHooks, observers::{CmpMap, CmpObserver, CmpValues, Observer}, state::HasMetadata, Error, @@ -146,11 +145,14 @@ pub struct CmpLogObserver<'a> { name: String, } -impl<'a> CmpObserver for CmpLogObserver<'a> { +impl<'a, I, S> CmpObserver for CmpLogObserver<'a> +where + S: HasMetadata, +{ /// Get the number of usable cmps (all by default) fn usable_count(&self) -> usize { match &self.size { - None => self.map().len(), + None => self.map.as_ref().len(), Some(o) => *o.as_ref(), } } @@ -164,19 +166,12 @@ impl<'a> CmpObserver for CmpLogObserver<'a> { } } -impl<'a> Observer for CmpLogObserver<'a> {} - -impl<'a, EM, I, S, Z> HasExecHooks for CmpLogObserver<'a> +impl<'a, I, S> Observer for CmpLogObserver<'a> where S: HasMetadata, + Self: CmpObserver, { - fn pre_exec( - &mut self, - _fuzzer: &mut Z, - _state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> { self.map.as_mut().reset()?; unsafe { CMPLOG_ENABLED = 1; @@ -184,13 +179,7 @@ where Ok(()) } - fn post_exec( - &mut self, - _fuzzer: &mut Z, - state: &mut S, - _mgr: &mut EM, - _input: &I, - ) -> Result<(), Error> { + fn post_exec(&mut self, state: &mut S, _input: &I) -> Result<(), Error> { unsafe { CMPLOG_ENABLED = 0; } diff --git a/libafl_tests/Cargo.toml b/libafl_tests/Cargo.toml index b73ea269f8..4a05baf817 100644 --- a/libafl_tests/Cargo.toml +++ b/libafl_tests/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libafl_tests" -version = "0.1.0" +version = "0.4.0" authors = ["tokatoka "] edition = "2018"