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 alloc::string::String;
|
||||||
use core::{fmt, marker::PhantomData};
|
use core::{fmt, marker::PhantomData};
|
||||||
use corpus::Corpus;
|
use corpus::Corpus;
|
||||||
use events::EventManager;
|
use events::{Event, EventManager};
|
||||||
use executors::{Executor, HasObservers};
|
use executors::{Executor, HasObservers};
|
||||||
use feedbacks::FeedbacksTuple;
|
use feedbacks::FeedbacksTuple;
|
||||||
use inputs::Input;
|
use inputs::Input;
|
||||||
@ -86,7 +86,11 @@ where
|
|||||||
let cur = current_milliseconds();
|
let cur = current_milliseconds();
|
||||||
if cur - last > 60 * 100 {
|
if cur - last > 60 * 100 {
|
||||||
last = cur;
|
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 state = State::new(corpus, tuple_list!());
|
||||||
|
|
||||||
let mut event_manager = LoggerEventManager::new(SimpleStats::new(|s| {
|
let stats = SimpleStats::new(|s| {
|
||||||
println!("{}", s);
|
println!("{}", s);
|
||||||
}));
|
});
|
||||||
|
let mut event_manager = LoggerEventManager::new(stats);
|
||||||
|
|
||||||
let mut executor = InMemoryExecutor::new(
|
let mut executor = InMemoryExecutor::new(
|
||||||
"main",
|
"main",
|
||||||
|
@ -208,7 +208,7 @@ where
|
|||||||
let idx = self.scheduled.schedule(14, rand, input);
|
let idx = self.scheduled.schedule(14, rand, input);
|
||||||
let mutation = match idx {
|
let mutation = match idx {
|
||||||
0 => mutation_bitflip,
|
0 => mutation_bitflip,
|
||||||
1 => mutation_byteflip,
|
/*1 => mutation_byteflip,
|
||||||
2 => mutation_byteinc,
|
2 => mutation_byteinc,
|
||||||
3 => mutation_bytedec,
|
3 => mutation_bytedec,
|
||||||
4 => mutation_byteneg,
|
4 => mutation_byteneg,
|
||||||
@ -219,7 +219,7 @@ where
|
|||||||
8 => mutation_dwordadd,
|
8 => mutation_dwordadd,
|
||||||
9 => mutation_byteinteresting,
|
9 => mutation_byteinteresting,
|
||||||
10 => mutation_wordinteresting,
|
10 => mutation_wordinteresting,
|
||||||
11 => mutation_dwordinteresting,
|
11 => mutation_dwordinteresting,*/
|
||||||
_ => mutation_splice,
|
_ => mutation_splice,
|
||||||
};
|
};
|
||||||
mutation(self, rand, state, input)?;
|
mutation(self, rand, state, input)?;
|
||||||
@ -277,7 +277,7 @@ where
|
|||||||
pub fn new_default() -> Self {
|
pub fn new_default() -> Self {
|
||||||
let mut scheduled = StdScheduledMutator::<C, I, R, S>::new();
|
let mut scheduled = StdScheduledMutator::<C, I, R, S>::new();
|
||||||
scheduled.add_mutation(mutation_bitflip);
|
scheduled.add_mutation(mutation_bitflip);
|
||||||
scheduled.add_mutation(mutation_byteflip);
|
/*scheduled.add_mutation(mutation_byteflip);
|
||||||
scheduled.add_mutation(mutation_byteinc);
|
scheduled.add_mutation(mutation_byteinc);
|
||||||
scheduled.add_mutation(mutation_bytedec);
|
scheduled.add_mutation(mutation_bytedec);
|
||||||
scheduled.add_mutation(mutation_byteneg);
|
scheduled.add_mutation(mutation_byteneg);
|
||||||
@ -301,7 +301,7 @@ where
|
|||||||
scheduled.add_mutation(mutation_bytesset);
|
scheduled.add_mutation(mutation_bytesset);
|
||||||
scheduled.add_mutation(mutation_bytesrandset);
|
scheduled.add_mutation(mutation_bytesrandset);
|
||||||
scheduled.add_mutation(mutation_bytescopy);
|
scheduled.add_mutation(mutation_bytescopy);
|
||||||
scheduled.add_mutation(mutation_bytesswap);
|
scheduled.add_mutation(mutation_bytesswap);*/
|
||||||
|
|
||||||
/* TODO
|
/* TODO
|
||||||
scheduled.add_mutation(mutation_tokeninsert);
|
scheduled.add_mutation(mutation_tokeninsert);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventManager,
|
events::{Event, EventManager},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::FeedbacksTuple,
|
||||||
inputs::Input,
|
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
|
// 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 needed by particular cases
|
||||||
if fitness > 0 {
|
if fitness > 0 {
|
||||||
|
let observers_buf = manager.serialize_observers(observers)?;
|
||||||
|
|
||||||
// TODO decouple events manager and engine
|
// TODO decouple events manager and engine
|
||||||
manager.new_testcase(
|
manager.fire(Event::NewTestcase {
|
||||||
&input_mut,
|
input: input_mut.clone(),
|
||||||
observers,
|
observers_buf,
|
||||||
state.corpus().count() + 1,
|
corpus_size: state.corpus().count() + 1,
|
||||||
"test".into(),
|
client_config: "TODO".into(),
|
||||||
)?;
|
})?;
|
||||||
state.add_if_interesting(input_mut, fitness)?;
|
state.add_if_interesting(input_mut, fitness)?;
|
||||||
// let _ = corpus.add(testcase);
|
// let _ = corpus.add(testcase);
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,7 +10,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
corpus::{Corpus, Testcase},
|
corpus::{Corpus, Testcase},
|
||||||
events::EventManager,
|
events::{Event, EventManager, LogSeverity},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
feedbacks::FeedbacksTuple,
|
feedbacks::FeedbacksTuple,
|
||||||
generators::Generator,
|
generators::Generator,
|
||||||
@ -143,10 +143,11 @@ where
|
|||||||
for in_dir in in_dirs {
|
for in_dir in in_dirs {
|
||||||
self.load_from_directory(executor, generator, manager, in_dir)?;
|
self.load_from_directory(executor, generator, manager, in_dir)?;
|
||||||
}
|
}
|
||||||
manager.log(
|
manager.fire(Event::Log {
|
||||||
0,
|
severity_level: LogSeverity::Debug,
|
||||||
format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
message: format!("Loaded {} initial testcases.", self.corpus().count()), // get corpus count
|
||||||
)?;
|
phantom: PhantomData,
|
||||||
|
})?;
|
||||||
manager.process(self)?;
|
manager.process(self)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -350,10 +351,11 @@ where
|
|||||||
added += 1;
|
added += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
manager.log(
|
manager.fire(Event::Log {
|
||||||
0,
|
severity_level: LogSeverity::Debug,
|
||||||
format!("Loaded {} over {} initial testcases", added, num),
|
message: format!("Loaded {} over {} initial testcases", added, num),
|
||||||
)?;
|
phantom: PhantomData,
|
||||||
|
})?;
|
||||||
manager.process(self)?;
|
manager.process(self)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,6 @@ where
|
|||||||
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
/// Deserialize the state and corpus tuple, previously serialized with `serialize_state_corpus(...)`
|
||||||
pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
|
pub fn deserialize_state_corpus_mgr<C, FT, I, R, SH, ST>(
|
||||||
state_corpus_serialized: &[u8],
|
state_corpus_serialized: &[u8],
|
||||||
stats: ST,
|
|
||||||
) -> Result<(State<C, I, R, FT>, LlmpEventManager<I, SH, ST>), AflError>
|
) -> Result<(State<C, I, R, FT>, LlmpEventManager<I, SH, ST>), AflError>
|
||||||
where
|
where
|
||||||
C: Corpus<I, R>,
|
C: Corpus<I, R>,
|
||||||
@ -70,7 +69,7 @@ where
|
|||||||
let client_description = postcard::from_bytes(&tuple.1)?;
|
let client_description = postcard::from_bytes(&tuple.1)?;
|
||||||
Ok((
|
Ok((
|
||||||
postcard::from_bytes(&tuple.0)?,
|
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