Add Stoppable trait to State which exposes an API to stop the fuzzer (#2325)
* add HasStopNext to State which exposes an API to stop the fuzzer. Stops the fuzzer in fuzz_loop or fuzz_loop_for when set to true * fix import * rename HasStopNext to HasShouldStopFuzzing and stop_next to should_stop_fuzzing * added HasShouldStopFuzzing trait constraint for libafl_libfuzzer_runtime fuzzer * rename HasShouldStopFuzzing to Stoppable and add it as a type constraint in libafl_libfuzzer report.rs * rename should_stop_fuzzing -> should_stop * introduce Event::Stop * fix prelude import * Call send_exiting when processing Event::Stop in restartable managers * fix clippy * introduce on_shutdown function in EventProcessor, a function to exit without saving state gracefully. In contrast with on_restart. * call manager.on_shutdown when stopping in fuzz_loop due to state.should_stop * Add missing on_shutdown implementations Check after every stage in Stages::perform_all if should exit and do so. * remove specialization * fix doc * introduce EventProcessor constraint in libafl_libfuzzer_runtime run clippy in libafl_libfuzzer_runtime * fix CentralizedEventManager's on_shutdown not calling inner.on_shutdown * fix bugs in CentralizedLauncher that wouldn't allow children to terminate properly * don't call send_exiting when processing Event::Stop since it will be called when calling on_shutdown anyways * clippy * add set_exit_after so broker does not need to inner_mut to set exit_cleanly_after * return Cow<str> from Event::name_detailed instead of a String * fix missing import in libafl_libfuzzer_runtime * add initate_stop and reset_stop to Stoppable trait to superceed should_stop_mut * clippy * typo * rename initate_stop to request_stop, should_stop to stop_requested and reset_stop to discard_stop_request * fix missing import * windows clippy fix * fix broker typo
This commit is contained in:
parent
762b6e008e
commit
eff40320eb
@ -95,7 +95,7 @@ where
|
|||||||
event: &Event<I>,
|
event: &Event<I>,
|
||||||
) -> Result<BrokerEventResult, Error> {
|
) -> Result<BrokerEventResult, Error> {
|
||||||
match &event {
|
match &event {
|
||||||
Event::NewTestcase { .. } => Ok(BrokerEventResult::Forward),
|
Event::NewTestcase { .. } | Event::Stop => Ok(BrokerEventResult::Forward),
|
||||||
_ => Ok(BrokerEventResult::Handled),
|
_ => Ok(BrokerEventResult::Handled),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,6 +208,7 @@ where
|
|||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
|
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
|
||||||
|
Event::Stop => Ok(BrokerEventResult::Forward),
|
||||||
//_ => Ok(BrokerEventResult::Forward),
|
//_ => Ok(BrokerEventResult::Forward),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ use crate::{
|
|||||||
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
||||||
inputs::{Input, NopInput, UsesInput},
|
inputs::{Input, NopInput, UsesInput},
|
||||||
observers::{ObserversTuple, TimeObserver},
|
observers::{ObserversTuple, TimeObserver},
|
||||||
state::{HasExecutions, HasLastReportTime, NopState, State, UsesState},
|
state::{HasExecutions, HasLastReportTime, NopState, State, Stoppable, UsesState},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -279,6 +279,7 @@ where
|
|||||||
self.inner.should_send()
|
self.inner.should_send()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::match_same_arms)]
|
||||||
fn fire(
|
fn fire(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
@ -295,6 +296,7 @@ where
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
Event::UpdateExecStats { .. } => true, // send it but this guy won't be handled. the only purpose is to keep this client alive else the broker thinks it is dead and will dc it
|
Event::UpdateExecStats { .. } => true, // send it but this guy won't be handled. the only purpose is to keep this client alive else the broker thinks it is dead and will dc it
|
||||||
|
Event::Stop => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -391,6 +393,11 @@ where
|
|||||||
self.inner.process(fuzzer, state, executor)
|
self.inner.process(fuzzer, state, executor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.inner.on_shutdown()?;
|
||||||
|
self.client.sender_mut().send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, EMH, S, SP, Z> EventManager<E, Z> for CentralizedEventManager<EM, EMH, S, SP>
|
impl<E, EM, EMH, S, SP, Z> EventManager<E, Z> for CentralizedEventManager<EM, EMH, S, SP>
|
||||||
@ -476,7 +483,7 @@ impl<EM, EMH, S, SP> CentralizedEventManager<EM, EMH, S, SP>
|
|||||||
where
|
where
|
||||||
EM: UsesState + EventFirer + AdaptiveSerializer + HasEventManagerId,
|
EM: UsesState + EventFirer + AdaptiveSerializer + HasEventManagerId,
|
||||||
EMH: EventManagerHooksTuple<EM::State>,
|
EMH: EventManagerHooksTuple<EM::State>,
|
||||||
S: State,
|
S: State + Stoppable,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
@ -662,6 +669,9 @@ where
|
|||||||
log::debug!("[{}] {} was discarded...)", process::id(), event_name);
|
log::debug!("[{}] {} was discarded...)", process::id(), event_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Event::Stop => {
|
||||||
|
state.request_stop();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::unknown(format!(
|
return Err(Error::unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {:?}.",
|
"Received illegal message that message should not have arrived: {:?}.",
|
||||||
|
@ -28,6 +28,8 @@ use std::process::Stdio;
|
|||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use std::{fs::File, os::unix::io::AsRawFd};
|
use std::{fs::File, os::unix::io::AsRawFd};
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
|
use libafl_bolts::llmp::Broker;
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
use libafl_bolts::llmp::Brokers;
|
use libafl_bolts::llmp::Brokers;
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
@ -716,7 +718,8 @@ where
|
|||||||
self.time_obs.clone(),
|
self.time_obs.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.main_run_client.take().unwrap()(state, c_mgr, *bind_to)
|
self.main_run_client.take().unwrap()(state, c_mgr, *bind_to)?;
|
||||||
|
Err(Error::shutting_down())
|
||||||
} else {
|
} else {
|
||||||
// Secondary clients
|
// Secondary clients
|
||||||
log::debug!("Running secondary client on PID {}", std::process::id());
|
log::debug!("Running secondary client on PID {}", std::process::id());
|
||||||
@ -733,7 +736,8 @@ where
|
|||||||
self.time_obs.clone(),
|
self.time_obs.clone(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.secondary_run_client.take().unwrap()(state, c_mgr, *bind_to)
|
self.secondary_run_client.take().unwrap()(state, c_mgr, *bind_to)?;
|
||||||
|
Err(Error::shutting_down())
|
||||||
}
|
}
|
||||||
}?,
|
}?,
|
||||||
};
|
};
|
||||||
@ -756,6 +760,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut brokers = Brokers::new();
|
let mut brokers = Brokers::new();
|
||||||
|
let exit_cleanly_after = NonZeroUsize::try_from(self.cores.ids.len()).unwrap();
|
||||||
|
|
||||||
// Add centralized broker
|
// Add centralized broker
|
||||||
brokers.add(Box::new({
|
brokers.add(Box::new({
|
||||||
@ -769,12 +774,14 @@ where
|
|||||||
let centralized_hooks = tuple_list!(CentralizedLlmpHook::<S::Input>::new()?);
|
let centralized_hooks = tuple_list!(CentralizedLlmpHook::<S::Input>::new()?);
|
||||||
|
|
||||||
// TODO switch to false after solving the bug
|
// TODO switch to false after solving the bug
|
||||||
LlmpBroker::with_keep_pages_attach_to_tcp(
|
let mut broker = LlmpBroker::with_keep_pages_attach_to_tcp(
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
centralized_hooks,
|
centralized_hooks,
|
||||||
self.centralized_broker_port,
|
self.centralized_broker_port,
|
||||||
true,
|
true,
|
||||||
)?
|
)?;
|
||||||
|
broker.set_exit_after(exit_cleanly_after);
|
||||||
|
broker
|
||||||
}));
|
}));
|
||||||
|
|
||||||
#[cfg(feature = "multi_machine")]
|
#[cfg(feature = "multi_machine")]
|
||||||
@ -808,19 +815,11 @@ where
|
|||||||
broker.inner_mut().connect_b2b(remote_broker_addr)?;
|
broker.inner_mut().connect_b2b(remote_broker_addr)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
let exit_cleanly_after = NonZeroUsize::try_from(self.cores.ids.len()).unwrap();
|
broker.set_exit_after(exit_cleanly_after);
|
||||||
|
|
||||||
broker
|
|
||||||
.inner_mut()
|
|
||||||
.set_exit_cleanly_after(exit_cleanly_after);
|
|
||||||
|
|
||||||
brokers.add(Box::new(broker));
|
brokers.add(Box::new(broker));
|
||||||
}
|
}
|
||||||
|
log::debug!("Broker has been initialized; pid {}.", std::process::id());
|
||||||
log::debug!(
|
|
||||||
"Brokers have been initialized on port {}.",
|
|
||||||
std::process::id()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Loop over all the brokers that should be polled
|
// Loop over all the brokers that should be polled
|
||||||
brokers.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
brokers.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
||||||
|
@ -468,6 +468,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Event::Stop => {
|
||||||
|
state.request_stop();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::unknown(format!(
|
return Err(Error::unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {:?}.",
|
"Received illegal message that message should not have arrived: {:?}.",
|
||||||
@ -626,6 +629,10 @@ where
|
|||||||
}
|
}
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpEventManager<EMH, S, SP>
|
impl<E, EMH, S, SP, Z> EventManager<E, Z> for LlmpEventManager<EMH, S, SP>
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
||||||
inputs::{Input, InputConverter, NopInput, NopInputConverter, UsesInput},
|
inputs::{Input, InputConverter, NopInput, NopInputConverter, UsesInput},
|
||||||
state::{HasExecutions, NopState, State, UsesState},
|
state::{HasExecutions, NopState, State, Stoppable, UsesState},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ where
|
|||||||
|
|
||||||
impl<DI, IC, ICB, S, SP> LlmpEventConverter<DI, IC, ICB, S, SP>
|
impl<DI, IC, ICB, S, SP> LlmpEventConverter<DI, IC, ICB, S, SP>
|
||||||
where
|
where
|
||||||
S: UsesInput + HasExecutions + HasMetadata,
|
S: UsesInput + HasExecutions + HasMetadata + Stoppable,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
IC: InputConverter<From = S::Input, To = DI>,
|
IC: InputConverter<From = S::Input, To = DI>,
|
||||||
ICB: InputConverter<From = DI, To = S::Input>,
|
ICB: InputConverter<From = DI, To = S::Input>,
|
||||||
@ -329,6 +329,7 @@ where
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Event::Stop => Ok(()),
|
||||||
_ => Err(Error::unknown(format!(
|
_ => Err(Error::unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {:?}.",
|
"Received illegal message that message should not have arrived: {:?}.",
|
||||||
event.name()
|
event.name()
|
||||||
|
@ -22,15 +22,15 @@ use libafl_bolts::os::startable_self;
|
|||||||
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
||||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||||
use libafl_bolts::os::{fork, ForkResult};
|
use libafl_bolts::os::{fork, ForkResult};
|
||||||
use libafl_bolts::{
|
|
||||||
llmp::LlmpBroker,
|
|
||||||
shmem::ShMemProvider,
|
|
||||||
tuples::{tuple_list, Handle},
|
|
||||||
};
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::LlmpConnection, os::CTRL_C_EXIT, shmem::StdShMemProvider, staterestore::StateRestorer,
|
llmp::LlmpConnection, os::CTRL_C_EXIT, shmem::StdShMemProvider, staterestore::StateRestorer,
|
||||||
};
|
};
|
||||||
|
use libafl_bolts::{
|
||||||
|
llmp::{Broker, LlmpBroker},
|
||||||
|
shmem::ShMemProvider,
|
||||||
|
tuples::{tuple_list, Handle},
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use typed_builder::TypedBuilder;
|
use typed_builder::TypedBuilder;
|
||||||
@ -218,6 +218,10 @@ where
|
|||||||
self.intermediate_save()?;
|
self.intermediate_save()?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -448,9 +452,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(exit_cleanly_after) = self.exit_cleanly_after {
|
if let Some(exit_cleanly_after) = self.exit_cleanly_after {
|
||||||
broker
|
broker.set_exit_after(exit_cleanly_after);
|
||||||
.inner_mut()
|
|
||||||
.set_exit_cleanly_after(exit_cleanly_after);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
broker.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
broker.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
||||||
|
@ -21,12 +21,7 @@ pub use llmp::*;
|
|||||||
pub mod tcp;
|
pub mod tcp;
|
||||||
|
|
||||||
pub mod broker_hooks;
|
pub mod broker_hooks;
|
||||||
use alloc::{
|
use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
|
||||||
borrow::Cow,
|
|
||||||
boxed::Box,
|
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::{
|
use core::{
|
||||||
fmt,
|
fmt,
|
||||||
hash::{BuildHasher, Hasher},
|
hash::{BuildHasher, Hasher},
|
||||||
@ -353,6 +348,8 @@ where
|
|||||||
/// Tag of this buffer
|
/// Tag of this buffer
|
||||||
tag: String,
|
tag: String,
|
||||||
},
|
},
|
||||||
|
/// Exit gracefully
|
||||||
|
Stop,
|
||||||
/*/// A custom type
|
/*/// A custom type
|
||||||
Custom {
|
Custom {
|
||||||
// TODO: Allow custom events
|
// TODO: Allow custom events
|
||||||
@ -364,7 +361,8 @@ impl<I> Event<I>
|
|||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
fn name(&self) -> &str {
|
/// Event's corresponding name
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
Event::NewTestcase { .. } => "Testcase",
|
Event::NewTestcase { .. } => "Testcase",
|
||||||
Event::UpdateExecStats { .. } => "Client Heartbeat",
|
Event::UpdateExecStats { .. } => "Client Heartbeat",
|
||||||
@ -377,21 +375,24 @@ where
|
|||||||
/*Event::Custom {
|
/*Event::Custom {
|
||||||
sender_id: _, /*custom_event} => custom_event.name()*/
|
sender_id: _, /*custom_event} => custom_event.name()*/
|
||||||
} => "todo",*/
|
} => "todo",*/
|
||||||
|
Event::Stop => "Stop",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_detailed(&self) -> String {
|
/// Event's corresponding name with additional info
|
||||||
|
fn name_detailed(&self) -> Cow<'static, str> {
|
||||||
match self {
|
match self {
|
||||||
Event::NewTestcase { input, .. } => {
|
Event::NewTestcase { input, .. } => {
|
||||||
format!("Testcase {}", input.generate_name(None))
|
Cow::Owned(format!("Testcase {}", input.generate_name(None)))
|
||||||
}
|
}
|
||||||
Event::UpdateExecStats { .. } => "Client Heartbeat".to_string(),
|
Event::UpdateExecStats { .. } => Cow::Borrowed("Client Heartbeat"),
|
||||||
Event::UpdateUserStats { .. } => "UserStats".to_string(),
|
Event::UpdateUserStats { .. } => Cow::Borrowed("UserStats"),
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
Event::UpdatePerfMonitor { .. } => "PerfMonitor".to_string(),
|
Event::UpdatePerfMonitor { .. } => Cow::Borrowed("PerfMonitor"),
|
||||||
Event::Objective { .. } => "Objective".to_string(),
|
Event::Objective { .. } => Cow::Borrowed("Objective"),
|
||||||
Event::Log { .. } => "Log".to_string(),
|
Event::Log { .. } => Cow::Borrowed("Log"),
|
||||||
Event::CustomBuf { .. } => "CustomBuf".to_string(),
|
Event::CustomBuf { .. } => Cow::Borrowed("CustomBuf"),
|
||||||
|
Event::Stop => Cow::Borrowed("Stop"),
|
||||||
/*Event::Custom {
|
/*Event::Custom {
|
||||||
sender_id: _, /*custom_event} => custom_event.name()*/
|
sender_id: _, /*custom_event} => custom_event.name()*/
|
||||||
} => "todo",*/
|
} => "todo",*/
|
||||||
@ -399,7 +400,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`EventFirer`] fire an event.
|
/// [`EventFirer`] fires an event.
|
||||||
pub trait EventFirer: UsesState {
|
pub trait EventFirer: UsesState {
|
||||||
/// Send off an [`Event`] to the broker
|
/// Send off an [`Event`] to the broker
|
||||||
///
|
///
|
||||||
@ -574,6 +575,9 @@ pub trait EventProcessor<E, Z>: UsesState {
|
|||||||
state: &mut Self::State,
|
state: &mut Self::State,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
) -> Result<usize, Error>;
|
) -> Result<usize, Error>;
|
||||||
|
|
||||||
|
/// Shutdown gracefully; typically without saving state.
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
/// The id of this [`EventManager`].
|
/// The id of this [`EventManager`].
|
||||||
/// For multi processed [`EventManager`]s,
|
/// For multi processed [`EventManager`]s,
|
||||||
@ -662,6 +666,10 @@ where
|
|||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, S, Z> EventManager<E, Z> for NopEventManager<S> where
|
impl<E, S, Z> EventManager<E, Z> for NopEventManager<S> where
|
||||||
@ -793,6 +801,10 @@ where
|
|||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
self.inner.process(fuzzer, state, executor)
|
self.inner.process(fuzzer, state, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.inner.on_shutdown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EM, M, Z> EventManager<E, Z> for MonitorTypedEventManager<EM, M>
|
impl<E, EM, M, Z> EventManager<E, Z> for MonitorTypedEventManager<EM, M>
|
||||||
|
@ -32,7 +32,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
monitors::Monitor,
|
monitors::Monitor,
|
||||||
state::{HasExecutions, HasLastReportTime, State, UsesState},
|
state::{HasExecutions, HasLastReportTime, State, Stoppable, UsesState},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -50,7 +50,7 @@ const _ENV_FUZZER_BROKER_CLIENT_INITIAL: &str = "_AFL_ENV_FUZZER_BROKER_CLIENT";
|
|||||||
/// A simple, single-threaded event manager that just logs
|
/// A simple, single-threaded event manager that just logs
|
||||||
pub struct SimpleEventManager<MT, S>
|
pub struct SimpleEventManager<MT, S>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
{
|
{
|
||||||
/// The monitor
|
/// The monitor
|
||||||
monitor: MT,
|
monitor: MT,
|
||||||
@ -64,7 +64,7 @@ where
|
|||||||
impl<MT, S> Debug for SimpleEventManager<MT, S>
|
impl<MT, S> Debug for SimpleEventManager<MT, S>
|
||||||
where
|
where
|
||||||
MT: Debug,
|
MT: Debug,
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
{
|
{
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
f.debug_struct("SimpleEventManager")
|
f.debug_struct("SimpleEventManager")
|
||||||
@ -128,6 +128,10 @@ where
|
|||||||
}
|
}
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, MT, S, Z> EventManager<E, Z> for SimpleEventManager<MT, S>
|
impl<E, MT, S, Z> EventManager<E, Z> for SimpleEventManager<MT, S>
|
||||||
@ -163,7 +167,7 @@ where
|
|||||||
impl<MT, S> HasEventManagerId for SimpleEventManager<MT, S>
|
impl<MT, S> HasEventManagerId for SimpleEventManager<MT, S>
|
||||||
where
|
where
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
{
|
{
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
EventManagerId(0)
|
EventManagerId(0)
|
||||||
@ -173,7 +177,7 @@ where
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl<S> SimpleEventManager<SimplePrintingMonitor, S>
|
impl<S> SimpleEventManager<SimplePrintingMonitor, S>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
{
|
{
|
||||||
/// Creates a [`SimpleEventManager`] that just prints to `stdout`.
|
/// Creates a [`SimpleEventManager`] that just prints to `stdout`.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
@ -185,7 +189,7 @@ where
|
|||||||
impl<MT, S> SimpleEventManager<MT, S>
|
impl<MT, S> SimpleEventManager<MT, S>
|
||||||
where
|
where
|
||||||
MT: Monitor, //TODO CE: CustomEvent,
|
MT: Monitor, //TODO CE: CustomEvent,
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
{
|
{
|
||||||
/// Creates a new [`SimpleEventManager`].
|
/// Creates a new [`SimpleEventManager`].
|
||||||
pub fn new(monitor: MT) -> Self {
|
pub fn new(monitor: MT) -> Self {
|
||||||
@ -281,22 +285,27 @@ where
|
|||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
|
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
|
||||||
//_ => Ok(BrokerEventResult::Forward),
|
Event::Stop => Ok(BrokerEventResult::Forward),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle arriving events in the client
|
// Handle arriving events in the client
|
||||||
#[allow(clippy::needless_pass_by_value, clippy::unused_self)]
|
#[allow(clippy::needless_pass_by_value, clippy::unused_self)]
|
||||||
fn handle_in_client(&mut self, state: &mut S, event: Event<S::Input>) -> Result<(), Error> {
|
fn handle_in_client(&mut self, state: &mut S, event: Event<S::Input>) -> Result<(), Error> {
|
||||||
if let Event::CustomBuf { tag, buf } = &event {
|
match event {
|
||||||
|
Event::CustomBuf { buf, tag } => {
|
||||||
for handler in &mut self.custom_buf_handlers {
|
for handler in &mut self.custom_buf_handlers {
|
||||||
handler(state, tag, buf)?;
|
handler(state, &tag, &buf)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
}
|
||||||
Err(Error::unknown(format!(
|
Event::Stop => {
|
||||||
|
state.request_stop();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => Err(Error::unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {event:?}."
|
"Received illegal message that message should not have arrived: {event:?}."
|
||||||
)))
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -309,7 +318,7 @@ where
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SimpleRestartingEventManager<MT, S, SP>
|
pub struct SimpleRestartingEventManager<MT, S, SP>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
SP: ShMemProvider, //CE: CustomEvent<I, OT>,
|
SP: ShMemProvider, //CE: CustomEvent<I, OT>,
|
||||||
{
|
{
|
||||||
/// The actual simple event mgr
|
/// The actual simple event mgr
|
||||||
@ -388,6 +397,9 @@ where
|
|||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
self.simple_event_mgr.process(fuzzer, state, executor)
|
self.simple_event_mgr.process(fuzzer, state, executor)
|
||||||
}
|
}
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -427,7 +439,7 @@ where
|
|||||||
impl<MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<MT, S, SP>
|
impl<MT, S, SP> HasEventManagerId for SimpleRestartingEventManager<MT, S, SP>
|
||||||
where
|
where
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
{
|
{
|
||||||
fn mgr_id(&self) -> EventManagerId {
|
fn mgr_id(&self) -> EventManagerId {
|
||||||
@ -439,7 +451,7 @@ where
|
|||||||
#[allow(clippy::type_complexity, clippy::too_many_lines)]
|
#[allow(clippy::type_complexity, clippy::too_many_lines)]
|
||||||
impl<MT, S, SP> SimpleRestartingEventManager<MT, S, SP>
|
impl<MT, S, SP> SimpleRestartingEventManager<MT, S, SP>
|
||||||
where
|
where
|
||||||
S: UsesInput,
|
S: UsesInput + Stoppable,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
MT: Monitor, //TODO CE: CustomEvent,
|
MT: Monitor, //TODO CE: CustomEvent,
|
||||||
{
|
{
|
||||||
|
@ -407,7 +407,7 @@ where
|
|||||||
log::log!((*severity_level).into(), "{message}");
|
log::log!((*severity_level).into(), "{message}");
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::CustomBuf { .. } => Ok(BrokerEventResult::Forward),
|
Event::CustomBuf { .. } | Event::Stop => Ok(BrokerEventResult::Forward),
|
||||||
//_ => Ok(BrokerEventResult::Forward),
|
//_ => Ok(BrokerEventResult::Forward),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -657,6 +657,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Event::Stop => {
|
||||||
|
state.request_stop();
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::unknown(format!(
|
return Err(Error::unknown(format!(
|
||||||
"Received illegal message that message should not have arrived: {:?}.",
|
"Received illegal message that message should not have arrived: {:?}.",
|
||||||
@ -809,6 +812,10 @@ where
|
|||||||
|
|
||||||
Ok(count)
|
Ok(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, EMH, S, Z> EventManager<E, Z> for TcpEventManager<EMH, S>
|
impl<E, EMH, S, Z> EventManager<E, Z> for TcpEventManager<EMH, S>
|
||||||
@ -967,6 +974,10 @@ where
|
|||||||
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
fn process(&mut self, fuzzer: &mut Z, state: &mut S, executor: &mut E) -> Result<usize, Error> {
|
||||||
self.tcp_mgr.process(fuzzer, state, executor)
|
self.tcp_mgr.process(fuzzer, state, executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_shutdown(&mut self) -> Result<(), Error> {
|
||||||
|
self.send_exiting()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -19,7 +19,7 @@ use crate::{
|
|||||||
start_timer,
|
start_timer,
|
||||||
state::{
|
state::{
|
||||||
HasCorpus, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions,
|
HasCorpus, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions,
|
||||||
UsesState,
|
Stoppable, UsesState,
|
||||||
},
|
},
|
||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
@ -182,9 +182,9 @@ pub trait Evaluator<E, EM>: UsesState {
|
|||||||
/// The main fuzzer trait.
|
/// The main fuzzer trait.
|
||||||
pub trait Fuzzer<E, EM, ST>: Sized + UsesState
|
pub trait Fuzzer<E, EM, ST>: Sized + UsesState
|
||||||
where
|
where
|
||||||
Self::State: HasMetadata + HasExecutions + HasLastReportTime,
|
Self::State: HasMetadata + HasExecutions + HasLastReportTime + Stoppable,
|
||||||
E: UsesState<State = Self::State>,
|
E: UsesState<State = Self::State>,
|
||||||
EM: ProgressReporter<State = Self::State>,
|
EM: ProgressReporter<State = Self::State> + EventProcessor<E, Self>,
|
||||||
ST: StagesTuple<E, EM, Self::State, Self>,
|
ST: StagesTuple<E, EM, Self::State, Self>,
|
||||||
{
|
{
|
||||||
/// Fuzz for a single iteration.
|
/// Fuzz for a single iteration.
|
||||||
@ -216,8 +216,14 @@ where
|
|||||||
loop {
|
loop {
|
||||||
// log::info!("Starting another fuzz_loop");
|
// log::info!("Starting another fuzz_loop");
|
||||||
manager.maybe_report_progress(state, monitor_timeout)?;
|
manager.maybe_report_progress(state, monitor_timeout)?;
|
||||||
|
if state.stop_requested() {
|
||||||
|
state.discard_stop_request();
|
||||||
|
manager.on_shutdown()?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
self.fuzz_one(stages, executor, state, manager)?;
|
self.fuzz_one(stages, executor, state, manager)?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fuzz for n iterations.
|
/// Fuzz for n iterations.
|
||||||
@ -248,6 +254,10 @@ where
|
|||||||
|
|
||||||
for _ in 0..iters {
|
for _ in 0..iters {
|
||||||
manager.maybe_report_progress(state, monitor_timeout)?;
|
manager.maybe_report_progress(state, monitor_timeout)?;
|
||||||
|
if state.stop_requested() {
|
||||||
|
state.discard_stop_request();
|
||||||
|
break;
|
||||||
|
}
|
||||||
ret = Some(self.fuzz_one(stages, executor, state, manager)?);
|
ret = Some(self.fuzz_one(stages, executor, state, manager)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -865,7 +875,7 @@ pub mod test {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::CorpusId,
|
corpus::CorpusId,
|
||||||
events::ProgressReporter,
|
events::{EventProcessor, ProgressReporter},
|
||||||
stages::{HasCurrentStage, StagesTuple},
|
stages::{HasCurrentStage, StagesTuple},
|
||||||
state::{HasExecutions, HasLastReportTime, State, UsesState},
|
state::{HasExecutions, HasLastReportTime, State, UsesState},
|
||||||
Fuzzer, HasMetadata,
|
Fuzzer, HasMetadata,
|
||||||
@ -901,7 +911,7 @@ pub mod test {
|
|||||||
impl<ST, E, EM> Fuzzer<E, EM, ST> for NopFuzzer<E::State>
|
impl<ST, E, EM> Fuzzer<E, EM, ST> for NopFuzzer<E::State>
|
||||||
where
|
where
|
||||||
E: UsesState,
|
E: UsesState,
|
||||||
EM: ProgressReporter<State = Self::State>,
|
EM: ProgressReporter<State = Self::State> + EventProcessor<E, Self>,
|
||||||
ST: StagesTuple<E, EM, Self::State, Self>,
|
ST: StagesTuple<E, EM, Self::State, Self>,
|
||||||
Self::State: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStage,
|
Self::State: HasMetadata + HasExecutions + HasLastReportTime + HasCurrentStage,
|
||||||
{
|
{
|
||||||
|
@ -45,13 +45,13 @@ pub use unicode::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{CorpusId, HasCurrentCorpusId},
|
corpus::{CorpusId, HasCurrentCorpusId},
|
||||||
events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter},
|
events::{EventFirer, EventProcessor, EventRestarter, HasEventManagerId, ProgressReporter},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
schedulers::Scheduler,
|
schedulers::Scheduler,
|
||||||
stages::push::PushStage,
|
stages::push::PushStage,
|
||||||
state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand, State, UsesState},
|
state::{HasCorpus, HasExecutions, HasLastReportTime, HasRand, State, Stoppable, UsesState},
|
||||||
Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasMetadata, HasNamedMetadata,
|
Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasMetadata, HasNamedMetadata,
|
||||||
HasScheduler,
|
HasScheduler,
|
||||||
};
|
};
|
||||||
@ -135,7 +135,7 @@ where
|
|||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
S: UsesInput + HasCurrentStage,
|
S: UsesInput + HasCurrentStage,
|
||||||
{
|
{
|
||||||
/// Performs all `Stages` in this tuple
|
/// Performs all `Stages` in this tuple.
|
||||||
fn perform_all(
|
fn perform_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
@ -174,10 +174,13 @@ where
|
|||||||
Head: Stage<E, EM, Z>,
|
Head: Stage<E, EM, Z>,
|
||||||
Tail: StagesTuple<E, EM, Head::State, Z> + HasConstLen,
|
Tail: StagesTuple<E, EM, Head::State, Z> + HasConstLen,
|
||||||
E: UsesState<State = Head::State>,
|
E: UsesState<State = Head::State>,
|
||||||
EM: UsesState<State = Head::State>,
|
EM: UsesState<State = Head::State> + EventProcessor<E, Z>,
|
||||||
Z: UsesState<State = Head::State>,
|
Z: UsesState<State = Head::State>,
|
||||||
Head::State: HasCurrentStage,
|
Head::State: HasCurrentStage,
|
||||||
{
|
{
|
||||||
|
/// Performs all stages in the tuple,
|
||||||
|
/// Checks after every stage if state wants to stop
|
||||||
|
/// and returns an [`Error::ShuttingDown`] if so
|
||||||
fn perform_all(
|
fn perform_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
@ -211,6 +214,12 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if state.stop_requested() {
|
||||||
|
state.discard_stop_request();
|
||||||
|
manager.on_shutdown()?;
|
||||||
|
return Err(Error::shutting_down());
|
||||||
|
}
|
||||||
|
|
||||||
// Execute the remaining stages
|
// Execute the remaining stages
|
||||||
self.1.perform_all(fuzzer, executor, state, manager)
|
self.1.perform_all(fuzzer, executor, state, manager)
|
||||||
}
|
}
|
||||||
@ -273,10 +282,13 @@ impl<E, EM, S, Z> StagesTuple<E, EM, S, Z>
|
|||||||
for Vec<Box<dyn Stage<E, EM, Z, State = S, Input = S::Input>>>
|
for Vec<Box<dyn Stage<E, EM, Z, State = S, Input = S::Input>>>
|
||||||
where
|
where
|
||||||
E: UsesState<State = S>,
|
E: UsesState<State = S>,
|
||||||
EM: UsesState<State = S>,
|
EM: UsesState<State = S> + EventProcessor<E, Z>,
|
||||||
Z: UsesState<State = S>,
|
Z: UsesState<State = S>,
|
||||||
S: UsesInput + HasCurrentStage + State,
|
S: UsesInput + HasCurrentStage + State,
|
||||||
{
|
{
|
||||||
|
/// Performs all stages in the `Vec`
|
||||||
|
/// Checks after every stage if state wants to stop
|
||||||
|
/// and returns an [`Error::ShuttingDown`] if so
|
||||||
fn perform_all(
|
fn perform_all(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
@ -284,8 +296,14 @@ where
|
|||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
manager: &mut EM,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.iter_mut()
|
self.iter_mut().try_for_each(|x| {
|
||||||
.try_for_each(|x| x.perform_restartable(fuzzer, executor, state, manager))
|
if state.stop_requested() {
|
||||||
|
state.discard_stop_request();
|
||||||
|
manager.on_shutdown()?;
|
||||||
|
return Err(Error::shutting_down());
|
||||||
|
}
|
||||||
|
x.perform_restartable(fuzzer, executor, state, manager)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ pub trait State:
|
|||||||
+ MaybeHasScalabilityMonitor
|
+ MaybeHasScalabilityMonitor
|
||||||
+ HasCurrentCorpusId
|
+ HasCurrentCorpusId
|
||||||
+ HasCurrentStage
|
+ HasCurrentStage
|
||||||
|
+ Stoppable
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,6 +262,9 @@ pub struct StdState<I, C, R, SC> {
|
|||||||
last_report_time: Option<Duration>,
|
last_report_time: Option<Duration>,
|
||||||
/// The current index of the corpus; used to record for resumable fuzzing.
|
/// The current index of the corpus; used to record for resumable fuzzing.
|
||||||
corpus_id: Option<CorpusId>,
|
corpus_id: Option<CorpusId>,
|
||||||
|
/// Request the fuzzer to stop at the start of the next stage
|
||||||
|
/// or at the beginning of the next fuzzing iteration
|
||||||
|
stop_requested: bool,
|
||||||
stage_stack: StageStack,
|
stage_stack: StageStack,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
@ -532,6 +536,32 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait for types that want to expose a stop API
|
||||||
|
pub trait Stoppable {
|
||||||
|
/// Check if stop is requested
|
||||||
|
fn stop_requested(&self) -> bool;
|
||||||
|
|
||||||
|
/// Request to stop
|
||||||
|
fn request_stop(&mut self);
|
||||||
|
|
||||||
|
/// Discard the stop request
|
||||||
|
fn discard_stop_request(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, C, R, SC> Stoppable for StdState<I, C, R, SC> {
|
||||||
|
fn request_stop(&mut self) {
|
||||||
|
self.stop_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn discard_stop_request(&mut self) {
|
||||||
|
self.stop_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_requested(&self) -> bool {
|
||||||
|
self.stop_requested
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<I, C, R, SC> HasCurrentStage for StdState<I, C, R, SC> {
|
impl<I, C, R, SC> HasCurrentStage for StdState<I, C, R, SC> {
|
||||||
fn set_current_stage_idx(&mut self, idx: StageId) -> Result<(), Error> {
|
fn set_current_stage_idx(&mut self, idx: StageId) -> Result<(), Error> {
|
||||||
self.stage_stack.set_current_stage_idx(idx)
|
self.stage_stack.set_current_stage_idx(idx)
|
||||||
@ -1087,6 +1117,7 @@ where
|
|||||||
corpus,
|
corpus,
|
||||||
solutions,
|
solutions,
|
||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
|
stop_requested: false,
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
introspection_monitor: ClientPerfMonitor::new(),
|
introspection_monitor: ClientPerfMonitor::new(),
|
||||||
#[cfg(feature = "scalability_introspection")]
|
#[cfg(feature = "scalability_introspection")]
|
||||||
@ -1135,6 +1166,7 @@ impl<I, C, R, SC> HasScalabilityMonitor for StdState<I, C, R, SC> {
|
|||||||
pub struct NopState<I> {
|
pub struct NopState<I> {
|
||||||
metadata: SerdeAnyMap,
|
metadata: SerdeAnyMap,
|
||||||
execution: u64,
|
execution: u64,
|
||||||
|
stop_requested: bool,
|
||||||
rand: StdRand,
|
rand: StdRand,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<I>,
|
||||||
}
|
}
|
||||||
@ -1147,6 +1179,7 @@ impl<I> NopState<I> {
|
|||||||
metadata: SerdeAnyMap::new(),
|
metadata: SerdeAnyMap::new(),
|
||||||
execution: 0,
|
execution: 0,
|
||||||
rand: StdRand::default(),
|
rand: StdRand::default(),
|
||||||
|
stop_requested: false,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1179,6 +1212,20 @@ impl<I> HasExecutions for NopState<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I> Stoppable for NopState<I> {
|
||||||
|
fn request_stop(&mut self) {
|
||||||
|
self.stop_requested = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn discard_stop_request(&mut self) {
|
||||||
|
self.stop_requested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_requested(&self) -> bool {
|
||||||
|
self.stop_requested
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<I> HasLastReportTime for NopState<I> {
|
impl<I> HasLastReportTime for NopState<I> {
|
||||||
fn last_report_time(&self) -> &Option<Duration> {
|
fn last_report_time(&self) -> &Option<Duration> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
@ -168,6 +168,8 @@ fn main() {
|
|||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
/* The main node has a broker, and a few worker threads */
|
/* The main node has a broker, and a few worker threads */
|
||||||
|
|
||||||
|
use libafl_bolts::llmp::Broker;
|
||||||
|
|
||||||
let mode = std::env::args()
|
let mode = std::env::args()
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.expect("no mode specified, chose 'broker', 'b2b', 'ctr', 'adder', 'large', or 'exiting'");
|
.expect("no mode specified, chose 'broker', 'b2b', 'ctr', 'adder', 'large', or 'exiting'");
|
||||||
@ -193,9 +195,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
)?;
|
)?;
|
||||||
broker.inner_mut().launch_tcp_listener_on(port)?;
|
broker.inner_mut().launch_tcp_listener_on(port)?;
|
||||||
// Exit when we got at least _n_ nodes, and all of them quit.
|
// Exit when we got at least _n_ nodes, and all of them quit.
|
||||||
broker
|
broker.set_exit_after(NonZeroUsize::new(1_usize).unwrap());
|
||||||
.inner_mut()
|
|
||||||
.set_exit_cleanly_after(NonZeroUsize::new(1_usize).unwrap());
|
|
||||||
broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS));
|
broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS));
|
||||||
}
|
}
|
||||||
"b2b" => {
|
"b2b" => {
|
||||||
|
@ -2091,6 +2091,9 @@ pub trait Broker {
|
|||||||
/// Getter to `exit_after`
|
/// Getter to `exit_after`
|
||||||
fn exit_after(&self) -> Option<NonZeroUsize>;
|
fn exit_after(&self) -> Option<NonZeroUsize>;
|
||||||
|
|
||||||
|
/// Setter for `exit_after`
|
||||||
|
fn set_exit_after(&mut self, n_clients: NonZeroUsize);
|
||||||
|
|
||||||
/// Getter to `has_clients`
|
/// Getter to `has_clients`
|
||||||
fn has_clients(&self) -> bool;
|
fn has_clients(&self) -> bool;
|
||||||
|
|
||||||
@ -2124,6 +2127,9 @@ where
|
|||||||
fn exit_after(&self) -> Option<NonZeroUsize> {
|
fn exit_after(&self) -> Option<NonZeroUsize> {
|
||||||
self.inner.exit_cleanly_after
|
self.inner.exit_cleanly_after
|
||||||
}
|
}
|
||||||
|
fn set_exit_after(&mut self, n_clients: NonZeroUsize) {
|
||||||
|
self.inner.set_exit_cleanly_after(n_clients);
|
||||||
|
}
|
||||||
|
|
||||||
fn has_clients(&self) -> bool {
|
fn has_clients(&self) -> bool {
|
||||||
self.inner.has_clients()
|
self.inner.has_clients()
|
||||||
|
@ -13,7 +13,7 @@ use std::{
|
|||||||
use libafl::{
|
use libafl::{
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
events::{
|
events::{
|
||||||
launcher::Launcher, EventConfig, ProgressReporter, SimpleEventManager,
|
launcher::Launcher, EventConfig, EventProcessor, ProgressReporter, SimpleEventManager,
|
||||||
SimpleRestartingEventManager,
|
SimpleRestartingEventManager,
|
||||||
},
|
},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
@ -23,7 +23,7 @@ use libafl::{
|
|||||||
Monitor, MultiMonitor,
|
Monitor, MultiMonitor,
|
||||||
},
|
},
|
||||||
stages::{HasCurrentStage, StagesTuple},
|
stages::{HasCurrentStage, StagesTuple},
|
||||||
state::{HasExecutions, HasLastReportTime, HasSolutions, UsesState},
|
state::{HasExecutions, HasLastReportTime, HasSolutions, Stoppable, UsesState},
|
||||||
Error, Fuzzer, HasMetadata,
|
Error, Fuzzer, HasMetadata,
|
||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
@ -66,9 +66,15 @@ fn do_fuzz<F, ST, E, S, EM>(
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
F: Fuzzer<E, EM, ST, State = S>,
|
F: Fuzzer<E, EM, ST, State = S>,
|
||||||
S: HasMetadata + HasExecutions + UsesInput + HasSolutions + HasLastReportTime + HasCurrentStage,
|
S: HasMetadata
|
||||||
|
+ HasExecutions
|
||||||
|
+ UsesInput
|
||||||
|
+ HasSolutions
|
||||||
|
+ HasLastReportTime
|
||||||
|
+ HasCurrentStage
|
||||||
|
+ Stoppable,
|
||||||
E: UsesState<State = S>,
|
E: UsesState<State = S>,
|
||||||
EM: ProgressReporter<State = S>,
|
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
|
||||||
ST: StagesTuple<E, EM, S, F>,
|
ST: StagesTuple<E, EM, S, F>,
|
||||||
{
|
{
|
||||||
if let Some(solution) = state.solutions().last() {
|
if let Some(solution) = state.solutions().last() {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::ffi::c_int;
|
use std::ffi::c_int;
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
events::{ProgressReporter, SimpleEventManager},
|
events::{EventProcessor, ProgressReporter, SimpleEventManager},
|
||||||
executors::HasObservers,
|
executors::HasObservers,
|
||||||
feedbacks::MapFeedbackMetadata,
|
feedbacks::MapFeedbackMetadata,
|
||||||
inputs::UsesInput,
|
inputs::UsesInput,
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
stages::{HasCurrentStage, StagesTuple},
|
stages::{HasCurrentStage, StagesTuple},
|
||||||
state::{HasExecutions, HasLastReportTime},
|
state::{HasExecutions, HasLastReportTime, Stoppable},
|
||||||
Error, Fuzzer, HasMetadata, HasNamedMetadata,
|
Error, Fuzzer, HasMetadata, HasNamedMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -29,9 +29,10 @@ where
|
|||||||
+ HasExecutions
|
+ HasExecutions
|
||||||
+ UsesInput
|
+ UsesInput
|
||||||
+ HasLastReportTime
|
+ HasLastReportTime
|
||||||
+ HasCurrentStage,
|
+ HasCurrentStage
|
||||||
|
+ Stoppable,
|
||||||
E: HasObservers<State = S>,
|
E: HasObservers<State = S>,
|
||||||
EM: ProgressReporter<State = S>,
|
EM: ProgressReporter<State = S> + EventProcessor<E, F>,
|
||||||
ST: StagesTuple<E, EM, S, F>,
|
ST: StagesTuple<E, EM, S, F>,
|
||||||
{
|
{
|
||||||
let meta = state
|
let meta = state
|
||||||
|
@ -121,8 +121,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.stdout.as_mut() {
|
if let Some(ob) = self.stdout.as_mut() {
|
||||||
Some(ob) => {
|
|
||||||
let mut stdout = Vec::new();
|
let mut stdout = Vec::new();
|
||||||
self.helper.nyx_stdout.rewind()?;
|
self.helper.nyx_stdout.rewind()?;
|
||||||
self.helper
|
self.helper
|
||||||
@ -132,8 +131,6 @@ where
|
|||||||
|
|
||||||
ob.observe_stdout(&stdout);
|
ob.observe_stdout(&stdout);
|
||||||
}
|
}
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(exit_kind)
|
Ok(exit_kind)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user