Merge branch 'main' of github.com:AFLplusplus/LibAFL into main
This commit is contained in:
commit
7c7c7e679f
2
.github/workflows/build_and_test.yml
vendored
2
.github/workflows/build_and_test.yml
vendored
@ -63,7 +63,7 @@ jobs:
|
|||||||
# cargo-hack's --feature-powerset would be nice here but libafl has a too many knobs
|
# cargo-hack's --feature-powerset would be nice here but libafl has a too many knobs
|
||||||
- name: Check each feature
|
- name: Check each feature
|
||||||
# Skipping python as it has to be built with the `maturin` tool
|
# Skipping python as it has to be built with the `maturin` tool
|
||||||
run: cargo hack check --feature-powerset --depth=2 --exclude-features=agpl,nautilus,python,sancov_pcguard_edges --no-dev-deps
|
run: cargo hack check --feature-powerset --depth=2 --exclude-features=agpl,nautilus,python,sancov_pcguard_edges,arm,aarch64,i386 --no-dev-deps
|
||||||
# pcguard edges and pcguard hitcounts are not compatible and we need to build them seperately
|
# pcguard edges and pcguard hitcounts are not compatible and we need to build them seperately
|
||||||
- name: Check pcguard edges
|
- name: Check pcguard edges
|
||||||
run: cargo check --features=sancov_pcguard_edges
|
run: cargo check --features=sancov_pcguard_edges
|
||||||
|
@ -34,14 +34,12 @@ pub fn main() {
|
|||||||
Arg::new("executable")
|
Arg::new("executable")
|
||||||
.about("The instrumented binary we want to fuzz")
|
.about("The instrumented binary we want to fuzz")
|
||||||
.required(true)
|
.required(true)
|
||||||
.index(1)
|
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("in")
|
Arg::new("in")
|
||||||
.about("The directory to read initial inputs from ('seeds')")
|
.about("The directory to read initial inputs from ('seeds')")
|
||||||
.required(true)
|
.required(true)
|
||||||
.index(2)
|
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -51,6 +49,11 @@ pub fn main() {
|
|||||||
.long("timeout")
|
.long("timeout")
|
||||||
.default_value("1200"),
|
.default_value("1200"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::new("arguments")
|
||||||
|
.setting(clap::ArgSettings::MultipleValues)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
let corpus_dirs = vec![PathBuf::from(res.value_of("in").unwrap().to_string())];
|
let corpus_dirs = vec![PathBuf::from(res.value_of("in").unwrap().to_string())];
|
||||||
@ -124,10 +127,15 @@ pub fn main() {
|
|||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
|
|
||||||
// Create the executor for the forkserver
|
// Create the executor for the forkserver
|
||||||
|
let args = match res.values_of("arguments") {
|
||||||
|
Some(vec) => vec.map(|s| s.to_string()).collect::<Vec<String>>().to_vec(),
|
||||||
|
None => [].to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut executor = TimeoutForkserverExecutor::new(
|
let mut executor = TimeoutForkserverExecutor::new(
|
||||||
ForkserverExecutor::new(
|
ForkserverExecutor::new(
|
||||||
res.value_of("executable").unwrap().to_string(),
|
res.value_of("executable").unwrap().to_string(),
|
||||||
&[],
|
&args,
|
||||||
true,
|
true,
|
||||||
tuple_list!(edges_observer, time_observer),
|
tuple_list!(edges_observer, time_observer),
|
||||||
)
|
)
|
||||||
|
@ -22,7 +22,9 @@ use libafl::{
|
|||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMemProvider},
|
||||||
tuples::{tuple_list, Merge},
|
tuples::{tuple_list, Merge},
|
||||||
},
|
},
|
||||||
corpus::{Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, QueueCorpusScheduler},
|
corpus::{
|
||||||
|
Corpus, IndexesLenTimeMinimizerCorpusScheduler, OnDiskCorpus, PowerQueueCorpusScheduler,
|
||||||
|
},
|
||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
@ -36,7 +38,11 @@ use libafl::{
|
|||||||
tokens_mutations, Tokens,
|
tokens_mutations, Tokens,
|
||||||
},
|
},
|
||||||
observers::{StdMapObserver, TimeObserver},
|
observers::{StdMapObserver, TimeObserver},
|
||||||
stages::{StdMutationalStage, TracingStage},
|
stages::{
|
||||||
|
calibrate::CalibrationStage,
|
||||||
|
power::{PowerMutationalStage, PowerSchedule},
|
||||||
|
StdMutationalStage, TracingStage,
|
||||||
|
},
|
||||||
state::{HasCorpus, HasMetadata, StdState},
|
state::{HasCorpus, HasMetadata, StdState},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
@ -248,8 +254,14 @@ fn fuzz(
|
|||||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let calibration = CalibrationStage::new(&mut state, &edges_observer);
|
||||||
|
let mutator = StdScheduledMutator::new(havoc_mutations());
|
||||||
|
|
||||||
|
let power = PowerMutationalStage::new(mutator, PowerSchedule::FAST, &edges_observer);
|
||||||
|
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(PowerQueueCorpusScheduler::new());
|
||||||
|
|
||||||
// A minimization+queue policy to get testcasess from the corpus
|
// A minimization+queue policy to get testcasess from the corpus
|
||||||
let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
//let scheduler = IndexesLenTimeMinimizerCorpusScheduler::new(QueueCorpusScheduler::new());
|
||||||
|
|
||||||
// A fuzzer with feedbacks and a corpus scheduler
|
// A fuzzer with feedbacks and a corpus scheduler
|
||||||
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
|
||||||
@ -297,7 +309,7 @@ fn fuzz(
|
|||||||
let mutational = StdMutationalStage::new(mutator);
|
let mutational = StdMutationalStage::new(mutator);
|
||||||
|
|
||||||
// The order of the stages matter!
|
// The order of the stages matter!
|
||||||
let mut stages = tuple_list!(tracing, i2s, mutational);
|
let mut stages = tuple_list!(calibration, tracing, i2s, mutational, power);
|
||||||
|
|
||||||
// Read tokens
|
// Read tokens
|
||||||
if let Some(tokenfile) = tokenfile {
|
if let Some(tokenfile) = tokenfile {
|
||||||
@ -324,6 +336,7 @@ fn fuzz(
|
|||||||
dup2(null_fd, io::stdout().as_raw_fd())?;
|
dup2(null_fd, io::stdout().as_raw_fd())?;
|
||||||
dup2(null_fd, io::stderr().as_raw_fd())?;
|
dup2(null_fd, io::stderr().as_raw_fd())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reopen file to make sure we're at the end
|
// reopen file to make sure we're at the end
|
||||||
log.replace(
|
log.replace(
|
||||||
OpenOptions::new()
|
OpenOptions::new()
|
||||||
|
@ -16,4 +16,4 @@ debug = true
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../../libafl/" }
|
libafl = { path = "../../libafl/" }
|
||||||
libafl_qemu = { path = "../../libafl_qemu/" }
|
libafl_qemu = { path = "../../libafl_qemu/", features = ["x86_64"] }
|
||||||
|
@ -177,14 +177,18 @@ where
|
|||||||
monitor.display(event.name().to_string(), client_id);
|
monitor.display(event.name().to_string(), client_id);
|
||||||
Ok(BrokerEventResult::Forward)
|
Ok(BrokerEventResult::Forward)
|
||||||
}
|
}
|
||||||
Event::UpdateExecutions {
|
Event::UpdateExecStats {
|
||||||
time,
|
time,
|
||||||
executions,
|
executions,
|
||||||
|
stability,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
} => {
|
} => {
|
||||||
// TODO: The monitor buffer should be added on client add.
|
// TODO: The monitor buffer should be added on client add.
|
||||||
let client = monitor.client_stats_mut_for(client_id);
|
let client = monitor.client_stats_mut_for(client_id);
|
||||||
client.update_executions(*executions as u64, *time);
|
client.update_executions(*executions as u64, *time);
|
||||||
|
if let Some(stability) = stability {
|
||||||
|
client.update_stability(*stability);
|
||||||
|
}
|
||||||
monitor.display(event.name().to_string(), client_id);
|
monitor.display(event.name().to_string(), client_id);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
@ -202,6 +206,7 @@ where
|
|||||||
Event::UpdatePerfMonitor {
|
Event::UpdatePerfMonitor {
|
||||||
time,
|
time,
|
||||||
executions,
|
executions,
|
||||||
|
stability,
|
||||||
introspection_monitor,
|
introspection_monitor,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
} => {
|
} => {
|
||||||
@ -213,6 +218,10 @@ where
|
|||||||
// Update the normal monitor for this client
|
// Update the normal monitor for this client
|
||||||
client.update_executions(*executions as u64, *time);
|
client.update_executions(*executions as u64, *time);
|
||||||
|
|
||||||
|
if let Some(stability) = stability {
|
||||||
|
client.update_stability(*stability);
|
||||||
|
}
|
||||||
|
|
||||||
// Update the performance monitor for this client
|
// Update the performance monitor for this client
|
||||||
client.update_introspection_monitor((**introspection_monitor).clone());
|
client.update_introspection_monitor((**introspection_monitor).clone());
|
||||||
|
|
||||||
|
@ -176,9 +176,11 @@ where
|
|||||||
executions: usize,
|
executions: usize,
|
||||||
},
|
},
|
||||||
/// New stats event to monitor.
|
/// New stats event to monitor.
|
||||||
UpdateExecutions {
|
UpdateExecStats {
|
||||||
/// The time of generation of the [`Event`]
|
/// The time of generation of the [`Event`]
|
||||||
time: Duration,
|
time: Duration,
|
||||||
|
/// The stability of this fuzzer node, if known
|
||||||
|
stability: Option<f32>,
|
||||||
/// The executions of this client
|
/// The executions of this client
|
||||||
executions: usize,
|
executions: usize,
|
||||||
/// [`PhantomData`]
|
/// [`PhantomData`]
|
||||||
@ -198,10 +200,10 @@ where
|
|||||||
UpdatePerfMonitor {
|
UpdatePerfMonitor {
|
||||||
/// The time of generation of the event
|
/// The time of generation of the event
|
||||||
time: Duration,
|
time: Duration,
|
||||||
|
|
||||||
/// The executions of this client
|
/// The executions of this client
|
||||||
executions: usize,
|
executions: usize,
|
||||||
|
/// The stability of this fuzzer node, if known
|
||||||
|
stability: Option<f32>,
|
||||||
/// Current performance statistics
|
/// Current performance statistics
|
||||||
introspection_monitor: Box<ClientPerfMonitor>,
|
introspection_monitor: Box<ClientPerfMonitor>,
|
||||||
|
|
||||||
@ -243,8 +245,9 @@ where
|
|||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
} => "Testcase",
|
} => "Testcase",
|
||||||
Event::UpdateExecutions {
|
Event::UpdateExecStats {
|
||||||
time: _,
|
time: _,
|
||||||
|
stability: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
}
|
}
|
||||||
@ -257,6 +260,7 @@ where
|
|||||||
Event::UpdatePerfMonitor {
|
Event::UpdatePerfMonitor {
|
||||||
time: _,
|
time: _,
|
||||||
executions: _,
|
executions: _,
|
||||||
|
stability: _,
|
||||||
introspection_monitor: _,
|
introspection_monitor: _,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
} => "PerfMonitor",
|
} => "PerfMonitor",
|
||||||
@ -288,6 +292,24 @@ where
|
|||||||
/// This should not happen for a normal use-cases.
|
/// This should not happen for a normal use-cases.
|
||||||
fn fire<S>(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
|
fn fire<S>(&mut self, state: &mut S, event: Event<I>) -> Result<(), Error>;
|
||||||
|
|
||||||
|
/// Send off an [`Event::Log`] event to the broker
|
||||||
|
/// This is a shortcut for [`EventFirer::fire`] with [`Event::Log`] as argument.
|
||||||
|
fn log<S>(
|
||||||
|
&mut self,
|
||||||
|
state: &mut S,
|
||||||
|
severity_level: LogSeverity,
|
||||||
|
message: String,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
self.fire(
|
||||||
|
state,
|
||||||
|
Event::Log {
|
||||||
|
severity_level,
|
||||||
|
message,
|
||||||
|
phantom: PhantomData,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Serialize all observers for this type and manager
|
/// Serialize all observers for this type and manager
|
||||||
fn serialize_observers<OT, S>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
fn serialize_observers<OT, S>(&mut self, observers: &OT) -> Result<Vec<u8>, Error>
|
||||||
where
|
where
|
||||||
@ -320,6 +342,7 @@ where
|
|||||||
S: HasExecutions + HasClientPerfMonitor,
|
S: HasExecutions + HasClientPerfMonitor,
|
||||||
{
|
{
|
||||||
let executions = *state.executions();
|
let executions = *state.executions();
|
||||||
|
let stability = *state.stability();
|
||||||
let cur = current_time();
|
let cur = current_time();
|
||||||
// default to 0 here to avoid crashes on clock skew
|
// default to 0 here to avoid crashes on clock skew
|
||||||
if cur.checked_sub(last_report_time).unwrap_or_default() > monitor_timeout {
|
if cur.checked_sub(last_report_time).unwrap_or_default() > monitor_timeout {
|
||||||
@ -327,8 +350,9 @@ where
|
|||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
self.fire(
|
self.fire(
|
||||||
state,
|
state,
|
||||||
Event::UpdateExecutions {
|
Event::UpdateExecStats {
|
||||||
executions,
|
executions,
|
||||||
|
stability,
|
||||||
time: cur,
|
time: cur,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
},
|
},
|
||||||
@ -348,6 +372,7 @@ where
|
|||||||
Event::UpdatePerfMonitor {
|
Event::UpdatePerfMonitor {
|
||||||
executions,
|
executions,
|
||||||
time: cur,
|
time: cur,
|
||||||
|
stability,
|
||||||
introspection_monitor: Box::new(state.introspection_monitor().clone()),
|
introspection_monitor: Box::new(state.introspection_monitor().clone()),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
},
|
},
|
||||||
|
@ -150,15 +150,20 @@ where
|
|||||||
monitor.display(event.name().to_string(), 0);
|
monitor.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
Event::UpdateExecutions {
|
Event::UpdateExecStats {
|
||||||
time,
|
time,
|
||||||
executions,
|
executions,
|
||||||
|
stability,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
} => {
|
} => {
|
||||||
// TODO: The monitor buffer should be added on client add.
|
// TODO: The monitor buffer should be added on client add.
|
||||||
monitor
|
let client = monitor.client_stats_mut_for(0);
|
||||||
.client_stats_mut_for(0)
|
|
||||||
.update_executions(*executions as u64, *time);
|
client.update_executions(*executions as u64, *time);
|
||||||
|
if let Some(stability) = stability {
|
||||||
|
client.update_stability(*stability);
|
||||||
|
}
|
||||||
|
|
||||||
monitor.display(event.name().to_string(), 0);
|
monitor.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
@ -177,13 +182,17 @@ where
|
|||||||
Event::UpdatePerfMonitor {
|
Event::UpdatePerfMonitor {
|
||||||
time,
|
time,
|
||||||
executions,
|
executions,
|
||||||
|
stability,
|
||||||
introspection_monitor,
|
introspection_monitor,
|
||||||
phantom: _,
|
phantom: _,
|
||||||
} => {
|
} => {
|
||||||
// TODO: The monitor buffer should be added on client add.
|
// TODO: The monitor buffer should be added on client add.
|
||||||
monitor.client_stats_mut()[0].update_executions(*executions as u64, *time);
|
let client = &mut monitor.client_stats_mut()[0];
|
||||||
monitor.client_stats_mut()[0]
|
client.update_executions(*executions as u64, *time);
|
||||||
.update_introspection_monitor((**introspection_monitor).clone());
|
client.update_introspection_monitor((**introspection_monitor).clone());
|
||||||
|
if let Some(stability) = stability {
|
||||||
|
client.update_stability(*stability);
|
||||||
|
}
|
||||||
monitor.display(event.name().to_string(), 0);
|
monitor.display(event.name().to_string(), 0);
|
||||||
Ok(BrokerEventResult::Handled)
|
Ok(BrokerEventResult::Handled)
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,6 @@ impl InProcessHandlers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn new<E, EM, I, OC, OF, OT, S, Z>() -> Result<Self, Error>
|
pub fn new<E, EM, I, OC, OF, OT, S, Z>() -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
|
@ -40,7 +40,7 @@ use crate::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// How an execution finished.
|
/// How an execution finished.
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
pub enum ExitKind {
|
pub enum ExitKind {
|
||||||
/// The run exited normally.
|
/// The run exited normally.
|
||||||
Ok,
|
Ok,
|
||||||
|
@ -118,6 +118,29 @@ impl<E> TimeoutExecutor<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
||||||
|
let milli_sec = exec_tmout.as_millis();
|
||||||
|
let it_value = Timeval {
|
||||||
|
tv_sec: (milli_sec / 1000) as i64,
|
||||||
|
tv_usec: (milli_sec % 1000) as i64,
|
||||||
|
};
|
||||||
|
let it_interval = Timeval {
|
||||||
|
tv_sec: 0,
|
||||||
|
tv_usec: 0,
|
||||||
|
};
|
||||||
|
let itimerval = Itimerval {
|
||||||
|
it_interval,
|
||||||
|
it_value,
|
||||||
|
};
|
||||||
|
self.itimerval = itimerval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
pub fn set_timeout(&mut self, exec_tmout: Duration) {
|
||||||
|
self.milli_sec = exec_tmout.as_millis() as u32;
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve the inner `Executor` that is wrapped by this `TimeoutExecutor`.
|
/// Retrieve the inner `Executor` that is wrapped by this `TimeoutExecutor`.
|
||||||
pub fn inner(&mut self) -> &mut E {
|
pub fn inner(&mut self) -> &mut E {
|
||||||
&mut self.executor
|
&mut self.executor
|
||||||
|
@ -243,7 +243,9 @@ where
|
|||||||
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
fn reset(&mut self) -> Result<(), Error> {
|
fn reset(&mut self) -> Result<(), Error> {
|
||||||
self.history_map.iter_mut().for_each(|x| *x = T::default());
|
self.history_map
|
||||||
|
.iter_mut()
|
||||||
|
.for_each(|x| *x = T::min_value());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,7 +268,7 @@ where
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
pub fn new(name: &'static str, map_size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
history_map: vec![T::default(); map_size],
|
history_map: vec![T::min_value(); map_size],
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -278,7 +280,7 @@ where
|
|||||||
T: Debug,
|
T: Debug,
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
history_map: vec![T::default(); map_observer.len()],
|
history_map: vec![T::min_value(); map_observer.len()],
|
||||||
name: map_observer.name().to_string(),
|
name: map_observer.name().to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,13 @@
|
|||||||
pub mod multi;
|
pub mod multi;
|
||||||
pub use multi::MultiMonitor;
|
pub use multi::MultiMonitor;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use alloc::{
|
||||||
|
string::{String, ToString},
|
||||||
use alloc::{string::String, vec::Vec};
|
vec::Vec,
|
||||||
|
};
|
||||||
use core::{fmt, time, time::Duration};
|
use core::{fmt, time, time::Duration};
|
||||||
|
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "introspection")]
|
|
||||||
use alloc::string::ToString;
|
|
||||||
|
|
||||||
use crate::bolts::{current_time, format_duration_hms};
|
use crate::bolts::{current_time, format_duration_hms};
|
||||||
|
|
||||||
@ -59,7 +57,8 @@ pub struct ClientStats {
|
|||||||
pub last_execs_per_sec: f32,
|
pub last_execs_per_sec: f32,
|
||||||
/// User-defined monitor
|
/// User-defined monitor
|
||||||
pub user_monitor: HashMap<String, UserStats>,
|
pub user_monitor: HashMap<String, UserStats>,
|
||||||
|
/// Stability, and if we ever received a stability value
|
||||||
|
pub stability: Option<f32>,
|
||||||
/// Client performance statistics
|
/// Client performance statistics
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
pub introspection_monitor: ClientPerfMonitor,
|
pub introspection_monitor: ClientPerfMonitor,
|
||||||
@ -89,6 +88,11 @@ impl ClientStats {
|
|||||||
self.objective_size = objective_size;
|
self.objective_size = objective_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// we got a new information about stability for this client, insert it.
|
||||||
|
pub fn update_stability(&mut self, stability: f32) {
|
||||||
|
self.stability = Some(stability);
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the calculated executions per second for this client
|
/// Get the calculated executions per second for this client
|
||||||
#[allow(clippy::cast_sign_loss, clippy::cast_precision_loss)]
|
#[allow(clippy::cast_sign_loss, clippy::cast_precision_loss)]
|
||||||
pub fn execs_per_sec(&mut self, cur_time: time::Duration) -> u64 {
|
pub fn execs_per_sec(&mut self, cur_time: time::Duration) -> u64 {
|
||||||
@ -150,6 +154,24 @@ pub trait Monitor {
|
|||||||
/// show the monitor to the user
|
/// show the monitor to the user
|
||||||
fn display(&mut self, event_msg: String, sender_id: u32);
|
fn display(&mut self, event_msg: String, sender_id: u32);
|
||||||
|
|
||||||
|
/// Show the Stabiliity
|
||||||
|
fn stability(&self) -> Option<f32> {
|
||||||
|
let mut stability_total = 0_f32;
|
||||||
|
let mut num = 0_usize;
|
||||||
|
for stat in self.client_stats() {
|
||||||
|
if let Some(stability) = stat.stability {
|
||||||
|
stability_total += stability;
|
||||||
|
num += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if num == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
|
Some(stability_total / num as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Amount of elements in the corpus (combined for all children)
|
/// Amount of elements in the corpus (combined for all children)
|
||||||
fn corpus_size(&self) -> u64 {
|
fn corpus_size(&self) -> u64 {
|
||||||
self.client_stats()
|
self.client_stats()
|
||||||
@ -269,13 +291,18 @@ where
|
|||||||
|
|
||||||
fn display(&mut self, event_msg: String, sender_id: u32) {
|
fn display(&mut self, event_msg: String, sender_id: u32) {
|
||||||
let fmt = format!(
|
let fmt = format!(
|
||||||
"[{} #{}] run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
|
"[{} #{}] run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, {} exec/sec: {}",
|
||||||
event_msg,
|
event_msg,
|
||||||
sender_id,
|
sender_id,
|
||||||
format_duration_hms(&(current_time() - self.start_time)),
|
format_duration_hms(&(current_time() - self.start_time)),
|
||||||
self.client_stats().len(),
|
self.client_stats().len(),
|
||||||
self.corpus_size(),
|
self.corpus_size(),
|
||||||
self.objective_size(),
|
self.objective_size(),
|
||||||
|
if let Some(stability) = self.stability() {
|
||||||
|
format!(", stability: {:.2}", stability)
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
},
|
||||||
self.total_execs(),
|
self.total_execs(),
|
||||||
self.execs_per_sec()
|
self.execs_per_sec()
|
||||||
);
|
);
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
bolts::current_time,
|
bolts::current_time,
|
||||||
corpus::{Corpus, PowerScheduleTestcaseMetaData},
|
corpus::{Corpus, PowerScheduleTestcaseMetaData},
|
||||||
executors::{Executor, HasObservers},
|
events::{EventFirer, LogSeverity},
|
||||||
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
|
feedbacks::{FeedbackStatesTuple, MapFeedbackState},
|
||||||
fuzzer::Evaluator,
|
fuzzer::Evaluator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::{MapObserver, ObserversTuple},
|
||||||
stages::Stage,
|
stages::Stage,
|
||||||
state::{HasCorpus, HasMetadata},
|
state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use alloc::{
|
use alloc::{
|
||||||
@ -20,11 +22,13 @@ use num_traits::PrimInt;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CalibrationStage<C, E, EM, I, O, OT, S, T, Z>
|
pub struct CalibrationStage<C, E, EM, FT, I, O, OT, S, T, Z>
|
||||||
where
|
where
|
||||||
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
FT: FeedbackStatesTuple,
|
||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver<T>,
|
O: MapObserver<T>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -34,53 +38,145 @@ where
|
|||||||
map_observer_name: String,
|
map_observer_name: String,
|
||||||
stage_max: usize,
|
stage_max: usize,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
phantom: PhantomData<(C, E, EM, I, O, OT, S, T, Z)>,
|
phantom: PhantomData<(C, E, EM, FT, I, O, OT, S, T, Z)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const CAL_STAGE_MAX: usize = 8;
|
const CAL_STAGE_START: usize = 4;
|
||||||
|
const CAL_STAGE_MAX: usize = 16;
|
||||||
|
|
||||||
impl<C, E, EM, I, O, OT, S, T, Z> Stage<E, EM, S, Z>
|
impl<C, E, EM, FT, I, O, OT, S, T, Z> Stage<E, EM, S, Z>
|
||||||
for CalibrationStage<C, E, EM, I, O, OT, S, T, Z>
|
for CalibrationStage<C, E, EM, FT, I, O, OT, S, T, Z>
|
||||||
where
|
where
|
||||||
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
FT: FeedbackStatesTuple,
|
||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver<T>,
|
O: MapObserver<T>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasCorpus<C, I> + HasMetadata,
|
S: HasCorpus<C, I> + HasMetadata + HasFeedbackStates<FT> + HasClientPerfMonitor,
|
||||||
Z: Evaluator<E, EM, I, S>,
|
Z: Evaluator<E, EM, I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::let_and_return)]
|
#[allow(clippy::let_and_return, clippy::too_many_lines)]
|
||||||
fn perform(
|
fn perform(
|
||||||
&mut self,
|
&mut self,
|
||||||
fuzzer: &mut Z,
|
fuzzer: &mut Z,
|
||||||
executor: &mut E,
|
executor: &mut E,
|
||||||
state: &mut S,
|
state: &mut S,
|
||||||
manager: &mut EM,
|
mgr: &mut EM,
|
||||||
corpus_idx: usize,
|
corpus_idx: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let iter = self.stage_max;
|
let mut iter = self.stage_max;
|
||||||
let handicap = state
|
let handicap = state
|
||||||
.metadata()
|
.metadata()
|
||||||
.get::<PowerScheduleMetadata>()
|
.get::<PowerScheduleMetadata>()
|
||||||
.ok_or_else(|| Error::KeyNotFound("PowerScheduleMetadata not found".to_string()))?
|
.ok_or_else(|| Error::KeyNotFound("PowerScheduleMetadata not found".to_string()))?
|
||||||
.queue_cycles;
|
.queue_cycles;
|
||||||
|
|
||||||
let start = current_time();
|
|
||||||
|
|
||||||
for _i in 0..iter {
|
|
||||||
let input = state
|
let input = state
|
||||||
.corpus()
|
.corpus()
|
||||||
.get(corpus_idx)?
|
.get(corpus_idx)?
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.load_input()?
|
.load_input()?
|
||||||
.clone();
|
.clone();
|
||||||
let _ = executor.run_target(fuzzer, state, manager, &input)?;
|
|
||||||
|
// Run once to get the initial calibration map
|
||||||
|
executor.observers_mut().pre_exec_all(state, &input)?;
|
||||||
|
let mut start = current_time();
|
||||||
|
|
||||||
|
let mut total_time = if executor.run_target(fuzzer, state, mgr, &input)? == ExitKind::Ok {
|
||||||
|
current_time() - start
|
||||||
|
} else {
|
||||||
|
mgr.log(
|
||||||
|
state,
|
||||||
|
LogSeverity::Warn,
|
||||||
|
"Corpus entry errored on execution!".into(),
|
||||||
|
)?;
|
||||||
|
// assume one second as default time
|
||||||
|
Duration::from_secs(1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let map_first = &executor
|
||||||
|
.observers()
|
||||||
|
.match_name::<O>(&self.map_observer_name)
|
||||||
|
.ok_or_else(|| Error::KeyNotFound("MapObserver not found".to_string()))?
|
||||||
|
.map()
|
||||||
|
.unwrap()
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
// Run CAL_STAGE_START - 1 times, increase by 2 for every time a new
|
||||||
|
// run is found to be unstable, with CAL_STAGE_MAX total runs.
|
||||||
|
let mut i = 1;
|
||||||
|
let mut has_errors = false;
|
||||||
|
let mut unstable_entries: usize = 0;
|
||||||
|
let map_len: usize = map_first.len() as usize;
|
||||||
|
while i < iter {
|
||||||
|
let input = state
|
||||||
|
.corpus()
|
||||||
|
.get(corpus_idx)?
|
||||||
|
.borrow_mut()
|
||||||
|
.load_input()?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
executor.observers_mut().pre_exec_all(state, &input)?;
|
||||||
|
start = current_time();
|
||||||
|
|
||||||
|
if executor.run_target(fuzzer, state, mgr, &input)? != ExitKind::Ok {
|
||||||
|
if !has_errors {
|
||||||
|
mgr.log(
|
||||||
|
state,
|
||||||
|
LogSeverity::Warn,
|
||||||
|
"Corpus entry errored on execution!".into(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
has_errors = true;
|
||||||
|
if iter < CAL_STAGE_MAX {
|
||||||
|
iter += 2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
total_time += current_time() - start;
|
||||||
|
|
||||||
|
let map = &executor
|
||||||
|
.observers()
|
||||||
|
.match_name::<O>(&self.map_observer_name)
|
||||||
|
.ok_or_else(|| Error::KeyNotFound("MapObserver not found".to_string()))?
|
||||||
|
.map()
|
||||||
|
.unwrap()
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
let history_map = &mut state
|
||||||
|
.feedback_states_mut()
|
||||||
|
.match_name_mut::<MapFeedbackState<T>>(&self.map_observer_name)
|
||||||
|
.unwrap()
|
||||||
|
.history_map;
|
||||||
|
|
||||||
|
for j in 0..map_len {
|
||||||
|
if map_first[j] != map[j] && history_map[j] != T::max_value() {
|
||||||
|
history_map[j] = T::max_value();
|
||||||
|
unstable_entries += 1;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = current_time();
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::cast_precision_loss)]
|
||||||
|
if unstable_entries != 0 {
|
||||||
|
*state.stability_mut() = Some((map_len - unstable_entries) as f32 / (map_len as f32));
|
||||||
|
|
||||||
|
if iter < CAL_STAGE_MAX {
|
||||||
|
iter += 2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let psmeta = state
|
||||||
|
.metadata_mut()
|
||||||
|
.get_mut::<PowerScheduleMetadata>()
|
||||||
|
.ok_or_else(|| Error::KeyNotFound("PowerScheduleMetadata not found".to_string()))?;
|
||||||
|
|
||||||
let map = executor
|
let map = executor
|
||||||
.observers()
|
.observers()
|
||||||
@ -89,20 +185,14 @@ where
|
|||||||
|
|
||||||
let bitmap_size = map.count_bytes();
|
let bitmap_size = map.count_bytes();
|
||||||
|
|
||||||
let psmeta = state
|
psmeta.set_exec_time(psmeta.exec_time() + total_time);
|
||||||
.metadata_mut()
|
|
||||||
.get_mut::<PowerScheduleMetadata>()
|
|
||||||
.ok_or_else(|| Error::KeyNotFound("PowerScheduleMetadata not found".to_string()))?;
|
|
||||||
|
|
||||||
psmeta.set_exec_time(psmeta.exec_time() + (end - start));
|
|
||||||
psmeta.set_cycles(psmeta.cycles() + (iter as u64));
|
psmeta.set_cycles(psmeta.cycles() + (iter as u64));
|
||||||
psmeta.set_bitmap_size(psmeta.bitmap_size() + bitmap_size);
|
psmeta.set_bitmap_size(psmeta.bitmap_size() + bitmap_size);
|
||||||
psmeta.set_bitmap_entries(psmeta.bitmap_entries() + 1);
|
psmeta.set_bitmap_entries(psmeta.bitmap_entries() + 1);
|
||||||
|
|
||||||
// println!("psmeta: {:#?}", psmeta);
|
|
||||||
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
|
let mut testcase = state.corpus().get(corpus_idx)?.borrow_mut();
|
||||||
|
|
||||||
testcase.set_exec_time((end - start) / (iter as u32));
|
testcase.set_exec_time(total_time / (iter as u32));
|
||||||
// println!("time: {:#?}", testcase.exec_time());
|
// println!("time: {:#?}", testcase.exec_time());
|
||||||
let data = testcase
|
let data = testcase
|
||||||
.metadata_mut()
|
.metadata_mut()
|
||||||
@ -208,11 +298,13 @@ impl PowerScheduleMetadata {
|
|||||||
|
|
||||||
crate::impl_serdeany!(PowerScheduleMetadata);
|
crate::impl_serdeany!(PowerScheduleMetadata);
|
||||||
|
|
||||||
impl<C, E, I, EM, O, OT, S, T, Z> CalibrationStage<C, E, EM, I, O, OT, S, T, Z>
|
impl<C, E, EM, FT, I, O, OT, S, T, Z> CalibrationStage<C, E, EM, FT, I, O, OT, S, T, Z>
|
||||||
where
|
where
|
||||||
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
T: PrimInt + Default + Copy + 'static + serde::Serialize + serde::de::DeserializeOwned + Debug,
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
E: Executor<EM, I, S, Z> + HasObservers<I, OT, S>,
|
||||||
|
EM: EventFirer<I>,
|
||||||
|
FT: FeedbackStatesTuple,
|
||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver<T>,
|
O: MapObserver<T>,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
@ -223,7 +315,7 @@ where
|
|||||||
state.add_metadata::<PowerScheduleMetadata>(PowerScheduleMetadata::new());
|
state.add_metadata::<PowerScheduleMetadata>(PowerScheduleMetadata::new());
|
||||||
Self {
|
Self {
|
||||||
map_observer_name: map_observer_name.name().to_string(),
|
map_observer_name: map_observer_name.name().to_string(),
|
||||||
stage_max: CAL_STAGE_MAX,
|
stage_max: CAL_STAGE_START,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,7 +246,7 @@ fn generate_mutations(iter: impl Iterator<Item = (SymExprRef, SymExpr)>) -> Vec<
|
|||||||
assert_eq!(bits_to_insert % 8, 0, "can only insert full bytes");
|
assert_eq!(bits_to_insert % 8, 0, "can only insert full bytes");
|
||||||
let after_len = (u64::from(target.get_size()) / 8) - offset - (bits_to_insert / 8);
|
let after_len = (u64::from(target.get_size()) / 8) - offset - (bits_to_insert / 8);
|
||||||
Some(
|
Some(
|
||||||
std::array::IntoIter::new([
|
[
|
||||||
if offset == 0 {
|
if offset == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -267,7 +267,8 @@ fn generate_mutations(iter: impl Iterator<Item = (SymExprRef, SymExpr)>) -> Vec<
|
|||||||
false,
|
false,
|
||||||
))
|
))
|
||||||
},
|
},
|
||||||
])
|
]
|
||||||
|
.into_iter()
|
||||||
.reduce(|acc: Option<BV>, val: Option<BV>| match (acc, val) {
|
.reduce(|acc: Option<BV>, val: Option<BV>| match (acc, val) {
|
||||||
(Some(prev), Some(next)) => Some(prev.concat(&next)),
|
(Some(prev), Some(next)) => Some(prev.concat(&next)),
|
||||||
(Some(prev), None) => Some(prev),
|
(Some(prev), None) => Some(prev),
|
||||||
|
@ -31,21 +31,16 @@ pub mod sync;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use sync::*;
|
pub use sync::*;
|
||||||
|
|
||||||
use crate::events::EventFirer;
|
|
||||||
use crate::events::EventRestarter;
|
|
||||||
use crate::events::HasEventManagerId;
|
|
||||||
use crate::events::ProgressReporter;
|
|
||||||
use crate::state::HasExecutions;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::rands::Rand,
|
bolts::rands::Rand,
|
||||||
corpus::Corpus,
|
corpus::{Corpus, CorpusScheduler},
|
||||||
corpus::CorpusScheduler,
|
events::{EventFirer, EventRestarter, HasEventManagerId, ProgressReporter},
|
||||||
executors::Executor,
|
executors::{Executor, HasObservers},
|
||||||
executors::HasObservers,
|
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::ObserversTuple,
|
observers::ObserversTuple,
|
||||||
state::HasRand,
|
state::{
|
||||||
state::{HasClientPerfMonitor, HasCorpus},
|
HasExecutions, HasRand, {HasClientPerfMonitor, HasCorpus},
|
||||||
|
},
|
||||||
Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasCorpusScheduler,
|
Error, EvaluatorObservers, ExecutesInput, ExecutionProcessor, HasCorpusScheduler,
|
||||||
};
|
};
|
||||||
use core::{convert::From, marker::PhantomData};
|
use core::{convert::From, marker::PhantomData};
|
||||||
|
@ -78,6 +78,12 @@ pub trait HasClientPerfMonitor {
|
|||||||
|
|
||||||
/// Mutatable ref to [`ClientPerfMonitor`]
|
/// Mutatable ref to [`ClientPerfMonitor`]
|
||||||
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor;
|
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor;
|
||||||
|
|
||||||
|
/// This node's stability
|
||||||
|
fn stability(&self) -> &Option<f32>;
|
||||||
|
|
||||||
|
/// This node's stability (mut)
|
||||||
|
fn stability_mut(&mut self) -> &mut Option<f32>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering metadata
|
/// Trait for elements offering metadata
|
||||||
@ -163,6 +169,8 @@ where
|
|||||||
metadata: SerdeAnyMap,
|
metadata: SerdeAnyMap,
|
||||||
/// MaxSize testcase size for mutators that appreciate it
|
/// MaxSize testcase size for mutators that appreciate it
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
|
/// The stability of the current fuzzing process
|
||||||
|
stability: Option<f32>,
|
||||||
|
|
||||||
/// Performance statistics for this fuzzer
|
/// Performance statistics for this fuzzer
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
@ -552,6 +560,7 @@ where
|
|||||||
Self {
|
Self {
|
||||||
rand,
|
rand,
|
||||||
executions: 0,
|
executions: 0,
|
||||||
|
stability: None,
|
||||||
start_time: Duration::from_millis(0),
|
start_time: Duration::from_millis(0),
|
||||||
metadata: SerdeAnyMap::default(),
|
metadata: SerdeAnyMap::default(),
|
||||||
corpus,
|
corpus,
|
||||||
@ -581,6 +590,18 @@ where
|
|||||||
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
|
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
|
||||||
&mut self.introspection_monitor
|
&mut self.introspection_monitor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This node's stability
|
||||||
|
#[inline]
|
||||||
|
fn stability(&self) -> &Option<f32> {
|
||||||
|
&self.stability
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This node's stability (mut)
|
||||||
|
#[inline]
|
||||||
|
fn stability_mut(&mut self) -> &mut Option<f32> {
|
||||||
|
&mut self.stability
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "introspection"))]
|
#[cfg(not(feature = "introspection"))]
|
||||||
@ -599,4 +620,16 @@ where
|
|||||||
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
|
fn introspection_monitor_mut(&mut self) -> &mut ClientPerfMonitor {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This node's stability
|
||||||
|
#[inline]
|
||||||
|
fn stability(&self) -> &Option<f32> {
|
||||||
|
&self.stability
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This node's stability (mut)
|
||||||
|
#[inline]
|
||||||
|
fn stability_mut(&mut self) -> &mut Option<f32> {
|
||||||
|
&mut self.stability
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,14 @@ edition = "2021"
|
|||||||
python = ["pyo3", "pyo3-build-config"]
|
python = ["pyo3", "pyo3-build-config"]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
# The following architecture features are mutually exclusive.
|
||||||
|
x86_64 = [] # build qemu for x86_64 (default)
|
||||||
|
i386 = [] # build qemu for i386
|
||||||
|
arm = [] # build qemu for arm
|
||||||
|
aarch64 = [] # build qemu for aarch64
|
||||||
|
|
||||||
|
clippy = [] # special feature for clippy, don't use in normal projects§
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libafl = { path = "../libafl", version = "0.7.0" }
|
libafl = { path = "../libafl", version = "0.7.0" }
|
||||||
libafl_targets = { path = "../libafl_targets", version = "0.7.0" }
|
libafl_targets = { path = "../libafl_targets", version = "0.7.0" }
|
||||||
|
@ -11,12 +11,24 @@ fn build_dep_check(tools: &[&str]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! assert_unique_feature {
|
||||||
|
() => {};
|
||||||
|
($first:tt $(,$rest:tt)*) => {
|
||||||
|
$(
|
||||||
|
#[cfg(not(feature = "clippy"))] // ignore multiple definition for clippy
|
||||||
|
#[cfg(all(feature = $first, feature = $rest))]
|
||||||
|
compile_error!(concat!("features \"", $first, "\" and \"", $rest, "\" cannot be used together"));
|
||||||
|
)*
|
||||||
|
assert_unique_feature!($($rest),*);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
println!("cargo:rerun-if-changed=src/asan-giovese.c");
|
println!("cargo:rerun-if-changed=src/asan-giovese.c");
|
||||||
println!("cargo:rerun-if-changed=src/asan-giovese.h");
|
println!("cargo:rerun-if-changed=src/asan-giovese.h");
|
||||||
println!("cargo:rerun-if-env-changed=CPU_TARGET");
|
|
||||||
println!("cargo:rerun-if-env-changed=CROSS_CC");
|
println!("cargo:rerun-if-env-changed=CROSS_CC");
|
||||||
|
|
||||||
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||||
@ -24,13 +36,40 @@ fn main() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we have at least and at most one architecutre feature set
|
||||||
|
// Else, we default to `x86_64` - having a default makes CI easier :)
|
||||||
|
assert_unique_feature!("arm", "aarch64", "i386", "i86_64");
|
||||||
|
#[cfg(not(any(
|
||||||
|
feature = "arm",
|
||||||
|
feature = "aarch64",
|
||||||
|
feature = "i386",
|
||||||
|
feature = "x86_64"
|
||||||
|
)))]
|
||||||
|
println!(
|
||||||
|
"cargo:warning=No architecture feature enabled for libafl_qemu, supported: arm, aarch64, i386, x86_64 - defaulting to x86_64"
|
||||||
|
);
|
||||||
|
|
||||||
|
let cpu_target = if cfg!(feature = "clippy") {
|
||||||
|
// assume x86_64 for clippy
|
||||||
|
"x86_64"
|
||||||
|
} else if cfg!(feature = "arm") {
|
||||||
|
"arm"
|
||||||
|
} else if cfg!(feature = "aarch64") {
|
||||||
|
"aarch64"
|
||||||
|
} else if cfg!(feature = "i386") {
|
||||||
|
"368"
|
||||||
|
} else {
|
||||||
|
// if cfg!(feature = "x86_64") {
|
||||||
|
"x86_64"
|
||||||
|
/*} else {
|
||||||
|
panic!("No architecture feture enabled for libafl_qemu");
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
let jobs = env::var("CARGO_BUILD_JOBS");
|
let jobs = env::var("CARGO_BUILD_JOBS");
|
||||||
let cpu_target = env::var("CPU_TARGET").unwrap_or_else(|_| {
|
|
||||||
println!("cargo:warning=CPU_TARGET is not set, default to x86_64");
|
|
||||||
"x86_64".to_owned()
|
|
||||||
});
|
|
||||||
let cross_cc = env::var("CROSS_CC").unwrap_or_else(|_| {
|
let cross_cc = env::var("CROSS_CC").unwrap_or_else(|_| {
|
||||||
println!("cargo:warning=CROSS_CC is not set, default to cc (things can go wrong if CPU_TARGET is not the host arch)");
|
println!("cargo:warning=CROSS_CC is not set, default to cc (things can go wrong if the selected cpu target ({}) is not the host arch ({}))", cpu_target, env::consts::ARCH);
|
||||||
"cc".to_owned()
|
"cc".to_owned()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,17 +1,40 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
#[cfg(feature = "aarch64")]
|
||||||
pub mod aarch64;
|
pub mod aarch64;
|
||||||
pub mod arm;
|
#[cfg(all(feature = "aarch64", not(feature = "clippy")))]
|
||||||
pub mod i386;
|
|
||||||
pub mod x86_64;
|
|
||||||
|
|
||||||
#[cfg(cpu_target = "aarch64")]
|
|
||||||
pub use aarch64::*;
|
pub use aarch64::*;
|
||||||
#[cfg(cpu_target = "arm")]
|
|
||||||
|
#[cfg(feature = "arm")]
|
||||||
|
pub mod arm;
|
||||||
|
#[cfg(all(feature = "arm", not(feature = "clippy")))]
|
||||||
pub use arm::*;
|
pub use arm::*;
|
||||||
#[cfg(cpu_target = "i386")]
|
|
||||||
|
#[cfg(feature = "i386")]
|
||||||
|
pub mod i386;
|
||||||
|
#[cfg(all(feature = "i386", not(feature = "clippy")))]
|
||||||
pub use i386::*;
|
pub use i386::*;
|
||||||
#[cfg(cpu_target = "x86_64")]
|
|
||||||
|
// We default to x86_64, having a default makes CI easier :)
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "x86_64",
|
||||||
|
not(any(
|
||||||
|
feature = "arm",
|
||||||
|
feature = "aarch64",
|
||||||
|
feature = "i386",
|
||||||
|
feature = "x86_64"
|
||||||
|
))
|
||||||
|
))]
|
||||||
|
pub mod x86_64;
|
||||||
|
#[cfg(any(
|
||||||
|
feature = "x86_64",
|
||||||
|
not(any(
|
||||||
|
feature = "arm",
|
||||||
|
feature = "aarch64",
|
||||||
|
feature = "i386",
|
||||||
|
feature = "x86_64"
|
||||||
|
))
|
||||||
|
))]
|
||||||
pub use x86_64::*;
|
pub use x86_64::*;
|
||||||
|
|
||||||
pub mod elf;
|
pub mod elf;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user