UserStats (#114)
* MultiStats * custom event in MapFeedback * fix introspection * fix windows * clippy * fix nostd * bump to 0.3.2
This commit is contained in:
parent
921baf74b5
commit
2f54e9dc01
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "baby_fuzzer"
|
name = "baby_fuzzer"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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 = "frida_libpng"
|
name = "frida_libpng"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
|
@ -34,7 +34,7 @@ use libafl::{
|
|||||||
observers::{HitcountsMapObserver, ObserversTuple, StdMapObserver, TimeObserver},
|
observers::{HitcountsMapObserver, ObserversTuple, StdMapObserver, TimeObserver},
|
||||||
stages::mutational::StdMutationalStage,
|
stages::mutational::StdMutationalStage,
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
stats::SimpleStats,
|
stats::MultiStats,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -320,13 +320,13 @@ unsafe fn fuzz(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let stats_closure = |s| println!("{}", s);
|
let stats_closure = |s| println!("{}", s);
|
||||||
// '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 = SimpleStats::new(stats_closure);
|
let stats = MultiStats::new(stats_closure);
|
||||||
|
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
AshmemService::start().expect("Failed to start Ashmem service");
|
AshmemService::start().expect("Failed to start Ashmem service");
|
||||||
let shmem_provider = StdShMemProvider::new()?;
|
let shmem_provider = StdShMemProvider::new()?;
|
||||||
|
|
||||||
let mut client_init_stats = || Ok(SimpleStats::new(stats_closure));
|
let mut client_init_stats = || Ok(MultiStats::new(stats_closure));
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr| {
|
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr| {
|
||||||
// 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.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libmozjpeg"
|
name = "libfuzzer_libmozjpeg"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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 = "libfuzzer_libpng"
|
name = "libfuzzer_libpng"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ use libafl::{
|
|||||||
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
stages::mutational::StdMutationalStage,
|
stages::mutational::StdMutationalStage,
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
stats::SimpleStats,
|
stats::MultiStats,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ pub fn main() {
|
|||||||
/// The actual fuzzer
|
/// The actual fuzzer
|
||||||
fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
|
fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> 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 = SimpleStats::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) = match setup_restarting_mgr_std(stats, broker_port) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_libpng_launcher"
|
name = "libfuzzer_libpng_launcher"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ use libafl::{
|
|||||||
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
stages::mutational::StdMutationalStage,
|
stages::mutational::StdMutationalStage,
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
stats::SimpleStats,
|
stats::MultiStats,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM};
|
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM};
|
||||||
@ -58,8 +58,8 @@ pub fn main() {
|
|||||||
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
|
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
|
||||||
|
|
||||||
let stats_closure = |s| println!("{}", s);
|
let stats_closure = |s| println!("{}", s);
|
||||||
let stats = SimpleStats::new(stats_closure);
|
let stats = MultiStats::new(stats_closure);
|
||||||
let mut client_init_stats = || Ok(SimpleStats::new(stats_closure));
|
let mut client_init_stats = || Ok(MultiStats::new(stats_closure));
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr| {
|
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr| {
|
||||||
let corpus_dirs = &[PathBuf::from("./corpus")];
|
let corpus_dirs = &[PathBuf::from("./corpus")];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libfuzzer_reachability"
|
name = "libfuzzer_reachability"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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 = "libfuzzer_stb_image"
|
name = "libfuzzer_stb_image"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
|
@ -19,7 +19,7 @@ use libafl::{
|
|||||||
observers::{StdMapObserver, TimeObserver},
|
observers::{StdMapObserver, TimeObserver},
|
||||||
stages::{StdMutationalStage, TracingStage},
|
stages::{StdMutationalStage, TracingStage},
|
||||||
state::{HasCorpus, StdState},
|
state::{HasCorpus, StdState},
|
||||||
stats::SimpleStats,
|
stats::MultiStats,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ pub fn main() {
|
|||||||
/// The actual fuzzer
|
/// The actual fuzzer
|
||||||
fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Result<(), Error> {
|
fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> 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 = SimpleStats::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) = match setup_restarting_mgr_std(stats, broker_port) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl"
|
name = "libafl"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
@ -52,7 +52,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.1" }
|
libafl_derive = { optional = true, path = "../libafl_derive", version = "0.3.2" }
|
||||||
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"
|
||||||
|
@ -249,7 +249,7 @@ where
|
|||||||
let client = stats.client_stats_mut_for(sender_id);
|
let client = stats.client_stats_mut_for(sender_id);
|
||||||
client.update_corpus_size(*corpus_size as u64);
|
client.update_corpus_size(*corpus_size as u64);
|
||||||
client.update_executions(*executions as u64, *time);
|
client.update_executions(*executions as u64, *time);
|
||||||
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
|
stats.display(event.name().to_string(), sender_id);
|
||||||
Ok(BrokerEventResult::Forward)
|
Ok(BrokerEventResult::Forward)
|
||||||
}
|
}
|
||||||
Event::UpdateStats {
|
Event::UpdateStats {
|
||||||
@ -260,7 +260,17 @@ where
|
|||||||
// TODO: The stats buffer should be added on client add.
|
// TODO: The stats buffer should be added on client add.
|
||||||
let client = stats.client_stats_mut_for(sender_id);
|
let client = stats.client_stats_mut_for(sender_id);
|
||||||
client.update_executions(*executions as u64, *time);
|
client.update_executions(*executions as u64, *time);
|
||||||
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
|
stats.display(event.name().to_string(), sender_id);
|
||||||
|
Ok(BrokerEventResult::Handled)
|
||||||
|
}
|
||||||
|
Event::UpdateUserStats {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
phantom: _,
|
||||||
|
} => {
|
||||||
|
let client = stats.client_stats_mut_for(sender_id);
|
||||||
|
client.update_user_stats(name.clone(), value.clone());
|
||||||
|
stats.display(event.name().to_string(), sender_id);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -282,9 +292,7 @@ where
|
|||||||
client.update_introspection_stats(**introspection_stats);
|
client.update_introspection_stats(**introspection_stats);
|
||||||
|
|
||||||
// Display the stats via `.display` only on core #1
|
// Display the stats via `.display` only on core #1
|
||||||
if sender_id == 1 {
|
stats.display(event.name().to_string(), sender_id);
|
||||||
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Correctly handled the event
|
// Correctly handled the event
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
@ -292,7 +300,7 @@ where
|
|||||||
Event::Objective { objective_size } => {
|
Event::Objective { objective_size } => {
|
||||||
let client = stats.client_stats_mut_for(sender_id);
|
let client = stats.client_stats_mut_for(sender_id);
|
||||||
client.update_objective_size(*objective_size as u64);
|
client.update_objective_size(*objective_size as u64);
|
||||||
stats.display(event.name().to_string() + " #" + &sender_id.to_string());
|
stats.display(event.name().to_string(), sender_id);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::Log {
|
Event::Log {
|
||||||
@ -301,6 +309,7 @@ where
|
|||||||
phantom: _,
|
phantom: _,
|
||||||
} => {
|
} => {
|
||||||
let (_, _) = (severity_level, message);
|
let (_, _) = (severity_level, message);
|
||||||
|
// TODO rely on Stats
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
println!("[LOG {}]: {}", severity_level, message);
|
println!("[LOG {}]: {}", severity_level, message);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
@ -338,7 +347,7 @@ where
|
|||||||
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
let observers: OT = postcard::from_bytes(&observers_buf)?;
|
||||||
// TODO include ExitKind in NewTestcase
|
// TODO include ExitKind in NewTestcase
|
||||||
let is_interesting =
|
let is_interesting =
|
||||||
fuzzer.is_interesting(state, &input, &observers, &ExitKind::Ok)?;
|
fuzzer.is_interesting(state, self, &input, &observers, &ExitKind::Ok)?;
|
||||||
if fuzzer
|
if fuzzer
|
||||||
.add_if_interesting(state, &input, is_interesting)?
|
.add_if_interesting(state, &input, is_interesting)?
|
||||||
.is_some()
|
.is_some()
|
||||||
|
@ -9,7 +9,7 @@ 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, Error};
|
use crate::{inputs::Input, observers::ObserversTuple, stats::UserStats, Error};
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
use crate::stats::ClientPerfStats;
|
use crate::stats::ClientPerfStats;
|
||||||
@ -95,6 +95,15 @@ where
|
|||||||
/// [`PhantomData`]
|
/// [`PhantomData`]
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
},
|
},
|
||||||
|
/// New stats.
|
||||||
|
UpdateUserStats {
|
||||||
|
/// Custom user stats name
|
||||||
|
name: String,
|
||||||
|
/// Custom user stats value
|
||||||
|
value: UserStats,
|
||||||
|
/// [`PhantomData`]
|
||||||
|
phantom: PhantomData<I>,
|
||||||
|
},
|
||||||
/// New stats with performance stats.
|
/// New stats with performance stats.
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
UpdatePerfStats {
|
UpdatePerfStats {
|
||||||
@ -143,11 +152,16 @@ where
|
|||||||
observers_buf: _,
|
observers_buf: _,
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
} => "New Testcase",
|
} => "Testcase",
|
||||||
Event::UpdateStats {
|
Event::UpdateStats {
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
|
}
|
||||||
|
| Event::UpdateUserStats {
|
||||||
|
name: _,
|
||||||
|
value: _,
|
||||||
|
phantom: _,
|
||||||
} => "Stats",
|
} => "Stats",
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
Event::UpdatePerfStats {
|
Event::UpdatePerfStats {
|
||||||
|
@ -100,7 +100,7 @@ where
|
|||||||
stats
|
stats
|
||||||
.client_stats_mut_for(0)
|
.client_stats_mut_for(0)
|
||||||
.update_executions(*executions as u64, *time);
|
.update_executions(*executions as u64, *time);
|
||||||
stats.display(event.name().to_string());
|
stats.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::UpdateStats {
|
Event::UpdateStats {
|
||||||
@ -112,7 +112,18 @@ where
|
|||||||
stats
|
stats
|
||||||
.client_stats_mut_for(0)
|
.client_stats_mut_for(0)
|
||||||
.update_executions(*executions as u64, *time);
|
.update_executions(*executions as u64, *time);
|
||||||
stats.display(event.name().to_string());
|
stats.display(event.name().to_string(), 0);
|
||||||
|
Ok(BrokerEventResult::Handled)
|
||||||
|
}
|
||||||
|
Event::UpdateUserStats {
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
phantom: _,
|
||||||
|
} => {
|
||||||
|
stats
|
||||||
|
.client_stats_mut_for(0)
|
||||||
|
.update_user_stats(name.clone(), value.clone());
|
||||||
|
stats.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -125,14 +136,14 @@ where
|
|||||||
// TODO: The stats buffer should be added on client add.
|
// TODO: The stats buffer should be added on client add.
|
||||||
stats.client_stats_mut()[0].update_executions(*executions as u64, *time);
|
stats.client_stats_mut()[0].update_executions(*executions as u64, *time);
|
||||||
stats.client_stats_mut()[0].update_introspection_stats(**introspection_stats);
|
stats.client_stats_mut()[0].update_introspection_stats(**introspection_stats);
|
||||||
stats.display(event.name().to_string());
|
stats.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::Objective { objective_size } => {
|
Event::Objective { objective_size } => {
|
||||||
stats
|
stats
|
||||||
.client_stats_mut_for(0)
|
.client_stats_mut_for(0)
|
||||||
.update_objective_size(*objective_size as u64);
|
.update_objective_size(*objective_size as u64);
|
||||||
stats.display(event.name().to_string());
|
stats.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::Log {
|
Event::Log {
|
||||||
|
@ -365,7 +365,7 @@ mod unix_signal_handler {
|
|||||||
|
|
||||||
let interesting = fuzzer
|
let interesting = fuzzer
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, &input, observers, &ExitKind::Timeout)
|
.is_interesting(state, event_mgr, &input, observers, &ExitKind::Timeout)
|
||||||
.expect("In timeout handler objective failure.");
|
.expect("In timeout handler objective failure.");
|
||||||
|
|
||||||
if interesting {
|
if interesting {
|
||||||
@ -514,7 +514,7 @@ mod unix_signal_handler {
|
|||||||
|
|
||||||
let interesting = fuzzer
|
let interesting = fuzzer
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, &input, observers, &ExitKind::Crash)
|
.is_interesting(state, event_mgr, &input, observers, &ExitKind::Crash)
|
||||||
.expect("In crash handler objective failure.");
|
.expect("In crash handler objective failure.");
|
||||||
|
|
||||||
if interesting {
|
if interesting {
|
||||||
@ -658,7 +658,7 @@ mod windows_exception_handler {
|
|||||||
|
|
||||||
let interesting = fuzzer
|
let interesting = fuzzer
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, &input, observers, &ExitKind::Crash)
|
.is_interesting(state, event_mgr, &input, observers, &ExitKind::Crash)
|
||||||
.expect("In crash handler objective failure.");
|
.expect("In crash handler objective failure.");
|
||||||
|
|
||||||
if interesting {
|
if interesting {
|
||||||
|
@ -11,11 +11,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
bolts::{tuples::Named, AsSlice},
|
bolts::{tuples::Named, AsSlice},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
|
events::{Event, EventFirer},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{Feedback, FeedbackState, FeedbackStatesTuple},
|
feedbacks::{Feedback, FeedbackState, FeedbackStatesTuple},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::{MapObserver, ObserversTuple},
|
||||||
state::{HasFeedbackStates, HasMetadata},
|
state::{HasFeedbackStates, HasMetadata},
|
||||||
|
stats::UserStats,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,14 +214,16 @@ where
|
|||||||
S: HasFeedbackStates<FT>,
|
S: HasFeedbackStates<FT>,
|
||||||
FT: FeedbackStatesTuple,
|
FT: FeedbackStatesTuple,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let mut interesting = false;
|
let mut interesting = false;
|
||||||
@ -248,6 +252,7 @@ where
|
|||||||
for i in 0..size {
|
for i in 0..size {
|
||||||
let history = map_state.history_map[i];
|
let history = map_state.history_map[i];
|
||||||
let item = observer.map()[i];
|
let item = observer.map()[i];
|
||||||
|
// TODO maybe walk again the histroy map only when it is interesting is more efficient
|
||||||
if item != initial {
|
if item != initial {
|
||||||
self.indexes.as_mut().unwrap().push(i);
|
self.indexes.as_mut().unwrap().push(i);
|
||||||
}
|
}
|
||||||
@ -287,6 +292,23 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if interesting {
|
||||||
|
let mut filled = 0;
|
||||||
|
for i in 0..size {
|
||||||
|
if map_state.history_map[i] != initial {
|
||||||
|
filled += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manager.fire(
|
||||||
|
state,
|
||||||
|
Event::UpdateUserStats {
|
||||||
|
name: self.name.to_string(),
|
||||||
|
value: UserStats::Ratio(filled, size as u64),
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(interesting)
|
Ok(interesting)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,14 +455,16 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver<usize>,
|
O: MapObserver<usize>,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
|
@ -10,6 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchName, Named},
|
bolts::tuples::{MatchName, Named},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
|
events::EventFirer,
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{ObserversTuple, TimeObserver},
|
observers::{ObserversTuple, TimeObserver},
|
||||||
@ -29,20 +30,24 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
/// `is_interesting ` return if an input is worth the addition to the corpus
|
/// `is_interesting ` return if an input is worth the addition to the corpus
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple;
|
OT: ObserversTuple;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
fn is_interesting_with_perf<OT>(
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn is_interesting_with_perf<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
@ -50,13 +55,14 @@ where
|
|||||||
feedback_index: usize,
|
feedback_index: usize,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// Start a timer for this feedback
|
// Start a timer for this feedback
|
||||||
let start_time = crate::cpu::read_time_counter();
|
let start_time = crate::cpu::read_time_counter();
|
||||||
|
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let ret = self.is_interesting(state, input, observers, &exit_kind);
|
let ret = self.is_interesting(state, manager, input, observers, &exit_kind);
|
||||||
|
|
||||||
// Get the elapsed time for checking this feedback
|
// Get the elapsed time for checking this feedback
|
||||||
let elapsed = crate::cpu::read_time_counter() - start_time;
|
let elapsed = crate::cpu::read_time_counter() - start_time;
|
||||||
@ -124,29 +130,32 @@ where
|
|||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let a = self
|
let a = self
|
||||||
.first
|
.first
|
||||||
.is_interesting(state, input, observers, exit_kind)?;
|
.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
let b = self
|
let b = self
|
||||||
.second
|
.second
|
||||||
.is_interesting(state, input, observers, exit_kind)?;
|
.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
Ok(a && b)
|
Ok(a && b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
fn is_interesting_with_perf<OT>(
|
fn is_interesting_with_perf<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
@ -154,11 +163,13 @@ where
|
|||||||
feedback_index: usize,
|
feedback_index: usize,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = self.first.is_interesting_with_perf(
|
let a = self.first.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
|
manager,
|
||||||
input,
|
input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
@ -167,6 +178,7 @@ where
|
|||||||
)?;
|
)?;
|
||||||
let b = self.second.is_interesting_with_perf(
|
let b = self.second.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
|
manager,
|
||||||
input,
|
input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
@ -241,29 +253,32 @@ where
|
|||||||
B: Feedback<I, S>,
|
B: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
let a = self
|
let a = self
|
||||||
.first
|
.first
|
||||||
.is_interesting(state, input, observers, exit_kind)?;
|
.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
let b = self
|
let b = self
|
||||||
.second
|
.second
|
||||||
.is_interesting(state, input, observers, exit_kind)?;
|
.is_interesting(state, manager, input, observers, exit_kind)?;
|
||||||
Ok(a || b)
|
Ok(a || b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
fn is_interesting_with_perf<OT>(
|
fn is_interesting_with_perf<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
@ -271,11 +286,13 @@ where
|
|||||||
feedback_index: usize,
|
feedback_index: usize,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// Execute this feedback
|
// Execute this feedback
|
||||||
let a = self.first.is_interesting_with_perf(
|
let a = self.first.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
|
manager,
|
||||||
input,
|
input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
@ -284,6 +301,7 @@ where
|
|||||||
)?;
|
)?;
|
||||||
let b = self.second.is_interesting_with_perf(
|
let b = self.second.is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
|
manager,
|
||||||
input,
|
input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
@ -354,19 +372,21 @@ where
|
|||||||
A: Feedback<I, S>,
|
A: Feedback<I, S>,
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
Ok(!self
|
Ok(!self
|
||||||
.first
|
.first
|
||||||
.is_interesting(state, input, observers, exit_kind)?)
|
.is_interesting(state, manager, input, observers, exit_kind)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -442,14 +462,16 @@ impl<I, S> Feedback<I, S> for ()
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
Ok(false)
|
Ok(false)
|
||||||
@ -471,14 +493,16 @@ impl<I, S> Feedback<I, S> for CrashFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
if let ExitKind::Crash = exit_kind {
|
if let ExitKind::Crash = exit_kind {
|
||||||
@ -518,14 +542,16 @@ impl<I, S> Feedback<I, S> for TimeoutFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
_observers: &OT,
|
_observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
if let ExitKind::Timeout = exit_kind {
|
if let ExitKind::Timeout = exit_kind {
|
||||||
@ -570,14 +596,16 @@ impl<I, S> Feedback<I, S> for TimeFeedback
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
{
|
{
|
||||||
// TODO Replace with match_name_type when stable
|
// TODO Replace with match_name_type when stable
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bolts::current_time,
|
bolts::current_time,
|
||||||
corpus::{Corpus, CorpusScheduler, Testcase},
|
corpus::{Corpus, CorpusScheduler, Testcase},
|
||||||
events::{Event, EventManager},
|
events::{Event, EventFirer, EventManager},
|
||||||
executors::{
|
executors::{
|
||||||
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
Executor, ExitKind, HasExecHooks, HasExecHooksTuple, HasObservers, HasObserversHooks,
|
||||||
},
|
},
|
||||||
@ -69,15 +69,19 @@ where
|
|||||||
pub trait IsInteresting<I, OT, S>
|
pub trait IsInteresting<I, OT, S>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
OT: ObserversTuple,
|
||||||
|
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(
|
fn is_interesting<EM>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>;
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add to the state if interesting
|
/// Add to the state if interesting
|
||||||
@ -259,18 +263,19 @@ where
|
|||||||
S: HasCorpus<C, I>,
|
S: HasCorpus<C, I>,
|
||||||
{
|
{
|
||||||
/// Evaluate if a set of observation channels has an interesting state
|
/// Evaluate if a set of observation channels has an interesting state
|
||||||
fn is_interesting(
|
fn is_interesting<EM>(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
|
manager: &mut EM,
|
||||||
input: &I,
|
input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
exit_kind: &ExitKind,
|
exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error>
|
) -> Result<bool, Error>
|
||||||
where
|
where
|
||||||
OT: ObserversTuple,
|
EM: EventFirer<I, S>,
|
||||||
{
|
{
|
||||||
self.feedback_mut()
|
self.feedback_mut()
|
||||||
.is_interesting(state, input, observers, exit_kind)
|
.is_interesting(state, manager, input, observers, exit_kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -521,7 +526,7 @@ where
|
|||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
let is_interesting = self
|
let is_interesting = self
|
||||||
.feedback_mut()
|
.feedback_mut()
|
||||||
.is_interesting(state, &input, observers, &exit_kind)?;
|
.is_interesting(state, event_mgr, &input, observers, &exit_kind)?;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
let is_interesting = {
|
let is_interesting = {
|
||||||
@ -533,6 +538,7 @@ where
|
|||||||
let feedback_index = 0;
|
let feedback_index = 0;
|
||||||
let is_interesting = self.feedback_mut().is_interesting_with_perf(
|
let is_interesting = self.feedback_mut().is_interesting_with_perf(
|
||||||
state,
|
state,
|
||||||
|
event_mgr,
|
||||||
&input,
|
&input,
|
||||||
observers,
|
observers,
|
||||||
&exit_kind,
|
&exit_kind,
|
||||||
@ -552,7 +558,7 @@ where
|
|||||||
start_timer!(state);
|
start_timer!(state);
|
||||||
let is_solution = self
|
let is_solution = self
|
||||||
.objective_mut()
|
.objective_mut()
|
||||||
.is_interesting(state, &input, observers, &exit_kind)?;
|
.is_interesting(state, event_mgr, &input, observers, &exit_kind)?;
|
||||||
|
|
||||||
mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll);
|
mark_feature_time!(state, PerfFeature::GetObjectivesInterestingAll);
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
//! Keep stats, and dispaly them to the user. Usually used in a broker, or main node, of some sort.
|
//! Keep stats, and dispaly them to the user. Usually used in a broker, or main node, of some sort.
|
||||||
|
|
||||||
|
pub mod multi;
|
||||||
|
pub use multi::MultiStats;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::{string::String, vec::Vec};
|
||||||
use core::{time, time::Duration};
|
use core::{fmt, time, time::Duration};
|
||||||
|
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
@ -14,6 +19,30 @@ use crate::bolts::current_time;
|
|||||||
|
|
||||||
const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds
|
const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds
|
||||||
|
|
||||||
|
/// User-defined stats types
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum UserStats {
|
||||||
|
Number(u64),
|
||||||
|
String(String),
|
||||||
|
Ratio(u64, u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for UserStats {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
UserStats::Number(n) => write!(f, "{}", n),
|
||||||
|
UserStats::String(s) => write!(f, "{}", s),
|
||||||
|
UserStats::Ratio(a, b) => {
|
||||||
|
if *b == 0 {
|
||||||
|
write!(f, "{}/{}", a, b)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}/{} ({}%)", a, b, a * 100 / b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A simple struct to keep track of client stats
|
/// A simple struct to keep track of client stats
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct ClientStats {
|
pub struct ClientStats {
|
||||||
@ -30,6 +59,8 @@ pub struct ClientStats {
|
|||||||
pub last_window_time: time::Duration,
|
pub last_window_time: time::Duration,
|
||||||
/// The last executions per sec
|
/// The last executions per sec
|
||||||
pub last_execs_per_sec: f32,
|
pub last_execs_per_sec: f32,
|
||||||
|
/// User-defined stats
|
||||||
|
pub user_stats: HashMap<String, UserStats>,
|
||||||
|
|
||||||
/// Client performance statistics
|
/// Client performance statistics
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -90,6 +121,16 @@ impl ClientStats {
|
|||||||
self.last_execs_per_sec as u64
|
self.last_execs_per_sec as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the user-defined stat with name and value
|
||||||
|
pub fn update_user_stats(&mut self, name: String, value: UserStats) {
|
||||||
|
self.user_stats.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a user-defined stat using the name
|
||||||
|
pub fn get_user_stats(&mut self, name: &str) -> Option<&UserStats> {
|
||||||
|
self.user_stats.get(name)
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the current [`ClientPerfStats`] with the given [`ClientPerfStats`]
|
/// Update the current [`ClientPerfStats`] with the given [`ClientPerfStats`]
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
pub fn update_introspection_stats(&mut self, introspection_stats: ClientPerfStats) {
|
pub fn update_introspection_stats(&mut self, introspection_stats: ClientPerfStats) {
|
||||||
@ -109,7 +150,7 @@ pub trait Stats {
|
|||||||
fn start_time(&mut self) -> time::Duration;
|
fn start_time(&mut self) -> time::Duration;
|
||||||
|
|
||||||
/// show the stats to the user
|
/// show the stats to the user
|
||||||
fn display(&mut self, event_msg: String);
|
fn display(&mut self, event_msg: String, sender_id: u32);
|
||||||
|
|
||||||
/// Amount of elements in the corpus (combined for all children)
|
/// Amount of elements in the corpus (combined for all children)
|
||||||
fn corpus_size(&self) -> u64 {
|
fn corpus_size(&self) -> u64 {
|
||||||
@ -186,10 +227,11 @@ where
|
|||||||
self.start_time
|
self.start_time
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display(&mut self, event_msg: String) {
|
fn display(&mut self, event_msg: String, sender_id: u32) {
|
||||||
let fmt = format!(
|
let fmt = format!(
|
||||||
"[{}] clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
|
"[{} #{}] clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
|
||||||
event_msg,
|
event_msg,
|
||||||
|
sender_id,
|
||||||
self.client_stats().len(),
|
self.client_stats().len(),
|
||||||
self.corpus_size(),
|
self.corpus_size(),
|
||||||
self.objective_size(),
|
self.objective_size(),
|
||||||
|
115
libafl/src/stats/multi.rs
Normal file
115
libafl/src/stats/multi.rs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
//! Stats to disply both cumulative and per-client stats
|
||||||
|
|
||||||
|
use alloc::{string::String, vec::Vec};
|
||||||
|
use core::{time, time::Duration};
|
||||||
|
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
use alloc::string::ToString;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
bolts::current_time,
|
||||||
|
stats::{ClientStats, Stats},
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Tracking stats during fuzzing and display both per-client and cumulative info.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct MultiStats<F>
|
||||||
|
where
|
||||||
|
F: FnMut(String),
|
||||||
|
{
|
||||||
|
print_fn: F,
|
||||||
|
start_time: Duration,
|
||||||
|
corpus_size: usize,
|
||||||
|
client_stats: Vec<ClientStats>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> Stats for MultiStats<F>
|
||||||
|
where
|
||||||
|
F: FnMut(String),
|
||||||
|
{
|
||||||
|
/// the client stats, mutable
|
||||||
|
fn client_stats_mut(&mut self) -> &mut Vec<ClientStats> {
|
||||||
|
&mut self.client_stats
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the client stats
|
||||||
|
fn client_stats(&self) -> &[ClientStats] {
|
||||||
|
&self.client_stats
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Time this fuzzing run stated
|
||||||
|
fn start_time(&mut self) -> time::Duration {
|
||||||
|
self.start_time
|
||||||
|
}
|
||||||
|
|
||||||
|
fn display(&mut self, event_msg: String, sender_id: u32) {
|
||||||
|
let pad = if event_msg.len() < 9 {
|
||||||
|
" ".repeat(9 - event_msg.len())
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
};
|
||||||
|
let head = format!("{}{} #{}", event_msg, pad, sender_id);
|
||||||
|
let global_fmt = format!(
|
||||||
|
"[{}] (GLOBAL) clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
|
||||||
|
head,
|
||||||
|
self.client_stats().len(),
|
||||||
|
self.corpus_size(),
|
||||||
|
self.objective_size(),
|
||||||
|
self.total_execs(),
|
||||||
|
self.execs_per_sec()
|
||||||
|
);
|
||||||
|
(self.print_fn)(global_fmt);
|
||||||
|
|
||||||
|
let client = self.client_stats_mut_for(sender_id);
|
||||||
|
let cur_time = current_time();
|
||||||
|
let exec_sec = client.execs_per_sec(cur_time);
|
||||||
|
|
||||||
|
let pad = " ".repeat(head.len());
|
||||||
|
let mut fmt = format!(
|
||||||
|
" {} (CLIENT) corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
|
||||||
|
pad, client.corpus_size, client.objective_size, client.executions, exec_sec
|
||||||
|
);
|
||||||
|
for (key, val) in &client.user_stats {
|
||||||
|
fmt += &format!(", {}: {}", key, val);
|
||||||
|
}
|
||||||
|
(self.print_fn)(fmt);
|
||||||
|
|
||||||
|
// Only print perf stats if the feature is enabled
|
||||||
|
#[cfg(feature = "introspection")]
|
||||||
|
{
|
||||||
|
// Print the client performance stats. Skip the Client 0 which is the broker
|
||||||
|
for (i, client) in self.client_stats.iter().skip(1).enumerate() {
|
||||||
|
let fmt = format!("Client {:03}: {}", i + 1, client.introspection_stats);
|
||||||
|
(self.print_fn)(fmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separate the spacing just a bit
|
||||||
|
(self.print_fn)("\n".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F> MultiStats<F>
|
||||||
|
where
|
||||||
|
F: FnMut(String),
|
||||||
|
{
|
||||||
|
/// Creates the stats, using the `current_time` as `start_time`.
|
||||||
|
pub fn new(print_fn: F) -> Self {
|
||||||
|
Self {
|
||||||
|
print_fn,
|
||||||
|
start_time: current_time(),
|
||||||
|
corpus_size: 0,
|
||||||
|
client_stats: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates the stats with a given `start_time`.
|
||||||
|
pub fn with_time(print_fn: F, start_time: time::Duration) -> Self {
|
||||||
|
Self {
|
||||||
|
print_fn,
|
||||||
|
start_time,
|
||||||
|
corpus_size: 0,
|
||||||
|
client_stats: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_cc"
|
name = "libafl_cc"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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.1"
|
version = "0.3.2"
|
||||||
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.1"
|
version = "0.3.2"
|
||||||
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"
|
||||||
@ -15,7 +15,7 @@ cc = { version = "1.0", features = ["parallel"] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.3.1", features = ["std", "libafl_derive"] }
|
libafl = { path = "../libafl", version = "0.3.1", features = ["std", "libafl_derive"] }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.3.1" }
|
libafl_targets = { path = "../libafl_targets", version = "0.3.2" }
|
||||||
nix = "0.20.0"
|
nix = "0.20.0"
|
||||||
libc = "0.2.92"
|
libc = "0.2.92"
|
||||||
hashbrown = "0.11"
|
hashbrown = "0.11"
|
||||||
|
@ -14,6 +14,7 @@ use libafl::{
|
|||||||
tuples::Named,
|
tuples::Named,
|
||||||
},
|
},
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
|
events::EventFirer,
|
||||||
executors::{CustomExitKind, ExitKind, HasExecHooks},
|
executors::{CustomExitKind, ExitKind, HasExecHooks},
|
||||||
feedbacks::Feedback,
|
feedbacks::Feedback,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
@ -1777,13 +1778,18 @@ impl<I, S> Feedback<I, S> for AsanErrorsFeedback
|
|||||||
where
|
where
|
||||||
I: Input + HasTargetBytes,
|
I: Input + HasTargetBytes,
|
||||||
{
|
{
|
||||||
fn is_interesting<OT: ObserversTuple>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
_exit_kind: &ExitKind,
|
_exit_kind: &ExitKind,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error>
|
||||||
|
where
|
||||||
|
EM: EventFirer<I, S>,
|
||||||
|
OT: ObserversTuple,
|
||||||
|
{
|
||||||
let observer = observers
|
let observer = observers
|
||||||
.match_name::<AsanErrorsObserver>("AsanErrors")
|
.match_name::<AsanErrorsObserver>("AsanErrors")
|
||||||
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
.expect("An AsanErrorsFeedback needs an AsanErrorsObserver");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "libafl_targets"
|
name = "libafl_targets"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
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.1", features = [] }
|
libafl = { path = "../libafl", version = "0.3.2", 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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user