From abe955137fb126b72b139f251c44fe9a2c1ffbd2 Mon Sep 17 00:00:00 2001 From: EvianZhang Date: Sat, 8 Feb 2025 21:08:00 +0800 Subject: [PATCH] Remove base-pattern for Monitor (#2953) * Remove base-pattern for Monitor * Fix runtime parameter for log_record --------- Co-authored-by: Dongjia "toka" Zhang --- MIGRATION.md | 1 + .../libfuzzer_libpng_launcher/src/lib.rs | 7 +- .../libfuzzer_libpng_norestart/src/lib.rs | 7 +- libafl/src/monitors/disk.rs | 76 ++++++------------- libafl/src/monitors/disk_aggregate.rs | 33 +++----- 5 files changed, 44 insertions(+), 80 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 0b356b0ed6..3569cb1d4f 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -10,6 +10,7 @@ - There is a `ClientStatsManager` to manage client statistics, and is owned by `EventManager`. Most of previous `Monitor`'s trait methods have been moved to the `ClientStatsManager`. - `user_monitor` has been renamed to `user_stats`, and its structure definitions have been moved to `statistics` module as well. - `introspection_monitor` has been renamed to `introspection_stats`, and perf-related structure definitions have been renamed and moved to `statistics` module as well. + - `OnDiskTomlMonitor`, `OnDiskJsonMonitor`, `OnDiskJsonAggregateMonitor` are now no longer takes a base monitor to wrap. If you want to use multiple monitors together, use `libafl::combine_monitor!`. # 0.14.1 -> 0.15.0 - `MmapShMem::new` and `MmapShMemProvider::new_shmem_with_id` now take `AsRef` instead of a byte array for the filename/id. diff --git a/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs index 0c512e87de..2c6e84362d 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs @@ -7,6 +7,7 @@ use std::{env, net::SocketAddr, path::PathBuf}; use clap::{self, Parser}; use libafl::{ + combine_monitor, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, events::{launcher::Launcher, EventConfig}, executors::{inprocess::InProcessExecutor, ExitKind}, @@ -140,9 +141,9 @@ pub extern "C" fn libafl_main() { let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory"); - let monitor = OnDiskTomlMonitor::new( - "./fuzzer_stats.toml", - MultiMonitor::new(|s| println!("{s}")), + let monitor = combine_monitor!( + OnDiskTomlMonitor::new("./fuzzer_stats.toml"), + MultiMonitor::new(|s| println!("{s}")) ); let mut run_client = |state: Option<_>, mut restarting_mgr, _client_description| { diff --git a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs index 5a195930c9..2bf2d4c640 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs @@ -8,6 +8,7 @@ use std::{env, net::SocketAddr, path::PathBuf}; use clap::Parser; use libafl::{ + combine_monitor, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::{ launcher::{ClientDescription, Launcher}, @@ -156,9 +157,9 @@ pub extern "C" fn libafl_main() { let shmem_provider = MmapShMemProvider::new().expect("Failed to init shared memory"); - let monitor = OnDiskTomlMonitor::new( - "./fuzzer_stats.toml", - MultiMonitor::new(|s| println!("{s}")), + let monitor = combine_monitor!( + OnDiskTomlMonitor::new("./fuzzer_stats.toml"), + MultiMonitor::new(|s| println!("{s}")) ); let mut run_client = |state: Option<_>, diff --git a/libafl/src/monitors/disk.rs b/libafl/src/monitors/disk.rs index b8e8e47ba8..15099d3342 100644 --- a/libafl/src/monitors/disk.rs +++ b/libafl/src/monitors/disk.rs @@ -1,4 +1,4 @@ -//! Monitors that wrap a base monitor and also log to disk using different formats like `JSON` and `TOML`. +//! Monitors that log to disk using different formats like `JSON` and `TOML`. use alloc::string::String; use core::time::Duration; @@ -11,32 +11,22 @@ use std::{ use libafl_bolts::{current_time, format_duration_hms, ClientId}; use serde_json::json; -use crate::{ - monitors::{Monitor, NopMonitor}, - statistics::manager::ClientStatsManager, -}; +use crate::{monitors::Monitor, statistics::manager::ClientStatsManager}; /// Wrap a monitor and log the current state of the monitor into a Toml file. #[derive(Debug, Clone)] -pub struct OnDiskTomlMonitor -where - M: Monitor, -{ - base: M, +pub struct OnDiskTomlMonitor { filename: PathBuf, last_update: Duration, update_interval: Duration, } -impl Monitor for OnDiskTomlMonitor -where - M: Monitor, -{ +impl Monitor for OnDiskTomlMonitor { fn display( &mut self, client_stats_manager: &mut ClientStatsManager, - event_msg: &str, - sender_id: ClientId, + _event_msg: &str, + _sender_id: ClientId, ) { let cur_time = current_time(); @@ -100,33 +90,26 @@ exec_sec = {} drop(file); } - - self.base - .display(client_stats_manager, event_msg, sender_id); } } -impl OnDiskTomlMonitor -where - M: Monitor, -{ +impl OnDiskTomlMonitor { /// Create new [`OnDiskTomlMonitor`] #[must_use] - pub fn new

(filename: P, base: M) -> Self + pub fn new

(filename: P) -> Self where P: Into, { - Self::with_update_interval(filename, base, Duration::from_secs(60)) + Self::with_update_interval(filename, Duration::from_secs(60)) } /// Create new [`OnDiskTomlMonitor`] with custom update interval #[must_use] - pub fn with_update_interval

(filename: P, base: M, update_interval: Duration) -> Self + pub fn with_update_interval

(filename: P, update_interval: Duration) -> Self where P: Into, { Self { - base, filename: filename.into(), last_update: current_time() - update_interval, update_interval, @@ -134,62 +117,55 @@ where } } -impl OnDiskTomlMonitor { +impl OnDiskTomlMonitor { /// Create new [`OnDiskTomlMonitor`] without a base #[must_use] + #[deprecated(since = "0.16.0", note = "Use new directly")] pub fn nop

(filename: P) -> Self where P: Into, { - Self::new(filename, NopMonitor::new()) + Self::new(filename) } } #[derive(Debug, Clone)] -/// Wraps a base monitor and continuously appends the current statistics to a Json lines file. -pub struct OnDiskJsonMonitor +/// Continuously appends the current statistics to a Json lines file. +pub struct OnDiskJsonMonitor where - F: FnMut(&mut M) -> bool, - M: Monitor, + F: FnMut(&mut ClientStatsManager) -> bool, { - base: M, path: PathBuf, /// A function that has the current runtime as argument and decides, whether a record should be logged log_record: F, } -impl OnDiskJsonMonitor +impl OnDiskJsonMonitor where - F: FnMut(&mut M) -> bool, - M: Monitor, + F: FnMut(&mut ClientStatsManager) -> bool, { /// Create a new [`OnDiskJsonMonitor`] - pub fn new

(filename: P, base: M, log_record: F) -> Self + pub fn new

(filename: P, log_record: F) -> Self where P: Into, { let path = filename.into(); - Self { - base, - path, - log_record, - } + Self { path, log_record } } } -impl Monitor for OnDiskJsonMonitor +impl Monitor for OnDiskJsonMonitor where - F: FnMut(&mut M) -> bool, - M: Monitor, + F: FnMut(&mut ClientStatsManager) -> bool, { fn display( &mut self, client_stats_manager: &mut ClientStatsManager, - event_msg: &str, - sender_id: ClientId, + _event_msg: &str, + _sender_id: ClientId, ) { - if (self.log_record)(&mut self.base) { + if (self.log_record)(client_stats_manager) { let file = OpenOptions::new() .append(true) .create(true) @@ -207,7 +183,5 @@ where }); writeln!(&file, "{line}").expect("Unable to write Json to file"); } - self.base - .display(client_stats_manager, event_msg, sender_id); } } diff --git a/libafl/src/monitors/disk_aggregate.rs b/libafl/src/monitors/disk_aggregate.rs index 9ffc0619f6..e9037d36ea 100644 --- a/libafl/src/monitors/disk_aggregate.rs +++ b/libafl/src/monitors/disk_aggregate.rs @@ -11,22 +11,17 @@ use serde_json::json; use crate::{monitors::Monitor, statistics::manager::ClientStatsManager}; -/// A monitor that wraps another monitor and logs aggregated stats to a JSON file. +/// A monitor that logs aggregated stats to a JSON file. #[derive(Clone)] -pub struct OnDiskJsonAggregateMonitor { - base: M, +pub struct OnDiskJsonAggregateMonitor { json_path: PathBuf, last_update: Duration, update_interval: Duration, } -impl Debug for OnDiskJsonAggregateMonitor -where - M: Debug, -{ +impl Debug for OnDiskJsonAggregateMonitor { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { f.debug_struct("OnDiskJsonAggregateMonitor") - .field("base", &self.base) .field("last_update", &self.last_update) .field("update_interval", &self.update_interval) .field("json_path", &self.json_path) @@ -34,20 +29,13 @@ where } } -impl Monitor for OnDiskJsonAggregateMonitor -where - M: Monitor, -{ +impl Monitor for OnDiskJsonAggregateMonitor { fn display( &mut self, client_stats_manager: &mut ClientStatsManager, - event_msg: &str, - sender_id: ClientId, + _event_msg: &str, + _sender_id: ClientId, ) { - // First let the base monitor handle its display - self.base - .display(client_stats_manager, event_msg, sender_id); - // Write JSON stats if update interval has elapsed let cur_time = current_time(); if cur_time - self.last_update >= self.update_interval { @@ -83,22 +71,21 @@ where } } -impl OnDiskJsonAggregateMonitor { +impl OnDiskJsonAggregateMonitor { /// Creates a new [`OnDiskJsonAggregateMonitor`] - pub fn new

(base: M, json_path: P) -> Self + pub fn new

(json_path: P) -> Self where P: Into, { - Self::with_interval(json_path, base, Duration::from_secs(10)) + Self::with_interval(json_path, Duration::from_secs(10)) } /// Creates a new [`OnDiskJsonAggregateMonitor`] with custom update interval - pub fn with_interval

(json_path: P, base: M, update_interval: Duration) -> Self + pub fn with_interval

(json_path: P, update_interval: Duration) -> Self where P: Into, { Self { - base, json_path: json_path.into(), last_update: current_time() - update_interval, update_interval,