LIBAFL_DEBUG_OUTPUT in Launcher and OnDiskTOMLMonitor to create fuzzer_stats (#666)
* LIBAFL_DEBUG_OUTPUT in launcher on unix * OnDiskTOMLMonitor * fix * clp * clippy * fix * fix * allow all Co-authored-by: tokatoka <tokazerkje@outlook.com>
This commit is contained in:
parent
2e746bf439
commit
323b8e23ee
1
fuzzers/libfuzzer_libpng_launcher/.gitignore
vendored
1
fuzzers/libfuzzer_libpng_launcher/.gitignore
vendored
@ -1 +1,2 @@
|
||||
fuzzer_stats.toml
|
||||
libpng-*
|
@ -27,7 +27,7 @@ use libafl::{
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::tui::TuiMonitor,
|
||||
monitors::{MultiMonitor, OnDiskTOMLMonitor},
|
||||
mutators::scheduled::{havoc_mutations, tokens_mutations, StdScheduledMutator},
|
||||
mutators::token_mutations::Tokens,
|
||||
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||
@ -139,7 +139,10 @@ pub fn libafl_main() {
|
||||
|
||||
let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory");
|
||||
|
||||
let monitor = TuiMonitor::new("Test fuzzer on libpng".into(), true);
|
||||
let monitor = OnDiskTOMLMonitor::new(
|
||||
"./fuzzer_stats.toml",
|
||||
MultiMonitor::new(|s| println!("{}", s)),
|
||||
);
|
||||
|
||||
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
|
@ -142,6 +142,9 @@ where
|
||||
.stdout_file
|
||||
.map(|filename| File::create(filename).unwrap());
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
let debug_output = std::env::var("LIBAFL_DEBUG_OUTPUT").is_ok();
|
||||
|
||||
// Spawn clients
|
||||
let mut index = 0_u64;
|
||||
for (id, bind_to) in core_ids.iter().enumerate().take(num_cores) {
|
||||
@ -163,10 +166,13 @@ where
|
||||
std::thread::sleep(std::time::Duration::from_millis(index * 100));
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
if let Some(file) = stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
if !debug_output {
|
||||
if let Some(file) = stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Fuzzer client. keeps retrying the connection to broker till the broker starts
|
||||
let (state, mgr) = RestartingMgr::<I, MT, OT, S, SP>::builder()
|
||||
.shmem_provider(self.shmem_provider.clone())
|
||||
|
@ -205,7 +205,7 @@ where
|
||||
|
||||
fn shmem_from_id_and_size(&mut self, id: ShMemId, size: usize) -> Result<Self::ShMem, Error> {
|
||||
let parts = id.as_str().split(':').collect::<Vec<&str>>();
|
||||
let server_id_str = parts.get(0).unwrap();
|
||||
let server_id_str = parts.first().unwrap();
|
||||
let (server_fd, client_fd) = self.send_receive(ServedShMemRequest::ExistingMap(
|
||||
ShMemDescription::from_string_and_size(server_id_str, size),
|
||||
))?;
|
||||
@ -431,7 +431,8 @@ where
|
||||
// It's either running at this point, or we won't be able to spawn it anyway.
|
||||
env::set_var(AFL_SHMEM_SERVICE_STARTED, "true");
|
||||
|
||||
match *success {
|
||||
let status = *success;
|
||||
match status {
|
||||
ShMemServiceStatus::Starting => panic!("Unreachable"),
|
||||
ShMemServiceStatus::Started => {
|
||||
println!("Started ShMem Service");
|
||||
|
@ -332,6 +332,8 @@ where
|
||||
name: String,
|
||||
/// Name identifier of the observer
|
||||
observer_name: String,
|
||||
/// Name of the feedback as shown in the `UserStats`
|
||||
stats_name: String,
|
||||
/// Phantom Data of Reducer
|
||||
phantom: PhantomData<(I, N, S, R, O, T)>,
|
||||
}
|
||||
@ -416,7 +418,7 @@ where
|
||||
manager.fire(
|
||||
state,
|
||||
Event::UpdateUserStats {
|
||||
name: self.name.to_string(),
|
||||
name: self.stats_name.to_string(),
|
||||
value: UserStats::Ratio(filled, size as u64),
|
||||
phantom: PhantomData,
|
||||
},
|
||||
@ -480,6 +482,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn create_stats_name(name: &str) -> String {
|
||||
name.to_lowercase()
|
||||
}
|
||||
|
||||
impl<I, N, O, R, S, T> MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
@ -497,6 +503,7 @@ where
|
||||
novelties: None,
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
stats_name: create_stats_name(map_observer.name()),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -509,6 +516,7 @@ where
|
||||
novelties: if track_novelties { Some(vec![]) } else { None },
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
stats_name: create_stats_name(map_observer.name()),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -521,6 +529,7 @@ where
|
||||
novelties: None,
|
||||
name: name.to_string(),
|
||||
observer_name: observer_name.to_string(),
|
||||
stats_name: create_stats_name(name),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@ -537,6 +546,7 @@ where
|
||||
indexes: if track_indexes { Some(vec![]) } else { None },
|
||||
novelties: if track_novelties { Some(vec![]) } else { None },
|
||||
observer_name: observer_name.to_string(),
|
||||
stats_name: create_stats_name(name),
|
||||
name: name.to_string(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
|
136
libafl/src/monitors/disk.rs
Normal file
136
libafl/src/monitors/disk.rs
Normal file
@ -0,0 +1,136 @@
|
||||
//! Monitors that wrap a base one and log on disk
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::time::Duration;
|
||||
|
||||
use crate::{
|
||||
bolts::{current_time, format_duration_hms},
|
||||
monitors::{ClientStats, Monitor, NopMonitor},
|
||||
};
|
||||
|
||||
use std::{fs::File, io::Write, path::PathBuf};
|
||||
|
||||
/// Wrap a monitor and log the current state of the monitor into a TOML file.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct OnDiskTOMLMonitor<M>
|
||||
where
|
||||
M: Monitor,
|
||||
{
|
||||
base: M,
|
||||
filename: PathBuf,
|
||||
last_update: Duration,
|
||||
}
|
||||
|
||||
impl<M> Monitor for OnDiskTOMLMonitor<M>
|
||||
where
|
||||
M: Monitor,
|
||||
{
|
||||
/// The client monitor, mutable
|
||||
fn client_stats_mut(&mut self) -> &mut Vec<ClientStats> {
|
||||
self.base.client_stats_mut()
|
||||
}
|
||||
|
||||
/// The client monitor
|
||||
fn client_stats(&self) -> &[ClientStats] {
|
||||
self.base.client_stats()
|
||||
}
|
||||
|
||||
/// Time this fuzzing run stated
|
||||
fn start_time(&mut self) -> Duration {
|
||||
self.base.start_time()
|
||||
}
|
||||
|
||||
fn display(&mut self, event_msg: String, sender_id: u32) {
|
||||
let cur_time = current_time();
|
||||
|
||||
if (cur_time - self.last_update).as_secs() >= 60 {
|
||||
self.last_update = cur_time;
|
||||
|
||||
let mut file = File::create(&self.filename).expect("Failed to open the TOML file");
|
||||
write!(
|
||||
&mut file,
|
||||
"# This TOML is generated using the OnDiskMonitor component of LibAFL
|
||||
|
||||
[global]
|
||||
run_time = \"{}\"
|
||||
clients = {}
|
||||
corpus = {}
|
||||
objectives = {}
|
||||
executions = {}
|
||||
exec_sec = {}
|
||||
",
|
||||
format_duration_hms(&(cur_time - self.start_time())),
|
||||
self.client_stats().len(),
|
||||
self.corpus_size(),
|
||||
self.objective_size(),
|
||||
self.total_execs(),
|
||||
self.execs_per_sec()
|
||||
)
|
||||
.expect("Failed to write to the TOML file");
|
||||
|
||||
for (i, client) in self.client_stats_mut().iter_mut().skip(1).enumerate() {
|
||||
let exec_sec = client.execs_per_sec(cur_time);
|
||||
|
||||
write!(
|
||||
&mut file,
|
||||
"
|
||||
[client_{}]
|
||||
corpus = {}
|
||||
objectives = {}
|
||||
executions = {}
|
||||
exec_sec = {}
|
||||
",
|
||||
i + 1,
|
||||
client.corpus_size,
|
||||
client.objective_size,
|
||||
client.executions,
|
||||
exec_sec
|
||||
)
|
||||
.expect("Failed to write to the TOML file");
|
||||
|
||||
for (key, val) in &client.user_monitor {
|
||||
let k: String = key
|
||||
.chars()
|
||||
.map(|c| if c.is_whitespace() { '_' } else { c })
|
||||
.filter(|c| c.is_alphanumeric() || *c == '_')
|
||||
.collect();
|
||||
writeln!(&mut file, "{} = \"{}\"", k, val)
|
||||
.expect("Failed to write to the TOML file");
|
||||
}
|
||||
}
|
||||
|
||||
drop(file);
|
||||
}
|
||||
|
||||
self.base.display(event_msg, sender_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> OnDiskTOMLMonitor<M>
|
||||
where
|
||||
M: Monitor,
|
||||
{
|
||||
/// Create new [`OnDiskTOMLMonitor`]
|
||||
#[must_use]
|
||||
pub fn new<P>(filename: P, base: M) -> Self
|
||||
where
|
||||
P: Into<PathBuf>,
|
||||
{
|
||||
Self {
|
||||
base,
|
||||
filename: filename.into(),
|
||||
last_update: current_time(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OnDiskTOMLMonitor<NopMonitor> {
|
||||
/// Create new [`OnDiskTOMLMonitor`] without a base
|
||||
#[must_use]
|
||||
pub fn nop<P>(filename: P) -> Self
|
||||
where
|
||||
P: Into<PathBuf>,
|
||||
{
|
||||
Self::new(filename, NopMonitor::new())
|
||||
}
|
||||
}
|
@ -7,6 +7,11 @@ pub use multi::MultiMonitor;
|
||||
#[allow(missing_docs)]
|
||||
pub mod tui;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod disk;
|
||||
#[cfg(feature = "std")]
|
||||
pub use disk::OnDiskTOMLMonitor;
|
||||
|
||||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
|
@ -813,9 +813,10 @@ pub mod pybind {
|
||||
}
|
||||
|
||||
#[pyo3(name = "match_name")]
|
||||
#[allow(clippy::all)]
|
||||
fn pymatch_name(&self, name: &str) -> Option<PythonObserver> {
|
||||
for ob in &self.list {
|
||||
if ob.name() == name {
|
||||
if *ob.name() == *name {
|
||||
return Some(ob.clone());
|
||||
}
|
||||
}
|
||||
|
@ -155,8 +155,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<E, EM, I, S, Z>
|
||||
SyncFromDiskStage<fn(&mut Z, &mut S, &Path) -> Result<I, Error>, E, EM, I, S, Z>
|
||||
/// Function type when the callback in `SyncFromDiskStage` is not a lambda
|
||||
pub type SyncFromDiskFunction<I, S, Z> = fn(&mut Z, &mut S, &Path) -> Result<I, Error>;
|
||||
|
||||
impl<E, EM, I, S, Z> SyncFromDiskStage<SyncFromDiskFunction<I, S, Z>, E, EM, I, S, Z>
|
||||
where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor + HasCorpus<I> + HasRand + HasMetadata,
|
||||
|
@ -381,7 +381,7 @@ mod tests {
|
||||
edge = cfg.get_edge((41864 >> 1) ^ 26911).unwrap();
|
||||
assert_eq!(edge.calling_func, "main");
|
||||
assert_eq!(edge.successor_edges.len(), 2);
|
||||
assert_eq!(*edge.successor_edges.get(0).unwrap(), (26911 >> 1) ^ 52706);
|
||||
assert_eq!(*edge.successor_edges.first().unwrap(), (26911 >> 1) ^ 52706);
|
||||
|
||||
assert!(cfg.get_edge(26911).is_none());
|
||||
assert!(cfg.get_edge(41864).is_some());
|
||||
|
Loading…
x
Reference in New Issue
Block a user