use alloc::vec::Vec;
use core::{fmt::Debug, marker::PhantomData, time::Duration};
#[cfg(feature = "std")]
use hashbrown::HashMap;
use libafl_bolts::ClientId;
#[cfg(feature = "std")]
use libafl_bolts::shmem::ShMemProvider;
#[cfg(feature = "std")]
use serde::Serialize;
#[cfg(feature = "std")]
use serde::de::DeserializeOwned;
use super::{AwaitRestartSafe, EventWithStats, ProgressReporter, std_on_restart};
use crate::{
Error, HasMetadata,
events::{
BrokerEventResult, Event, EventFirer, EventManagerId, EventReceiver, EventRestarter,
HasEventManagerId, SendExiting, std_maybe_report_progress, std_report_progress,
},
monitors::{Monitor, stats::ClientStatsManager},
state::{
HasCurrentStageId, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable,
},
};
#[cfg(feature = "std")]
use crate::{
events::RestartingMgr,
monitors::{SimplePrintingMonitor, stats::ClientStats},
state::HasSolutions,
};
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
const _ENV_FUZZER_RECEIVER: &str = "_AFL_ENV_FUZZER_RECEIVER";
const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
pub struct SimpleEventManager<I, MT, S> {
monitor: MT,
events: Vec<EventWithStats<I>>,
phantom: PhantomData<S>,
client_stats_manager: ClientStatsManager,
}
impl<I, MT, S> Debug for SimpleEventManager<I, MT, S>
where
MT: Debug,
I: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SimpleEventManager")
.field("monitor", &self.monitor)
.field("events", &self.events)
.finish_non_exhaustive()
}
}
impl<I, MT, S> EventFirer<I, S> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: Stoppable,
{
fn should_send(&self) -> bool {
true
}
fn fire(&mut self, _state: &mut S, event: EventWithStats<I>) -> Result<(), Error> {
match Self::handle_in_broker(&mut self.monitor, &mut self.client_stats_manager, &event)? {
BrokerEventResult::Forward => self.events.push(event),
BrokerEventResult::Handled => (),
}
Ok(())
}
}
impl<I, MT, S> SendExiting for SimpleEventManager<I, MT, S> {
fn send_exiting(&mut self) -> Result<(), Error> {
Ok(())
}
fn on_shutdown(&mut self) -> Result<(), Error> {
self.send_exiting()
}
}
impl<I, MT, S> AwaitRestartSafe for SimpleEventManager<I, MT, S> {
fn await_restart_safe(&mut self) {}
}
impl<I, MT, S> EventRestarter<S> for SimpleEventManager<I, MT, S>
where
S: HasCurrentStageId,
{
fn on_restart(&mut self, state: &mut S) -> Result<(), Error> {
std_on_restart(self, state)
}
}
impl<I, MT, S> EventReceiver<I, S> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: Stoppable,
{
fn try_receive(&mut self, state: &mut S) -> Result<Option<(EventWithStats<I>, bool)>, Error> {
while let Some(event) = self.events.pop() {
match event.event() {
Event::Stop => {
state.request_stop();
}
_ => {
return Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {event:?}."
)));
}
}
}
Ok(None)
}
fn on_interesting(
&mut self,
_state: &mut S,
_event_vec: EventWithStats<I>,
) -> Result<(), Error> {
Ok(())
}
}
impl<I, MT, S> ProgressReporter<S> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: HasMetadata + HasExecutions + HasLastReportTime + Stoppable + MaybeHasClientPerfMonitor,
{
fn maybe_report_progress(
&mut self,
state: &mut S,
monitor_timeout: Duration,
) -> Result<(), Error> {
std_maybe_report_progress(self, state, monitor_timeout)
}
fn report_progress(&mut self, state: &mut S) -> Result<(), Error> {
std_report_progress(self, state)
}
}
impl<I, MT, S> HasEventManagerId for SimpleEventManager<I, MT, S> {
fn mgr_id(&self) -> EventManagerId {
EventManagerId(0)
}
}
#[cfg(feature = "std")]
impl<I, S> SimpleEventManager<I, SimplePrintingMonitor, S>
where
I: Debug,
S: Stoppable,
{
#[must_use]
pub fn printing() -> Self {
Self::new(SimplePrintingMonitor::new())
}
}
impl<I, MT, S> SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: Stoppable,
{
pub fn new(monitor: MT) -> Self {
Self {
monitor,
events: vec![],
client_stats_manager: ClientStatsManager::default(),
phantom: PhantomData,
}
}
fn handle_in_broker(
monitor: &mut MT,
client_stats_manager: &mut ClientStatsManager,
event: &EventWithStats<I>,
) -> Result<BrokerEventResult, Error> {
let stats = event.stats();
client_stats_manager.client_stats_insert(ClientId(0))?;
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_executions(stats.executions, stats.time);
})?;
let event = event.event();
match event {
Event::NewTestcase { corpus_size, .. } => {
client_stats_manager.client_stats_insert(ClientId(0))?;
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_corpus_size(*corpus_size as u64);
})?;
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
Event::Heartbeat => {
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
Event::UpdateUserStats { name, value, .. } => {
client_stats_manager.client_stats_insert(ClientId(0))?;
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_user_stats(name.clone(), value.clone());
})?;
client_stats_manager.aggregate(name);
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
Event::UpdateUserStatsMap { stats, .. } => {
client_stats_manager.client_stats_insert(ClientId(0))?;
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
for (name, value) in stats {
client_stat.update_user_stats(name.clone(), value.clone());
}
})?;
for name in stats.keys() {
client_stats_manager.aggregate(name);
}
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
#[cfg(feature = "introspection")]
Event::UpdatePerfMonitor {
introspection_stats,
..
} => {
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_introspection_stats(introspection_stats);
})?;
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
Event::Objective { objective_size, .. } => {
client_stats_manager.client_stats_insert(ClientId(0))?;
client_stats_manager.update_client_stats_for(ClientId(0), |client_stat| {
client_stat.update_objective_size(*objective_size as u64);
})?;
monitor.display(client_stats_manager, event.name(), ClientId(0))?;
Ok(BrokerEventResult::Handled)
}
Event::Log {
severity_level,
message,
..
} => {
let (_, _) = (message, severity_level);
log::log!((*severity_level).into(), "{message}");
Ok(BrokerEventResult::Handled)
}
Event::Stop => Ok(BrokerEventResult::Forward),
}
}
}
#[cfg(feature = "std")]
pub type SimpleRestartingEventManager<I, MT, S, SP> =
crate::events::RestartingEventManager<SimpleEventManager<I, MT, S>, SP>;
#[cfg(feature = "std")]
impl<I, MT, S, SP> crate::events::Restorable<S, SP> for SimpleEventManager<I, MT, S>
where
I: Debug,
MT: Monitor,
S: HasCurrentStageId + Serialize,
SP: ShMemProvider,
{
type RestartState = (Duration, HashMap<ClientId, ClientStats>);
fn on_restart(&mut self, state: &mut S) -> Result<(bool, Self::RestartState), Error> {
state.on_restart()?;
let inner_state = (
self.client_stats_manager.start_time(),
self.client_stats_manager.client_stats().clone(),
);
Ok((true, inner_state))
}
}
#[cfg(feature = "std")]
impl<I, MT, S, SP> SimpleRestartingEventManager<I, MT, S, SP>
where
I: Debug,
MT: Monitor,
S: Stoppable,
SP: ShMemProvider,
{
pub fn launch(
monitor: MT,
shmem_provider: &mut SP,
_use_fork: bool,
) -> Result<(Option<S>, Self), Error>
where
S: DeserializeOwned + Serialize + HasSolutions<I> + HasCurrentStageId,
MT: Debug,
{
let mut restarting_mgr = RestartingMgr::new(shmem_provider.clone());
#[cfg(unix)]
restarting_mgr.fork(_use_fork);
restarting_mgr.launch(|mut staterestorer, _new_shmem_provider, _core_id| {
let (state, mgr) = match staterestorer
.restore::<(Option<S>, (Duration, HashMap<ClientId, ClientStats>))>()?
{
None => {
log::info!("First run. Let's set it all up");
(
None::<S>,
SimpleRestartingEventManager::new(
SimpleEventManager::<I, MT, S>::new(monitor),
staterestorer,
),
)
}
Some((state_opt, (start_time, clients_stats))) => {
log::info!("Subsequent run. Loaded previous state.");
staterestorer.reset();
let mut inner = SimpleEventManager::<I, MT, S>::new(monitor);
inner.client_stats_manager.set_start_time(start_time);
inner
.client_stats_manager
.update_all_client_stats(clients_stats);
(
state_opt,
SimpleRestartingEventManager::new(inner, staterestorer),
)
}
};
Ok((state, mgr))
})
}
}