From b7fcfdd192b5d7be65393a2caacb422952a1c01c Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 11 Feb 2025 02:40:53 +0100 Subject: [PATCH] Change combine_monitors macro to be tuple_list of Monitors (#2963) * Make Monitors tuple_list * fix * no_std * unused * more --- MIGRATION.md | 14 ++-- .../libfuzzer_libpng_launcher/src/lib.rs | 3 +- .../libfuzzer_libpng_norestart/src/lib.rs | 3 +- libafl/src/monitors/mod.rs | 70 ++++++++++--------- 4 files changed, 48 insertions(+), 42 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 5cc832d788..1a10f84e25 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,7 +1,9 @@ -# 0.15.0 -> 0.16.0 +# Migration Notes For LibAFL Versions + +## 0.15.0 -> 0.16.0 - `EventManager` is refactored to avoid calling function from `Fuzzer`, thus we do not evaluate testcases in `EventManager` anymore. - - Now we have `EventReceiver` in `events` module, and `EventProessor` in `fuzzer` module. + - Now we have `EventReceiver` in `events` module, and `EventProcessor` in `fuzzer` module. - `EventReceiver` is responsible for receiving testcases and delegates its evaluation to `EventProcessor`. - `EventProcessor` is responsible for evaluating the testcases passed by the `EventReceiver`. - Since we don't evaluate testcases in the `EventManager` anymore. `on_fire` and `post_exec` have been deleted from `EventManagerHook`. @@ -10,9 +12,9 @@ - `Monitor` is refactored. Most statistics have been extracted into an individual `stats` module under `monitors`. - 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`, `introspection_monitor` has been renamed to `introspection_stats`, perf-related structure definitions have been renamed, and all were moved to the `stats` module. - - `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!`. + - `OnDiskTomlMonitor`, `OnDiskJsonMonitor`, `OnDiskJsonAggregateMonitor` are now no longer takes a base monitor to wrap. If you want to use multiple monitors together, simply use a `tuple_list`. -# 0.14.1 -> 0.15.0 +## 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. - The closure passed to a `DumpToDiskStage` now provides the `Testcase` instead of just the `Input`. @@ -35,11 +37,11 @@ - Restrictions from certain schedulers and stages that required their inner observer to implement `MapObserver` have been lifted in favor of requiring `Hash` - Related: removed `hash_simple` from `MapObserver` -# 0.14.0 -> 0.15.0 +## 0.14.0 -> 0.15.0 - Removed `with_observers` from `Executor` trait. - `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;` -# Pre 0.9 -> 0.9 +## Pre 0.9 -> 0.9 - [Migrating from LibAFL <0.9 to 0.9](https://aflplus.plus/libafl-book/design/migration-0.9.html) \ No newline at end of file diff --git a/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs index 2c6e84362d..d76d5f9f05 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_launcher/src/lib.rs @@ -7,7 +7,6 @@ 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}, @@ -141,7 +140,7 @@ pub extern "C" fn libafl_main() { let shmem_provider = StdShMemProvider::new().expect("Failed to init shared memory"); - let monitor = combine_monitor!( + let monitor = tuple_list!( OnDiskTomlMonitor::new("./fuzzer_stats.toml"), MultiMonitor::new(|s| println!("{s}")) ); diff --git a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs index 2bf2d4c640..684d616f76 100644 --- a/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs +++ b/fuzzers/inprocess/libfuzzer_libpng_norestart/src/lib.rs @@ -8,7 +8,6 @@ use std::{env, net::SocketAddr, path::PathBuf}; use clap::Parser; use libafl::{ - combine_monitor, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, events::{ launcher::{ClientDescription, Launcher}, @@ -157,7 +156,7 @@ pub extern "C" fn libafl_main() { let shmem_provider = MmapShMemProvider::new().expect("Failed to init shared memory"); - let monitor = combine_monitor!( + let monitor = tuple_list!( OnDiskTomlMonitor::new("./fuzzer_stats.toml"), MultiMonitor::new(|s| println!("{s}")) ); diff --git a/libafl/src/monitors/mod.rs b/libafl/src/monitors/mod.rs index 75e79fbaac..780cf4d35a 100644 --- a/libafl/src/monitors/mod.rs +++ b/libafl/src/monitors/mod.rs @@ -261,45 +261,51 @@ macro_rules! mark_feedback_time { }}; } -// The client stats of first and second monitor will always be maintained -// to be consistent -/// A combined monitor consisting of multiple [`Monitor`]s. -#[derive(Debug, Clone)] -pub struct CombinedMonitor { - first: A, - second: B, -} - -impl CombinedMonitor { - /// Create a new combined monitor - pub fn new(first: A, second: B) -> Self { - Self { first, second } - } -} - -impl Monitor for CombinedMonitor { +impl Monitor for (A, B) { fn display( &mut self, client_stats_manager: &mut ClientStatsManager, event_msg: &str, sender_id: ClientId, ) { - self.first - .display(client_stats_manager, event_msg, sender_id); - self.second - .display(client_stats_manager, event_msg, sender_id); + self.0.display(client_stats_manager, event_msg, sender_id); + self.1.display(client_stats_manager, event_msg, sender_id); } } -/// Variadic macro to create a chain of [`Monitor`] -#[macro_export] -macro_rules! combine_monitor { - ( $last:expr ) => { $last }; - - ( $last:expr, ) => { $last }; - - ( $head:expr, $($tail:expr),+ $(,)?) => { - // recursive call - $crate::monitors::CombinedMonitor::new($head , $crate::combine_monitor!($($tail),+)) - }; +impl Monitor for (A, ()) { + fn display( + &mut self, + client_stats_manager: &mut ClientStatsManager, + event_msg: &str, + sender_id: ClientId, + ) { + self.0.display(client_stats_manager, event_msg, sender_id); + } +} + +#[cfg(test)] +mod test { + use libafl_bolts::ClientId; + use tuple_list::tuple_list; + + use super::{stats::ClientStatsManager, Monitor, NopMonitor, SimpleMonitor}; + + #[test] + fn test_monitor_tuple_list() { + let mut client_stats = ClientStatsManager::new(); + let mut mgr_list = tuple_list!( + SimpleMonitor::new(|_msg| { + #[cfg(feature = "std")] + println!("{_msg}"); + }), + SimpleMonitor::new(|_msg| { + #[cfg(feature = "std")] + println!("{_msg}"); + }), + NopMonitor::default(), + NopMonitor::default(), + ); + mgr_list.display(&mut client_stats, "test", ClientId(0)); + } }