new eventmanager structure
This commit is contained in:
parent
419a4aef86
commit
f97418d311
File diff suppressed because it is too large
Load Diff
161
afl/src/events/stats.rs
Normal file
161
afl/src/events/stats.rs
Normal file
@ -0,0 +1,161 @@
|
||||
use core::{time, time::Duration};
|
||||
|
||||
use crate::utils::current_time;
|
||||
|
||||
const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds
|
||||
|
||||
/// A simple struct to keep track of client stats
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ClientStats {
|
||||
// stats (maybe we need a separated struct?)
|
||||
/// The corpus size for this client
|
||||
pub corpus_size: u64,
|
||||
/// The total executions for this client
|
||||
pub executions: u64,
|
||||
/// The last reported executions for this client
|
||||
pub last_window_executions: u64,
|
||||
/// The last time we got this information
|
||||
pub last_window_time: time::Duration,
|
||||
/// The last executions per sec
|
||||
pub last_execs_per_sec: u64,
|
||||
}
|
||||
|
||||
impl ClientStats {
|
||||
pub fn update_executions(&mut self, executions: u64, cur_time: time::Duration) {
|
||||
self.executions = executions;
|
||||
if (cur_time - self.last_window_time).as_secs() > CLIENT_STATS_TIME_WINDOW_SECS {
|
||||
self.last_execs_per_sec = self.execs_per_sec(cur_time);
|
||||
self.last_window_time = cur_time;
|
||||
self.last_window_executions = executions;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execs_per_sec(&self, cur_time: time::Duration) -> u64 {
|
||||
if self.executions == 0 {
|
||||
return 0;
|
||||
}
|
||||
let secs = (cur_time - self.last_window_time).as_secs();
|
||||
if secs == 0 {
|
||||
self.last_execs_per_sec
|
||||
} else {
|
||||
let diff = self.executions - self.last_window_executions;
|
||||
diff / secs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Stats {
|
||||
/// the client stats (mut)
|
||||
fn client_stats_mut(&mut self) -> &mut Vec<ClientStats>;
|
||||
|
||||
/// the client stats
|
||||
fn client_stats(&self) -> &[ClientStats];
|
||||
|
||||
/// creation time
|
||||
fn start_time(&mut self) -> time::Duration;
|
||||
|
||||
/// show the stats to the user
|
||||
fn show(&mut self, event_msg: String);
|
||||
|
||||
/// Amount of elements in the corpus (combined for all children)
|
||||
fn corpus_size(&self) -> u64 {
|
||||
self.client_stats()
|
||||
.iter()
|
||||
.fold(0u64, |acc, x| acc + x.corpus_size)
|
||||
}
|
||||
|
||||
/// Total executions
|
||||
#[inline]
|
||||
fn total_execs(&mut self) -> u64 {
|
||||
self.client_stats()
|
||||
.iter()
|
||||
.fold(0u64, |acc, x| acc + x.executions)
|
||||
}
|
||||
|
||||
/// Executions per second
|
||||
#[inline]
|
||||
fn execs_per_sec(&mut self) -> u64 {
|
||||
let cur_time = current_time();
|
||||
self.client_stats()
|
||||
.iter()
|
||||
.fold(0u64, |acc, x| acc + x.execs_per_sec(cur_time))
|
||||
}
|
||||
|
||||
/// The client stats for a specific id, creating new if it doesn't exist
|
||||
fn client_stats_mut_for(&mut self, client_id: u32) -> &mut ClientStats {
|
||||
let client_stat_count = self.client_stats().len();
|
||||
for _ in client_stat_count..(client_id + 1) as usize {
|
||||
self.client_stats_mut().push(ClientStats {
|
||||
last_window_time: current_time(),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
&mut self.client_stats_mut()[client_id as usize]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SimpleStats<F>
|
||||
where
|
||||
F: FnMut(String),
|
||||
{
|
||||
print_fn: F,
|
||||
start_time: Duration,
|
||||
corpus_size: usize,
|
||||
client_stats: Vec<ClientStats>,
|
||||
}
|
||||
|
||||
impl<F> Stats for SimpleStats<F>
|
||||
where
|
||||
F: FnMut(String),
|
||||
{
|
||||
/// the client stats, mutable
|
||||
fn client_stats_mut(&mut self) -> &mut Vec<ClientStats> {
|
||||
&mut self.client_stats
|
||||
}
|
||||
|
||||
/// the client stats
|
||||
fn client_stats(&self) -> &[ClientStats] {
|
||||
&self.client_stats
|
||||
}
|
||||
|
||||
/// Time this fuzzing run stated
|
||||
fn start_time(&mut self) -> time::Duration {
|
||||
self.start_time
|
||||
}
|
||||
|
||||
fn show(&mut self, event_msg: String) {
|
||||
let fmt = format!(
|
||||
"[{}] clients: {}, corpus: {}, executions: {}, exec/sec: {}",
|
||||
event_msg,
|
||||
self.client_stats().len(),
|
||||
self.corpus_size(),
|
||||
self.total_execs(),
|
||||
self.execs_per_sec()
|
||||
);
|
||||
(self.print_fn)(fmt);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> SimpleStats<F>
|
||||
where
|
||||
F: FnMut(String),
|
||||
{
|
||||
pub fn new(print_fn: F) -> Self {
|
||||
Self {
|
||||
print_fn: print_fn,
|
||||
start_time: current_time(),
|
||||
corpus_size: 0,
|
||||
client_stats: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_time(print_fn: F, start_time: time::Duration) -> Self {
|
||||
Self {
|
||||
print_fn: print_fn,
|
||||
start_time: start_time,
|
||||
corpus_size: 0,
|
||||
client_stats: vec![],
|
||||
}
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ pub mod utils;
|
||||
use alloc::string::String;
|
||||
use core::{fmt, marker::PhantomData};
|
||||
use corpus::Corpus;
|
||||
use events::EventManager;
|
||||
use events::{Event, EventManager};
|
||||
use executors::{Executor, HasObservers};
|
||||
use feedbacks::FeedbacksTuple;
|
||||
use inputs::Input;
|
||||
@ -86,7 +86,11 @@ where
|
||||
let cur = current_milliseconds();
|
||||
if cur - last > 60 * 100 {
|
||||
last = cur;
|
||||
manager.update_stats(state.executions(), state.executions_over_seconds())?;
|
||||
manager.fire(Event::UpdateStats {
|
||||
executions: state.executions(),
|
||||
execs_over_sec: state.executions_over_seconds(),
|
||||
phantom: PhantomData,
|
||||
})?
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -265,9 +269,10 @@ mod tests {
|
||||
|
||||
let mut state = State::new(corpus, tuple_list!());
|
||||
|
||||
let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| {
|
||||
let stats = SimpleStats::new(|s| {
|
||||
println!("{}", s);
|
||||
}));
|
||||
});
|
||||
let mut event_manager = LoggerEventManager::new(stats);
|
||||
|
||||
let mut executor = InMemoryExecutor::new(
|
||||
"main",
|
||||
|
@ -208,7 +208,7 @@ where
|
||||
let idx = self.scheduled.schedule(14, rand, input);
|
||||
let mutation = match idx {
|
||||
0 => mutation_bitflip,
|
||||
1 => mutation_byteflip,
|
||||
/*1 => mutation_byteflip,
|
||||
2 => mutation_byteinc,
|
||||
3 => mutation_bytedec,
|
||||
4 => mutation_byteneg,
|
||||
@ -219,7 +219,7 @@ where
|
||||
8 => mutation_dwordadd,
|
||||
9 => mutation_byteinteresting,
|
||||
10 => mutation_wordinteresting,
|
||||
11 => mutation_dwordinteresting,
|
||||
11 => mutation_dwordinteresting,*/
|
||||
_ => mutation_splice,
|
||||
};
|
||||
mutation(self, rand, state, input)?;
|
||||
@ -277,7 +277,7 @@ where
|
||||
pub fn new_default() -> Self {
|
||||
let mut scheduled = StdScheduledMutator::<C, I, R, S>::new();
|
||||
scheduled.add_mutation(mutation_bitflip);
|
||||
scheduled.add_mutation(mutation_byteflip);
|
||||
/*scheduled.add_mutation(mutation_byteflip);
|
||||
scheduled.add_mutation(mutation_byteinc);
|
||||
scheduled.add_mutation(mutation_bytedec);
|
||||
scheduled.add_mutation(mutation_byteneg);
|
||||
@ -301,7 +301,7 @@ where
|
||||
scheduled.add_mutation(mutation_bytesset);
|
||||
scheduled.add_mutation(mutation_bytesrandset);
|
||||
scheduled.add_mutation(mutation_bytescopy);
|
||||
scheduled.add_mutation(mutation_bytesswap);
|
||||
scheduled.add_mutation(mutation_bytesswap);*/
|
||||
|
||||
/* TODO
|
||||
scheduled.add_mutation(mutation_tokeninsert);
|
||||
|
@ -1,7 +1,7 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
events::EventManager,
|
||||
events::{Event, EventManager},
|
||||
executors::{Executor, HasObservers},
|
||||
feedbacks::FeedbacksTuple,
|
||||
inputs::Input,
|
||||
@ -76,13 +76,15 @@ where
|
||||
// So by default we shoudl trigger it in corpus.add, so that the user can override it and remove
|
||||
// if needed by particular cases
|
||||
if fitness > 0 {
|
||||
let observers_buf = manager.serialize_observers(observers)?;
|
||||
|
||||
// TODO decouple events manager and engine
|
||||
manager.new_testcase(
|
||||
&input_mut,
|
||||
observers,
|
||||
state.corpus().count() + 1,
|
||||
"test".into(),
|
||||
)?;
|
||||
manager.fire(Event::NewTestcase {
|
||||
input: input_mut.clone(),
|
||||
observers_buf,
|
||||
corpus_size: state.corpus().count() + 1,
|
||||
client_config: "TODO".into(),
|
||||
})?;
|
||||
state.add_if_interesting(input_mut, fitness)?;
|
||||
// let _ = corpus.add(testcase);
|
||||
} else {
|
||||
|
@ -10,7 +10,7 @@ use std::{
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, Testcase},
|
||||
events::EventManager,
|
||||
events::{Event, EventManager, LogSeverity},
|
||||
executors::{Executor, HasObservers},
|
||||
feedbacks::FeedbacksTuple,
|
||||
generators::Generator,
|
||||
@ -143,10 +143,11 @@ where
|
||||
for in_dir in in_dirs {
|
||||
self.load_from_directory(executor, generator, manager, in_dir)?;
|
||||
}
|
||||
manager.log(
|
||||
0,
|
||||
format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
||||
)?;
|
||||
manager.fire(Event::Log {
|
||||
severity_level: LogSeverity::Debug,
|
||||
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
||||
phantom: PhantomData,
|
||||
})?;
|
||||
manager.process(self)?;
|
||||
Ok(())
|
||||
}
|
||||
@ -350,10 +351,11 @@ where
|
||||
added += 1;
|
||||
}
|
||||
}
|
||||
manager.log(
|
||||
0,
|
||||
format!("Loaded {} over {} initial testcases", added, num),
|
||||
)?;
|
||||
manager.fire(Event::Log {
|
||||
severity_level: LogSeverity::Debug,
|
||||
message: format!("Loaded {} over {} initial testcases", added, num),
|
||||
phantom: PhantomData,
|
||||
})?;
|
||||
manager.process(self)?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ where
|
||||
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
||||
pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
|
||||
state_corpus_serialized: &[u8],
|
||||
stats: ST,
|
||||
) -> Result<(State<C, I, R, FT>, LlmpEventManager<I, SH, ST>), AflError>
|
||||
where
|
||||
C: Corpus<I, R>,
|
||||
@ -70,7 +69,7 @@ where
|
||||
let client_description = postcard::from_bytes(&tuple.1)?;
|
||||
Ok((
|
||||
postcard::from_bytes(&tuple.0)?,
|
||||
LlmpEventManager::existing_client_from_description(&client_description, stats)?,
|
||||
LlmpEventManager::existing_client_from_description(&client_description)?,
|
||||
))
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user