Change combine_monitors macro to be tuple_list of Monitors (#2963)

* Make Monitors tuple_list

* fix

* no_std

* unused

* more
This commit is contained in:
Dominik Maier 2025-02-11 02:40:53 +01:00 committed by GitHub
parent c62c6a7ecc
commit b7fcfdd192
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 42 deletions

View File

@ -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<Path>` 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)

View File

@ -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}"))
);

View File

@ -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}"))
);

View File

@ -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<A, B> {
first: A,
second: B,
}
impl<A: Monitor, B: Monitor> CombinedMonitor<A, B> {
/// Create a new combined monitor
pub fn new(first: A, second: B) -> Self {
Self { first, second }
}
}
impl<A: Monitor, B: Monitor> Monitor for CombinedMonitor<A, B> {
impl<A: Monitor, B: Monitor> 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<A: Monitor> 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));
}
}