FeedbackState as metadata (#627)
* SerdeAny MapFeedbackState * Fix macro syntax * alloc * fix * Metadata calibrate and map feedback * metadata feedback states * compile * fmt * Register common generic types * tests * sugar * no_std * fix book * alloc * fix fuzzers * fix * fmt * disable python bindings for libafl * clippy * fmt * fixes * fmt * fix * fix * fix * fix * fix * release autofix * fix * fix * fix * fmt * fix * fix * name * fix Co-authored-by: Dominik Maier <dmnk@google.com>
This commit is contained in:
parent
fa839bb08d
commit
da537aae83
@ -7,8 +7,8 @@ edition = "2021"
|
||||
pyo3 = { version = "0.15", features = ["extension-module"] }
|
||||
libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] }
|
||||
libafl_sugar = { path = "../../libafl_sugar", version = "0.7", features = ["python"] }
|
||||
libafl = { path = "../../libafl", version = "0.7", features = ["python"] }
|
||||
|
||||
#libafl = { path = "../../libafl", version = "0.7", features = ["python"] }
|
||||
libafl = { path = "../../libafl", version = "0.7" }
|
||||
|
||||
[build-dependencies]
|
||||
pyo3-build-config = { version = "0.15" }
|
||||
|
@ -1,4 +1,4 @@
|
||||
use libafl;
|
||||
//use libafl;
|
||||
use libafl_qemu;
|
||||
use libafl_sugar;
|
||||
use pyo3::prelude::*;
|
||||
@ -14,9 +14,9 @@ pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
|
||||
libafl_qemu::python_module(py, qemu_module)?;
|
||||
m.add_submodule(qemu_module)?;
|
||||
|
||||
let libafl_module = PyModule::new(py, "libafl")?;
|
||||
libafl::python_module(py, libafl_module)?;
|
||||
m.add_submodule(libafl_module)?;
|
||||
//let libafl_module = PyModule::new(py, "libafl")?;
|
||||
//libafl::python_module(py, libafl_module)?;
|
||||
//m.add_submodule(libafl_module)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -114,8 +114,9 @@ let mut state = StdState::new(
|
||||
// Corpus in which we store solutions (crashes in this example),
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
(),
|
||||
);
|
||||
&mut (),
|
||||
&mut ()
|
||||
).unwrap();
|
||||
```
|
||||
|
||||
It takes a random number generator, that is part of the fuzzer state, in this case, we use the default one `StdRand` but you can choose a different one. We seed it with the current nanoseconds.
|
||||
@ -273,7 +274,7 @@ let mut executor = InProcessExecutor::new(
|
||||
.expect("Failed to create the Executor".into());
|
||||
```
|
||||
|
||||
Now that the fuzzer can observe which condition is satisfied, we need a way to rate an input as interesting (i.e. worth of addition to the corpus) based on this observation. Here comes the notion of Feedback. The Feedback is part of the State and provides a way to rate input and its corresponding execution as interesting looking for the information in the observers. Feedbacks can maintain a cumulative state of the information seen so far in a so-called FeedbackState instance, in our case it maintains the set of conditions satisfied in the previous runs.
|
||||
Now that the fuzzer can observe which condition is satisfied, we need a way to rate an input as interesting (i.e. worth of addition to the corpus) based on this observation. Here comes the notion of Feedback. The Feedback is part of the State and provides a way to rate input and its corresponding execution as interesting looking for the information in the observers. Feedbacks can maintain a cumulative state of the information seen so far in a metadata in the State, in our case it maintains the set of conditions satisfied in the previous runs.
|
||||
|
||||
We use MaxMapFeedback, a feedback that implements a novelty search over the map of the MapObserver. Basically, if there is a value in the observer's map that is greater than the maximum value registered so far for the same entry, it rates the input as interesting and updates its state.
|
||||
|
||||
@ -286,20 +287,17 @@ extern crate libafl;
|
||||
use libafl::{
|
||||
bolts::{current_nanos, rands::StdRand, tuples::tuple_list},
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
feedbacks::{MapFeedbackState, MaxMapFeedback, CrashFeedback},
|
||||
feedbacks::{MaxMapFeedback, CrashFeedback},
|
||||
fuzzer::StdFuzzer,
|
||||
state::StdState,
|
||||
observers::StdMapObserver,
|
||||
};
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -310,10 +308,9 @@ let mut state = StdState::new(
|
||||
// Corpus in which we store solutions (crashes in this example),
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
&mut feedback,
|
||||
&mut objective
|
||||
).unwrap();
|
||||
|
||||
// ...
|
||||
|
||||
|
@ -8,7 +8,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -41,7 +41,7 @@ pub fn main() {
|
||||
signals_set(2);
|
||||
if buf.len() > 2 && buf[2] == b'c' {
|
||||
#[cfg(unix)]
|
||||
panic!("=(");
|
||||
panic!("Artificial bug triggered =)");
|
||||
|
||||
// panic!() raises a STATUS_STACK_BUFFER_OVERRUN exception which cannot be caught by the exception handler.
|
||||
// Here we make it raise STATUS_ACCESS_VIOLATION instead.
|
||||
@ -58,16 +58,14 @@ pub fn main() {
|
||||
};
|
||||
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let observer =
|
||||
unsafe { StdMapObserver::new_from_ptr("signals", SIGNALS.as_mut_ptr(), SIGNALS.len()) };
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -79,9 +77,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -13,7 +13,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::{Automaton, GramatronGenerator},
|
||||
inputs::GramatronInput,
|
||||
@ -61,14 +61,11 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -80,9 +77,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -9,7 +9,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
||||
inputs::{GeneralizedInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -92,14 +92,11 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new_tracking(&feedback_state, &observer, false, true);
|
||||
let mut feedback = MaxMapFeedback::new_tracking(&observer, false, true);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -111,9 +108,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if state.metadata().get::<Tokens>().is_none() {
|
||||
state.add_metadata(Tokens::from([b"FOO".to_vec(), b"BAR".to_vec()]));
|
||||
|
@ -9,9 +9,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedback_or,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::{NautilusContext, NautilusGenerator},
|
||||
inputs::NautilusInput,
|
||||
@ -51,17 +49,14 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = feedback_or!(
|
||||
MaxMapFeedback::new(&feedback_state, &observer),
|
||||
let mut feedback = feedback_or!(
|
||||
MaxMapFeedback::new(&observer),
|
||||
NautilusFeedback::new(&context)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -73,9 +68,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if state.metadata().get::<NautilusChunksMetadata>().is_none() {
|
||||
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));
|
||||
|
@ -9,7 +9,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
||||
inputs::{EncodedInput, InputDecoder, InputEncoder, NaiveTokenizer, TokenInputEncoderDecoder},
|
||||
monitors::SimpleMonitor,
|
||||
@ -69,14 +69,11 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -88,9 +85,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -14,7 +14,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{ExitKind, InProcessForkExecutor},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -68,14 +68,11 @@ pub fn main() {
|
||||
let observer = StdMapObserver::new("signals", signals_clone.as_mut_slice());
|
||||
// Create a stacktrace observer to add the observers tuple
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -87,9 +84,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -9,7 +9,7 @@ use libafl::{
|
||||
corpus::InMemoryCorpus,
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -77,14 +77,11 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -96,9 +93,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
InMemoryCorpus::new(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| {
|
||||
|
@ -14,9 +14,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::InProcessForkExecutor,
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -59,17 +57,13 @@ pub fn main() {
|
||||
libafl::observers::HarnessType::Child,
|
||||
);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let st_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_and!(
|
||||
let mut objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
||||
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||
);
|
||||
|
||||
// create a State from scratch
|
||||
@ -82,9 +76,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, st_feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -8,9 +8,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -48,17 +46,13 @@ pub fn main() {
|
||||
libafl::observers::HarnessType::InProcess,
|
||||
);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let st_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_and!(
|
||||
let mut objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
||||
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||
);
|
||||
|
||||
// create a State from scratch
|
||||
@ -71,9 +65,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, st_feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -10,9 +10,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::command::CommandConfigurator,
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{HasTargetBytes, Input},
|
||||
@ -43,22 +41,15 @@ pub fn main() {
|
||||
// Create a stacktrace observer
|
||||
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let bt_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_and!(
|
||||
let mut objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::<ASANBacktraceObserver>::new_with_observer(
|
||||
"ASANBacktraceObserver",
|
||||
&bt_observer
|
||||
)
|
||||
NewHashFeedback::<ASANBacktraceObserver>::new(&bt_observer)
|
||||
);
|
||||
// let objective = CrashFeedback::new();
|
||||
// let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -70,9 +61,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, bt_feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -10,9 +10,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::forkserver::ForkserverExecutor,
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::BytesInput,
|
||||
@ -54,20 +52,13 @@ pub fn main() {
|
||||
|
||||
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let bt_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false);
|
||||
let mut feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
// We want to do the same crash deduplication that AFL does
|
||||
let objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::new_with_observer("NewHashFeedback", &bt_observer)
|
||||
);
|
||||
let mut objective = feedback_and!(CrashFeedback::new(), NewHashFeedback::new(&bt_observer));
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -79,9 +70,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, bt_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -15,9 +15,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::{ExitKind, InProcessForkExecutor},
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -76,17 +74,13 @@ pub fn main() {
|
||||
libafl::observers::HarnessType::Child,
|
||||
);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let bt_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_and!(
|
||||
let mut objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
||||
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||
);
|
||||
|
||||
// create a State from scratch
|
||||
@ -99,9 +93,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, bt_feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -9,9 +9,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedback_and,
|
||||
feedbacks::{
|
||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
||||
},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -70,17 +68,13 @@ pub fn main() {
|
||||
libafl::observers::HarnessType::InProcess,
|
||||
);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
let hash_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_and!(
|
||||
let mut objective = feedback_and!(
|
||||
CrashFeedback::new(),
|
||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("NewHashFeedback", &bt_observer)
|
||||
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||
);
|
||||
|
||||
// create a State from scratch
|
||||
@ -93,9 +87,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, hash_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -1,4 +1,4 @@
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use core::time::Duration;
|
||||
use libafl::{
|
||||
bolts::{
|
||||
@ -12,7 +12,7 @@ use libafl::{
|
||||
events::SimpleEventManager,
|
||||
executors::forkserver::{ForkserverExecutor, TimeoutForkserverExecutor},
|
||||
feedback_and_fast, feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::BytesInput,
|
||||
monitors::SimpleMonitor,
|
||||
@ -33,7 +33,7 @@ use libafl::bolts::shmem::StdShMemProvider;
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
pub fn main() {
|
||||
let res = App::new("forkserver_simple")
|
||||
let res = Command::new("forkserver_simple")
|
||||
.about("Example Forkserver fuzer")
|
||||
.arg(
|
||||
Arg::new("executable")
|
||||
@ -63,7 +63,7 @@ pub fn main() {
|
||||
.arg(
|
||||
Arg::new("arguments")
|
||||
.help("Arguments passed to the target")
|
||||
.setting(clap::ArgSettings::MultipleValues)
|
||||
.multiple_values(true)
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
@ -101,28 +101,22 @@ pub fn main() {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// The state of the edges feedback for crashes.
|
||||
let objective_state = MapFeedbackState::new("crash_edges", MAP_SIZE);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
// We want to do the same crash deduplication that AFL does
|
||||
let objective = feedback_and_fast!(
|
||||
let mut objective = feedback_and_fast!(
|
||||
// Must be a crash
|
||||
CrashFeedback::new(),
|
||||
// Take it onlt if trigger new coverage over crashes
|
||||
MaxMapFeedback::new(&objective_state, &edges_observer)
|
||||
MaxMapFeedback::<_, _, _, u8>::new(&edges_observer)
|
||||
);
|
||||
|
||||
// create a State from scratch
|
||||
@ -135,9 +129,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state, objective_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
@ -163,7 +160,7 @@ pub fn main() {
|
||||
|
||||
let mut tokens = Tokens::new();
|
||||
let forkserver = ForkserverExecutor::builder()
|
||||
.program(res.value_of("executable").unwrap().to_string())
|
||||
.program(res.value_of("executable").unwrap())
|
||||
.debug_child(debug_child)
|
||||
.shmem_provider(&mut shmem_provider)
|
||||
.autotokens(&mut tokens)
|
||||
|
@ -20,8 +20,8 @@ use libafl::{
|
||||
corpus::{ondisk::OnDiskMetadataFormat, CachedOnDiskCorpus, Corpus, OnDiskCorpus},
|
||||
events::{llmp::LlmpRestartingEventManager, EventConfig},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedback_and_fast, feedback_or, feedback_or_fast,
|
||||
feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -72,9 +72,13 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
|
||||
let shmem_provider = StdShMemProvider::new()?;
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
||||
let mut run_client = |state: Option<_>,
|
||||
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
core_id| {
|
||||
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
|
||||
|
||||
// println!("{:?}", mgr.mgr_id());
|
||||
|
||||
let lib = libloading::Library::new(options.clone().harness.unwrap()).unwrap();
|
||||
let target_func: libloading::Symbol<
|
||||
unsafe extern "C" fn(data: *const u8, size: usize) -> i32,
|
||||
@ -88,9 +92,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
};
|
||||
|
||||
if options.asan && options.asan_cores.contains(core_id) {
|
||||
(|state: Option<StdState<_, _, _, _, _>>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||
let gum = Gum::obtain();
|
||||
|
||||
let coverage = CoverageRuntime::new();
|
||||
@ -114,26 +116,25 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// Feedbacks to recognize an input as solution
|
||||
#[cfg(unix)]
|
||||
let objective = feedback_or_fast!(
|
||||
let mut objective = feedback_or_fast!(
|
||||
CrashFeedback::new(),
|
||||
TimeoutFeedback::new(),
|
||||
AsanErrorsFeedback::new()
|
||||
// true enables the AsanErrorFeedback
|
||||
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
||||
);
|
||||
#[cfg(windows)]
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -149,10 +150,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
Some(OnDiskMetadataFormat::JsonPretty),
|
||||
)
|
||||
.unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
@ -216,9 +217,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
Ok(())
|
||||
})(state, mgr, core_id)
|
||||
} else if options.cmplog && options.cmplog_cores.contains(core_id) {
|
||||
(|state: Option<StdState<_, _, _, _, _>>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||
let gum = Gum::obtain();
|
||||
|
||||
let coverage = CoverageRuntime::new();
|
||||
@ -237,19 +236,23 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// Feedbacks to recognize an input as solution
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
#[cfg(unix)]
|
||||
let mut objective = feedback_or_fast!(
|
||||
CrashFeedback::new(),
|
||||
TimeoutFeedback::new(),
|
||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
||||
);
|
||||
#[cfg(windows)]
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -265,10 +268,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
Some(OnDiskMetadataFormat::JsonPretty),
|
||||
)
|
||||
.unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
@ -348,9 +351,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
Ok(())
|
||||
})(state, mgr, core_id)
|
||||
} else {
|
||||
(|state: Option<StdState<_, _, _, _, _>>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||
let gum = Gum::obtain();
|
||||
|
||||
let coverage = CoverageRuntime::new();
|
||||
@ -368,19 +369,23 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// Feedbacks to recognize an input as solution
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
#[cfg(unix)]
|
||||
let mut objective = feedback_or_fast!(
|
||||
CrashFeedback::new(),
|
||||
TimeoutFeedback::new(),
|
||||
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
|
||||
);
|
||||
#[cfg(windows)]
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -396,10 +401,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
||||
Some(OnDiskMetadataFormat::JsonPretty),
|
||||
)
|
||||
.unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
||||
#[global_allocator]
|
||||
static GLOBAL: MiMalloc = MiMalloc;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
#[cfg(unix)]
|
||||
use nix::{self, unistd::dup};
|
||||
@ -30,7 +30,7 @@ use libafl::{
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -64,7 +64,7 @@ pub fn libafl_main() {
|
||||
// Needed only on no_std
|
||||
//RegistryBuilder::register::<Tokens>();
|
||||
|
||||
let res = match App::new("libafl_fuzzbench")
|
||||
let res = match Command::new("libafl_fuzzbench")
|
||||
.version("0.7.1")
|
||||
.author("AFLplusplus team")
|
||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||
@ -113,7 +113,7 @@ pub fn libafl_main() {
|
||||
env::current_exe()
|
||||
.unwrap_or_else(|_| "fuzzer".into())
|
||||
.to_string_lossy(),
|
||||
err.info,
|
||||
err,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -260,20 +260,21 @@ fn fuzz(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -286,9 +287,12 @@ fn fuzz(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("Let's fuzz :)");
|
||||
@ -300,8 +304,6 @@ fn fuzz(
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||
}
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "fuzzbench_qemu"
|
||||
name = "fuzzbench_fork_qemu"
|
||||
version = "0.7.1"
|
||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||
edition = "2021"
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use core::cell::RefCell;
|
||||
#[cfg(unix)]
|
||||
use nix::{self, unistd::dup};
|
||||
@ -27,7 +27,7 @@ use libafl::{
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{ExitKind, ShadowExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -62,7 +62,7 @@ pub fn main() {
|
||||
// Needed only on no_std
|
||||
//RegistryBuilder::register::<Tokens>();
|
||||
|
||||
let res = match App::new("libafl_qemu_fuzzbench")
|
||||
let res = match Command::new("libafl_qemu_fuzzbench")
|
||||
.version("0.4.0")
|
||||
.author("AFLplusplus team")
|
||||
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
||||
@ -101,7 +101,7 @@ pub fn main() {
|
||||
env::current_exe()
|
||||
.unwrap_or_else(|_| "fuzzer".into())
|
||||
.to_string_lossy(),
|
||||
err.info,
|
||||
err,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -240,20 +240,21 @@ fn fuzz(
|
||||
let cmplog_observer =
|
||||
CmpLogObserver::new("cmplog", unsafe { CMPLOG_MAP_PTR.as_mut().unwrap() }, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -266,13 +267,14 @@ fn fuzz(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
#[cfg(unix)]
|
||||
use nix::{self, unistd::dup};
|
||||
@ -27,7 +27,7 @@ use libafl::{
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -68,7 +68,7 @@ pub fn main() {
|
||||
// Needed only on no_std
|
||||
//RegistryBuilder::register::<Tokens>();
|
||||
|
||||
let res = match App::new("libafl_qemu_fuzzbench")
|
||||
let res = match Command::new("libafl_qemu_fuzzbench")
|
||||
.version("0.4.0")
|
||||
.author("AFLplusplus team")
|
||||
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
||||
@ -113,7 +113,7 @@ pub fn main() {
|
||||
env::current_exe()
|
||||
.unwrap_or_else(|_| "fuzzer".into())
|
||||
.to_string_lossy(),
|
||||
err.info,
|
||||
err,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -253,20 +253,21 @@ fn fuzz(
|
||||
// Create an observation channel using cmplog map
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -279,13 +280,14 @@ fn fuzz(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
||||
#[global_allocator]
|
||||
static GLOBAL: MiMalloc = MiMalloc;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use content_inspector::inspect;
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
#[cfg(unix)]
|
||||
@ -31,7 +31,7 @@ use libafl::{
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, GeneralizedInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -70,7 +70,7 @@ pub fn libafl_main() {
|
||||
// Needed only on no_std
|
||||
//RegistryBuilder::register::<Tokens>();
|
||||
|
||||
let res = match App::new("libafl_fuzzbench")
|
||||
let res = match Command::new("libafl_fuzzbench")
|
||||
.version("0.7.1")
|
||||
.author("AFLplusplus team")
|
||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||
@ -119,7 +119,7 @@ pub fn libafl_main() {
|
||||
env::current_exe()
|
||||
.unwrap_or_else(|_| "fuzzer".into())
|
||||
.to_string_lossy(),
|
||||
err.info,
|
||||
err,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -321,20 +321,20 @@ fn fuzz_binary(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, true),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -347,9 +347,12 @@ fn fuzz_binary(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("Let's fuzz :)");
|
||||
@ -361,8 +364,6 @@ fn fuzz_binary(
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||
}
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
@ -531,20 +532,21 @@ fn fuzz_text(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
let mut map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, true);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, true),
|
||||
let mut feedback = feedback_or!(
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -557,9 +559,12 @@ fn fuzz_text(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("Let's fuzz :)");
|
||||
@ -571,8 +576,6 @@ fn fuzz_text(
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||
}
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
||||
#[global_allocator]
|
||||
static GLOBAL: MiMalloc = MiMalloc;
|
||||
|
||||
use clap::{App, Arg};
|
||||
use clap::{Arg, Command};
|
||||
use core::{cell::RefCell, time::Duration};
|
||||
#[cfg(unix)]
|
||||
use nix::{self, unistd::dup};
|
||||
@ -30,7 +30,7 @@ use libafl::{
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -64,7 +64,7 @@ pub fn libafl_main() {
|
||||
// Needed only on no_std
|
||||
//RegistryBuilder::register::<Tokens>();
|
||||
|
||||
let res = match App::new("libafl_fuzzbench")
|
||||
let res = match Command::new("libafl_fuzzbench")
|
||||
.version("0.7.1")
|
||||
.author("AFLplusplus team")
|
||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||
@ -113,7 +113,7 @@ pub fn libafl_main() {
|
||||
env::current_exe()
|
||||
.unwrap_or_else(|_| "fuzzer".into())
|
||||
.to_string_lossy(),
|
||||
err.info,
|
||||
err,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -260,20 +260,21 @@ fn fuzz(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -286,9 +287,12 @@ fn fuzz(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("Let's fuzz :)");
|
||||
@ -300,8 +304,6 @@ fn fuzz(
|
||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||
}
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
|
||||
// Setup a randomic Input2State stage
|
||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! This is the drop-in replacement for libfuzzer, to be used together with [`Atheris`](https://github.com/google/atheris)
|
||||
//! for python instrumentation and fuzzing.
|
||||
|
||||
use clap::{App, AppSettings, Arg};
|
||||
use clap::{AppSettings, Arg, Command};
|
||||
use core::{convert::TryInto, ffi::c_void, slice, time::Duration};
|
||||
use std::{
|
||||
env,
|
||||
@ -25,7 +25,7 @@ use libafl::{
|
||||
events::EventConfig,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandBytesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -124,7 +124,7 @@ pub fn LLVMFuzzerRunDriver(
|
||||
|
||||
println!("Args: {:?}", std::env::args());
|
||||
|
||||
let matches = App::new("libafl_atheris")
|
||||
let matches = Command::new("libafl_atheris")
|
||||
.version("0.1.0")
|
||||
.setting(AppSettings::AllowExternalSubcommands)
|
||||
.arg(Arg::new("script")) // The python script is the first arg
|
||||
@ -213,7 +213,7 @@ pub fn LLVMFuzzerRunDriver(
|
||||
|
||||
// TODO: we need to handle Atheris calls to `exit` on errors somhow.
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr, _core_id| {
|
||||
let mut run_client = |state: Option<_>, mut mgr, _core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
let edges_observer = unsafe {
|
||||
HitcountsMapObserver::new(StdMapObserver::new_from_ptr(
|
||||
@ -230,20 +230,17 @@ pub fn LLVMFuzzerRunDriver(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -256,9 +253,12 @@ pub fn LLVMFuzzerRunDriver(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(output_dir.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// Create a dictionary if not existing
|
||||
|
@ -17,7 +17,7 @@ use libafl::{
|
||||
events::{setup_restarting_mgr_std, EventConfig},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -86,24 +86,15 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// Create an observation channel using the allocations map
|
||||
let allocs_observer = StdMapObserver::new("allocs", unsafe { &mut libafl_alloc_map });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let edges_feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// The state of the cmps feedback.
|
||||
let cmps_feedback_state = MapFeedbackState::with_observer(&cmps_observer);
|
||||
|
||||
// The state of the allocs feedback.
|
||||
let allocs_feedback_state = MapFeedbackState::with_observer(&allocs_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = feedback_or!(
|
||||
MaxMapFeedback::new(&edges_feedback_state, &edges_observer),
|
||||
MaxMapFeedback::new(&cmps_feedback_state, &cmps_observer),
|
||||
MaxMapFeedback::new(&allocs_feedback_state, &allocs_observer)
|
||||
let mut feedback = feedback_or!(
|
||||
MaxMapFeedback::new(&edges_observer),
|
||||
MaxMapFeedback::new(&cmps_observer),
|
||||
MaxMapFeedback::new(&allocs_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -116,13 +107,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(
|
||||
edges_feedback_state,
|
||||
cmps_feedback_state,
|
||||
allocs_feedback_state
|
||||
),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -20,7 +20,7 @@ use libafl::{
|
||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -81,20 +81,21 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -107,9 +108,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
@ -129,7 +133,6 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
|
||||
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
@ -24,7 +24,7 @@ use libafl::{
|
||||
events::EventConfig,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -143,7 +143,7 @@ pub fn libafl_main() {
|
||||
|
||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
|
||||
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
|
||||
@ -151,20 +151,17 @@ pub fn libafl_main() {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -177,9 +174,12 @@ pub fn libafl_main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(&opt.output).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -24,7 +24,7 @@ use libafl::{
|
||||
events::EventConfig,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -141,7 +141,7 @@ pub fn libafl_main() {
|
||||
|
||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
|
||||
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
let edges = unsafe { edges_map_from_ptr() };
|
||||
let edges_observer =
|
||||
@ -150,20 +150,17 @@ pub fn libafl_main() {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -176,9 +173,12 @@ pub fn libafl_main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(opt.output.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -24,7 +24,7 @@ use libafl::{
|
||||
events::EventConfig,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::tui::TuiMonitor,
|
||||
@ -141,7 +141,7 @@ pub fn libafl_main() {
|
||||
|
||||
let monitor = TuiMonitor::new("Test fuzzer on libpng".into(), true);
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
|
||||
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
|
||||
@ -149,20 +149,17 @@ pub fn libafl_main() {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -175,9 +172,12 @@ pub fn libafl_main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(&opt.output).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -11,7 +11,7 @@ use libafl::{
|
||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{MapFeedbackState, MaxMapFeedback, ReachabilityFeedback},
|
||||
feedbacks::{MaxMapFeedback, ReachabilityFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -75,14 +75,11 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let reachability_observer =
|
||||
unsafe { StdMapObserver::new_from_ptr("png.c", __libafl_target_list, TARGET_SIZE) };
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &edges_observer);
|
||||
let mut feedback = MaxMapFeedback::new(&edges_observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = ReachabilityFeedback::new(&reachability_observer);
|
||||
let mut objective = ReachabilityFeedback::new(&reachability_observer);
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -95,9 +92,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -12,7 +12,7 @@ use libafl::{
|
||||
events::{setup_restarting_mgr_std, EventConfig},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -77,20 +77,17 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -103,9 +100,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -25,7 +25,7 @@ use libafl::{
|
||||
command::CommandConfigurator, inprocess::InProcessExecutor, ExitKind, ShadowExecutor,
|
||||
},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes, Input},
|
||||
monitors::MultiMonitor,
|
||||
@ -116,20 +116,18 @@ fn fuzz(
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -142,9 +140,11 @@ fn fuzz(
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
)
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
).unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
|
@ -7,7 +7,7 @@ use libafl::{
|
||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandPrintablesGenerator,
|
||||
monitors::SimpleMonitor,
|
||||
@ -41,14 +41,11 @@ fn input_generator() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -60,9 +57,12 @@ fn input_generator() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -12,7 +12,7 @@ use libafl::{
|
||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase},
|
||||
events::SimpleEventManager,
|
||||
executors::ExitKind,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||
fuzzer::StdFuzzer,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
@ -36,14 +36,11 @@ pub fn main() {
|
||||
// Create an observation channel using the signals map
|
||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
let feedback = MaxMapFeedback::<BytesInput, _, _, _>::new(&feedback_state, &observer);
|
||||
let mut feedback = MaxMapFeedback::<BytesInput, _, _, _>::new(&observer);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = CrashFeedback::new();
|
||||
let mut objective = CrashFeedback::new();
|
||||
|
||||
// create a State from scratch
|
||||
let mut state = StdState::new(
|
||||
@ -55,9 +52,12 @@ pub fn main() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
);
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||
|
@ -17,7 +17,7 @@ use libafl::{
|
||||
events::EventConfig,
|
||||
executors::{ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::MultiMonitor,
|
||||
@ -50,7 +50,7 @@ pub fn fuzz() {
|
||||
let broker_port = 1337;
|
||||
let cores = Cores::from_cmdline("0-11").unwrap();
|
||||
let corpus_dirs = [PathBuf::from("./corpus")];
|
||||
let objective_dir = PathBuf::from("./crashes");
|
||||
let mut objective_dir = PathBuf::from("./crashes");
|
||||
|
||||
// Initialize QEMU
|
||||
env::remove_var("LD_LIBRARY_PATH");
|
||||
@ -120,20 +120,17 @@ pub fn fuzz() {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -146,9 +143,12 @@ pub fn fuzz() {
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// A minimization+queue policy to get testcasess from the corpus
|
||||
|
@ -12,15 +12,15 @@ use libafl::{
|
||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::StdFuzzer,
|
||||
inputs::HasTargetBytes,
|
||||
monitors::MultiMonitor,
|
||||
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||
schedulers::{powersched::PowerSchedule, PowerQueueScheduler},
|
||||
stages::{calibrate::CalibrationStage, power::StdPowerMutationalStage},
|
||||
state::{HasCorpus, StdState},
|
||||
Error,
|
||||
Error, Fuzzer,
|
||||
};
|
||||
|
||||
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM};
|
||||
@ -88,21 +88,22 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||
|
||||
let calibration = CalibrationStage::new(&map_feedback);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
map_feedback,
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer),
|
||||
PacketLenFeedback::new()
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -115,9 +116,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
// The feedbacks can report the data that should persist in the State.
|
||||
&mut feedback,
|
||||
// Same for objective feedbacks
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
println!("We're a client, let's fuzz :)");
|
||||
@ -125,7 +129,6 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
||||
// Setup a lain mutator with a mutational stage
|
||||
let mutator = LainMutator::new();
|
||||
|
||||
let calibration = CalibrationStage::new(&edges_observer);
|
||||
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
||||
|
||||
let mut stages = tuple_list!(calibration, power);
|
||||
|
@ -45,6 +45,7 @@ impl<S> Feedback<PacketData, S> for PacketLenFeedback
|
||||
where
|
||||
S: HasClientPerfMonitor,
|
||||
{
|
||||
#[inline]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
@ -72,11 +73,6 @@ where
|
||||
.insert(PacketLenMetadata { length: self.len });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn discard_metadata(&mut self, _state: &mut S, _input: &PacketData) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for PacketLenFeedback {
|
||||
|
@ -13,13 +13,13 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
|
||||
|
||||
[features]
|
||||
default = ["std", "derive", "llmp_compression", "rand_trait", "fork"]
|
||||
std = ["serde_json", "serde_json/std", "hostname", "core_affinity", "nix", "serde/std", "bincode", "wait-timeout", "regex", "build_id", "uuid", "tui_monitor", "backtrace"] # print, env, launcher ... support
|
||||
std = ["serde_json", "serde_json/std", "hostname", "core_affinity", "nix", "serde/std", "bincode", "wait-timeout", "regex", "build_id", "uuid", "tui_monitor", "ctor", "backtrace"] # print, env, launcher ... support
|
||||
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
|
||||
fork = [] # uses the fork() syscall to spawn children, instead of launching a new command, if supported by the OS (has no effect on Windows, no_std).
|
||||
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
||||
introspection = [] # Include performance statistics of the fuzzing pipeline
|
||||
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
|
||||
python = ["pyo3"]
|
||||
#python = ["pyo3"]
|
||||
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
|
||||
cli = ["clap"] # expose bolts::cli
|
||||
qemu_cli = ["cli"]
|
||||
@ -59,13 +59,13 @@ erased-serde = { version = "0.3.12", default-features = false, features = ["allo
|
||||
postcard = { version = "0.7", features = ["alloc"] } # no_std compatible serde serialization fromat
|
||||
bincode = {version = "1.3", optional = true }
|
||||
static_assertions = "1.1.0"
|
||||
ctor = "0.1.20"
|
||||
num_enum = { version = "0.5.4", default-features = false }
|
||||
typed-builder = "0.9.1" # Implement the builder pattern at compiletime
|
||||
ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] } # The hash function already used in hashbrown
|
||||
intervaltree = { version = "0.2.7", default-features = false, features = ["serde"] }
|
||||
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
||||
|
||||
ctor = { optional = true, version = "0.1" }
|
||||
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
|
||||
miniz_oxide = { version = "0.4.4", optional = true}
|
||||
core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", rev = "6648a7a", optional = true }
|
||||
|
@ -103,7 +103,7 @@ macro_rules! create_serde_registry_for_trait {
|
||||
*REGISTRY
|
||||
.deserializers
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.expect("Empty types registry")
|
||||
.get(&id)
|
||||
.expect("Cannot deserialize an unregistered type")
|
||||
};
|
||||
@ -302,6 +302,15 @@ macro_rules! create_serde_registry_for_trait {
|
||||
map: HashMap<u64, HashMap<u64, Box<dyn $trait_name>>>,
|
||||
}
|
||||
|
||||
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
|
||||
// We unwrap postcard, it should not have a reason to fail.
|
||||
impl Clone for NamedSerdeAnyMap {
|
||||
fn clone(&self) -> Self {
|
||||
let serialized = postcard::to_allocvec(&self).unwrap();
|
||||
postcard::from_bytes(&serialized).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused_qualifications)]
|
||||
impl NamedSerdeAnyMap {
|
||||
/// Get an element by name
|
||||
@ -496,15 +505,18 @@ macro_rules! create_serde_registry_for_trait {
|
||||
/// Insert an element into this map.
|
||||
#[inline]
|
||||
#[allow(unused_qualifications)]
|
||||
pub fn insert(&mut self, val: Box<dyn $trait_name>, name: &str) {
|
||||
let id = unpack_type_id((*val).type_id());
|
||||
pub fn insert<T>(&mut self, val: T, name: &str)
|
||||
where
|
||||
T: $trait_name,
|
||||
{
|
||||
let id = unpack_type_id(TypeId::of::<T>());
|
||||
if !self.map.contains_key(&id) {
|
||||
self.map.insert(id, HashMap::default());
|
||||
}
|
||||
self.map
|
||||
.get_mut(&id)
|
||||
.unwrap()
|
||||
.insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), val);
|
||||
.insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), Box::new(val));
|
||||
}
|
||||
|
||||
/// Returns the `len` of this map.
|
||||
@ -590,41 +602,36 @@ macro_rules! create_serde_registry_for_trait {
|
||||
create_serde_registry_for_trait!(serdeany_registry, crate::bolts::serdeany::SerdeAny);
|
||||
pub use serdeany_registry::*;
|
||||
|
||||
/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`]
|
||||
/// Register a `SerdeAny` type in the [`RegistryBuilder`]
|
||||
#[cfg(feature = "std")]
|
||||
#[macro_export]
|
||||
macro_rules! impl_serdeany {
|
||||
($struct_name:ident) => {
|
||||
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
|
||||
fn as_any(&self) -> &dyn ::core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_boxed(
|
||||
self: ::std::boxed::Box<Self>,
|
||||
) -> ::std::boxed::Box<dyn ::core::any::Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
macro_rules! register_at_startup {
|
||||
($struct_type:ty) => {
|
||||
const _: () = {
|
||||
#[$crate::ctor]
|
||||
fn $struct_name() {
|
||||
$crate::bolts::serdeany::RegistryBuilder::register::<$struct_name>();
|
||||
fn constructor() {
|
||||
$crate::bolts::serdeany::RegistryBuilder::register::<$struct_type>();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/// Implement [`SerdeAny`] for a type
|
||||
/// Do nothing for `no_std`, you have to register it manually in `main()` with [`RegistryBuilder::register`]
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_export]
|
||||
macro_rules! register_at_startup {
|
||||
($struct_type:ty) => {};
|
||||
}
|
||||
|
||||
/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`] when on std
|
||||
#[macro_export]
|
||||
macro_rules! impl_serdeany {
|
||||
($struct_name:ident) => {
|
||||
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
|
||||
($struct_name:ident < $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ > $(, < $( $opt:tt ),+ >)*) =>
|
||||
{
|
||||
impl < $( $lt $( : $clt $(+ $dlt )* )? ),+ >
|
||||
$crate::bolts::serdeany::SerdeAny
|
||||
for $struct_name < $( $lt ),+ >
|
||||
{
|
||||
fn as_any(&self) -> &dyn ::core::any::Any {
|
||||
self
|
||||
}
|
||||
@ -634,10 +641,37 @@ macro_rules! impl_serdeany {
|
||||
}
|
||||
|
||||
fn as_any_boxed(
|
||||
self: ::alloc::boxed::Box<Self>,
|
||||
) -> ::alloc::boxed::Box<dyn ::core::any::Any> {
|
||||
self: $crate::alloc::boxed::Box<$struct_name < $( $lt ),+ >>,
|
||||
) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
$crate::register_at_startup!($struct_name < $( $opt ),+ >);
|
||||
)*
|
||||
};
|
||||
($struct_name:ident) =>
|
||||
{
|
||||
impl
|
||||
$crate::bolts::serdeany::SerdeAny
|
||||
for $struct_name
|
||||
{
|
||||
fn as_any(&self) -> &dyn ::core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_boxed(
|
||||
self: $crate::alloc::boxed::Box<$struct_name>,
|
||||
) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
$crate::register_at_startup!($struct_name);
|
||||
};
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use core::cell::RefCell;
|
||||
use crate::{inputs::Input, Error};
|
||||
|
||||
/// Corpus with all current testcases
|
||||
pub trait Corpus<I>: serde::Serialize + serde::de::DeserializeOwned
|
||||
pub trait Corpus<I>: serde::Serialize + for<'de> serde::Deserialize<'de>
|
||||
where
|
||||
I: Input,
|
||||
{
|
||||
|
@ -967,7 +967,7 @@ mod tests {
|
||||
|
||||
let solutions = InMemoryCorpus::<BytesInput>::new();
|
||||
|
||||
let mut state = StdState::new(rand, corpus, solutions, tuple_list!());
|
||||
let mut state = StdState::new(rand, corpus, solutions, &mut (), &mut ()).unwrap();
|
||||
|
||||
let mut shmem_provider = StdShMemProvider::new().unwrap();
|
||||
|
||||
|
@ -1682,10 +1682,10 @@ pub mod pybind {
|
||||
use pyo3::types::PyBytes;
|
||||
|
||||
macro_rules! define_python_in_process_executor {
|
||||
($struct_name:ident, $py_name:tt, $my_std_state_type_name: ident, $std_state_name: ident, $event_manager_name: ident, $map_observer_name: ident, $std_fuzzer_name: ident) => {
|
||||
($struct_name:ident, $py_name:tt, $my_std_state_type_name: ident, $std_state_name: ident, $event_manager_name: ident, $observer_name: ident, $std_fuzzer_name: ident) => {
|
||||
use crate::events::pybind::$event_manager_name;
|
||||
use crate::fuzzer::pybind::$std_fuzzer_name;
|
||||
use crate::observers::pybind::$map_observer_name;
|
||||
use crate::observers::map::pybind::$observer_name;
|
||||
use crate::state::pybind::{$my_std_state_type_name, $std_state_name};
|
||||
|
||||
#[pyclass(unsendable, name = $py_name)]
|
||||
@ -1695,7 +1695,7 @@ pub mod pybind {
|
||||
/// Rust wrapped OwnedInProcessExecutor object
|
||||
pub owned_in_process_executor: OwnedInProcessExecutor<
|
||||
BytesInput,
|
||||
($map_observer_name, ()),
|
||||
($observer_name, ()),
|
||||
$my_std_state_type_name,
|
||||
>,
|
||||
}
|
||||
@ -1705,7 +1705,7 @@ pub mod pybind {
|
||||
#[new]
|
||||
fn new(
|
||||
harness: PyObject,
|
||||
py_observer: $map_observer_name,
|
||||
py_observer: $observer_name,
|
||||
py_fuzzer: &mut $std_fuzzer_name,
|
||||
py_state: &mut $std_state_name,
|
||||
py_event_manager: &mut $event_manager_name,
|
||||
@ -1734,9 +1734,9 @@ pub mod pybind {
|
||||
}
|
||||
|
||||
define_python_in_process_executor!(
|
||||
PythonOwnedInProcessExecutorI8,
|
||||
"OwnedInProcessExecutorI8",
|
||||
MyStdStateI8,
|
||||
PythonOwnedInProcessExecutor,
|
||||
"OwnedInProcessExecutor",
|
||||
PythonStdState,
|
||||
PythonStdStateI8,
|
||||
PythonEventManagerI8,
|
||||
PythonMapObserverI8,
|
||||
|
@ -195,11 +195,11 @@ pub mod pybind {
|
||||
|
||||
macro_rules! define_python_executor {
|
||||
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident, $my_std_fuzzer_type_name: ident,
|
||||
$event_manager_name: ident, $in_process_executor_name: ident, $map_observer_name: ident) => {
|
||||
$event_manager_name: ident, $in_process_executor_name: ident, $observer_name: ident) => {
|
||||
use crate::events::pybind::$event_manager_name;
|
||||
use crate::executors::inprocess::pybind::$in_process_executor_name;
|
||||
use crate::fuzzer::pybind::$my_std_fuzzer_type_name;
|
||||
use crate::observers::map::pybind::$map_observer_name;
|
||||
use crate::observers::pybind::$observer_name;
|
||||
use crate::state::pybind::$my_std_state_type_name;
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -211,44 +211,37 @@ pub mod pybind {
|
||||
#[derive(Debug)]
|
||||
/// Executor + HasObservers Trait binding
|
||||
pub struct $struct_name_trait {
|
||||
executor: $wrapper_name,
|
||||
wrapper: $wrapper_name,
|
||||
}
|
||||
|
||||
impl $struct_name_trait {
|
||||
fn get_executor(
|
||||
fn unwrap(
|
||||
&self,
|
||||
) -> &(impl Executor<
|
||||
$event_manager_name,
|
||||
BytesInput,
|
||||
$my_std_state_type_name,
|
||||
$my_std_fuzzer_type_name,
|
||||
> + HasObservers<BytesInput, ($map_observer_name, ()), $my_std_state_type_name>)
|
||||
{
|
||||
> + HasObservers<BytesInput, ($observer_name, ()), $my_std_state_type_name>) {
|
||||
unsafe {
|
||||
match self.executor {
|
||||
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
|
||||
&(*py_owned_inprocess_executor).owned_in_process_executor
|
||||
}
|
||||
match self.wrapper {
|
||||
$wrapper_name::OwnedInProcess(py_wrapper) => &(*py_wrapper).upcast(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut_executor(
|
||||
fn unwrap_mut(
|
||||
&mut self,
|
||||
) -> &mut (impl Executor<
|
||||
$event_manager_name,
|
||||
BytesInput,
|
||||
$my_std_state_type_name,
|
||||
$my_std_fuzzer_type_name,
|
||||
> + HasObservers<
|
||||
BytesInput,
|
||||
($map_observer_name, ()),
|
||||
$my_std_state_type_name,
|
||||
>) {
|
||||
> + HasObservers<BytesInput, ($observer_name, ()), $my_std_state_type_name>) {
|
||||
unsafe {
|
||||
match self.executor {
|
||||
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
|
||||
&mut (*py_owned_inprocess_executor).owned_in_process_executor
|
||||
match self.wrapper {
|
||||
$wrapper_name::OwnedInProcess(py_wrapper) => {
|
||||
&mut (*py_wrapper).upcast_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,20 +255,20 @@ pub mod pybind {
|
||||
owned_inprocess_executor: &mut $in_process_executor_name,
|
||||
) -> Self {
|
||||
Self {
|
||||
executor: $wrapper_name::OwnedInProcess(owned_inprocess_executor),
|
||||
wrapper: $wrapper_name::OwnedInProcess(owned_inprocess_executor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, S> HasObservers<I, ($map_observer_name, ()), S> for $struct_name_trait {
|
||||
impl<I, S> HasObservers<I, ($observer_name, ()), S> for $struct_name_trait {
|
||||
// #[inline]
|
||||
fn observers(&self) -> &($map_observer_name, ()) {
|
||||
self.get_executor().observers()
|
||||
fn observers(&self) -> &($observer_name, ()) {
|
||||
self.unwrap().observers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn observers_mut(&mut self) -> &mut ($map_observer_name, ()) {
|
||||
self.get_mut_executor().observers_mut()
|
||||
fn observers_mut(&mut self) -> &mut ($observer_name, ()) {
|
||||
self.unwrap_mut().observers_mut()
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,112 +288,26 @@ pub mod pybind {
|
||||
mgr: &mut $event_manager_name,
|
||||
input: &BytesInput,
|
||||
) -> Result<ExitKind, Error> {
|
||||
self.get_mut_executor()
|
||||
.run_target(fuzzer, state, mgr, input)
|
||||
self.unwrap_mut().run_target(fuzzer, state, mgr, input)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorI8,
|
||||
"ExecutorI8",
|
||||
PythonExecutorWrapperI8,
|
||||
MyStdStateI8,
|
||||
MyStdFuzzerI8,
|
||||
PythonEventManagerI8,
|
||||
PythonOwnedInProcessExecutorI8,
|
||||
PythonMapObserverI8
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorI16,
|
||||
"ExecutorI16",
|
||||
PythonExecutorWrapperI16,
|
||||
MyStdStateI16,
|
||||
MyStdFuzzerI16,
|
||||
PythonEventManagerI16,
|
||||
PythonOwnedInProcessExecutorI16,
|
||||
PythonMapObserverI16
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorI32,
|
||||
"ExecutorI32",
|
||||
PythonExecutorWrapperI32,
|
||||
MyStdStateI32,
|
||||
MyStdFuzzerI32,
|
||||
PythonEventManagerI32,
|
||||
PythonOwnedInProcessExecutorI32,
|
||||
PythonMapObserverI32
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorI64,
|
||||
"ExecutorI64",
|
||||
PythonExecutorWrapperI64,
|
||||
MyStdStateI64,
|
||||
MyStdFuzzerI64,
|
||||
PythonEventManagerI64,
|
||||
PythonOwnedInProcessExecutorI64,
|
||||
PythonMapObserverI64
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorU8,
|
||||
"ExecutorU8",
|
||||
PythonExecutorWrapperU8,
|
||||
MyStdStateU8,
|
||||
MyStdFuzzerU8,
|
||||
PythonEventManagerU8,
|
||||
PythonOwnedInProcessExecutorU8,
|
||||
PythonMapObserverU8
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorU16,
|
||||
"ExecutorU16",
|
||||
PythonExecutorWrapperU16,
|
||||
MyStdStateU16,
|
||||
MyStdFuzzerU16,
|
||||
PythonEventManagerU16,
|
||||
PythonOwnedInProcessExecutorU16,
|
||||
PythonMapObserverU16
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorU32,
|
||||
"ExecutorU32",
|
||||
PythonExecutorWrapperU32,
|
||||
MyStdStateU32,
|
||||
MyStdFuzzerU32,
|
||||
PythonEventManagerU32,
|
||||
PythonOwnedInProcessExecutorU32,
|
||||
PythonMapObserverU32
|
||||
);
|
||||
|
||||
define_python_executor!(
|
||||
PythonExecutorU64,
|
||||
"ExecutorU64",
|
||||
PythonExecutorWrapperU64,
|
||||
MyStdStateU64,
|
||||
MyStdFuzzerU64,
|
||||
PythonEventManagerU64,
|
||||
PythonOwnedInProcessExecutorU64,
|
||||
PythonMapObserverU64
|
||||
PythonExecutor,
|
||||
"Executor",
|
||||
PythonExecutorWrapper,
|
||||
PythonStdState,
|
||||
PythonStdFuzzer,
|
||||
PythonEventManager,
|
||||
PythonOwnedInProcessExecutor,
|
||||
PythonObserver
|
||||
);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonExecutorI8>()?;
|
||||
m.add_class::<PythonExecutorI16>()?;
|
||||
m.add_class::<PythonExecutorI32>()?;
|
||||
m.add_class::<PythonExecutorI64>()?;
|
||||
|
||||
m.add_class::<PythonExecutorU8>()?;
|
||||
m.add_class::<PythonExecutorU16>()?;
|
||||
m.add_class::<PythonExecutorU32>()?;
|
||||
m.add_class::<PythonExecutorU64>()?;
|
||||
m.add_class::<PythonExecutor>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -7,24 +7,24 @@ use alloc::{
|
||||
use core::ops::{BitAnd, BitOr};
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
use num_traits::PrimInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
bolts::{
|
||||
tuples::{MatchName, Named},
|
||||
AsMutSlice, AsRefIterator, AsSlice, HasRefCnt,
|
||||
},
|
||||
bolts::{tuples::Named, AsMutSlice, AsRefIterator, AsSlice, HasRefCnt},
|
||||
corpus::Testcase,
|
||||
events::{Event, EventFirer},
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, FeedbackState},
|
||||
feedbacks::{Feedback, HasObserverName},
|
||||
inputs::Input,
|
||||
monitors::UserStats,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
state::{HasClientPerfMonitor, HasFeedbackStates, HasMetadata},
|
||||
state::{HasClientPerfMonitor, HasMetadata, HasNamedMetadata},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The prefix of the metadata names
|
||||
pub const MAPFEEDBACK_PREFIX: &str = "mapfeedback_metadata_";
|
||||
|
||||
/// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from ``HitcountsMapObserver``.
|
||||
pub type AflMapFeedback<I, O, S, T> = MapFeedback<I, DifferentIsNovel, O, OrReducer, S, T>;
|
||||
|
||||
@ -272,71 +272,44 @@ impl MapNoveltiesMetadata {
|
||||
}
|
||||
|
||||
/// The state of [`MapFeedback`]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||
pub struct MapFeedbackState<T>
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "T: DeserializeOwned")]
|
||||
pub struct MapFeedbackMetadata<T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize,
|
||||
{
|
||||
/// Contains information about untouched entries
|
||||
pub history_map: Vec<T>,
|
||||
/// Name identifier of this instance
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
impl<T> FeedbackState for MapFeedbackState<T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
{
|
||||
fn reset(&mut self) -> Result<(), Error> {
|
||||
self.history_map.iter_mut().for_each(|x| *x = T::default());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
crate::impl_serdeany!(
|
||||
MapFeedbackMetadata<T: Debug + Default + Copy + 'static + Serialize + DeserializeOwned>,
|
||||
<u8>,<u16>,<u32>,<u64>,<i8>,<i16>,<i32>,<i64>,<f32>,<f64>,<bool>,<char>
|
||||
);
|
||||
|
||||
impl<T> Named for MapFeedbackState<T>
|
||||
impl<T> MapFeedbackMetadata<T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
|
||||
T: Default + Copy + 'static + Serialize + DeserializeOwned,
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MapFeedbackState<T>
|
||||
where
|
||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
|
||||
{
|
||||
/// Create new `MapFeedbackState`
|
||||
/// Create new `MapFeedbackMetadata`
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
||||
pub fn new(map_size: usize) -> Self {
|
||||
Self {
|
||||
history_map: vec![T::default(); map_size],
|
||||
name: name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new `MapFeedbackState` for the observer type.
|
||||
pub fn with_observer<O>(map_observer: &O) -> Self
|
||||
where
|
||||
O: MapObserver<Entry = T>,
|
||||
T: PartialEq + Debug,
|
||||
{
|
||||
Self {
|
||||
history_map: vec![map_observer.initial(); map_observer.len()],
|
||||
name: map_observer.name().to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new `MapFeedbackState` using a name and a map.
|
||||
/// Create new `MapFeedbackMetadata` using a name and a map.
|
||||
/// The map can be shared.
|
||||
#[must_use]
|
||||
pub fn with_history_map(name: &'static str, history_map: Vec<T>) -> Self {
|
||||
Self {
|
||||
history_map,
|
||||
name: name.to_string(),
|
||||
pub fn with_history_map(history_map: Vec<T>) -> Self {
|
||||
Self { history_map }
|
||||
}
|
||||
|
||||
/// Reset the map
|
||||
pub fn reset(&mut self) -> Result<(), Error> {
|
||||
self.history_map.iter_mut().for_each(|x| *x = T::default());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -344,12 +317,12 @@ where
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<Entry = T>,
|
||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||
N: IsNovel<T>,
|
||||
S: HasFeedbackStates,
|
||||
S: HasNamedMetadata,
|
||||
{
|
||||
/// Indexes used in the last observation
|
||||
indexes: Option<Vec<usize>>,
|
||||
@ -365,14 +338,19 @@ where
|
||||
|
||||
impl<I, N, O, R, S, T> Feedback<I, S> for MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
R: Reducer<T>,
|
||||
O: MapObserver<Entry = T>,
|
||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||
N: IsNovel<T>,
|
||||
I: Input,
|
||||
S: HasFeedbackStates + HasClientPerfMonitor + Debug,
|
||||
S: HasNamedMetadata + HasClientPerfMonitor + Debug,
|
||||
{
|
||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||
state.add_named_metadata(MapFeedbackMetadata::<T>::default(), &self.name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
@ -393,11 +371,14 @@ where
|
||||
let initial = observer.initial();
|
||||
|
||||
let map_state = state
|
||||
.feedback_states_mut()
|
||||
.match_name_mut::<MapFeedbackState<T>>(&self.name)
|
||||
.named_metadata_mut()
|
||||
.get_mut::<MapFeedbackMetadata<T>>(&self.name)
|
||||
.unwrap();
|
||||
if map_state.history_map.len() < observer.len() {
|
||||
map_state.history_map.resize(observer.len(), T::default());
|
||||
}
|
||||
|
||||
assert!(size <= map_state.history_map.len(), "The size of the associated map observer cannot exceed the size of the history map of the feedback. If you are running multiple instances of slightly different fuzzers (e.g. one with ASan and another without) synchronized using LLMP please check the `configuration` field of the LLMP manager.");
|
||||
// assert!(size <= map_state.history_map.len(), "The size of the associated map observer cannot exceed the size of the history map of the feedback. If you are running multiple instances of slightly different fuzzers (e.g. one with ASan and another without) synchronized using LLMP please check the `configuration` field of the LLMP manager.");
|
||||
|
||||
assert!(size <= observer.len());
|
||||
|
||||
@ -471,12 +452,12 @@ where
|
||||
|
||||
impl<I, N, O, R, S, T> Named for MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
R: Reducer<T>,
|
||||
N: IsNovel<T>,
|
||||
O: MapObserver<Entry = T>,
|
||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||
S: HasFeedbackStates,
|
||||
S: HasNamedMetadata,
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
@ -484,22 +465,37 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, N, O, R, S, T> MapFeedback<I, N, O, R, S, T>
|
||||
impl<I, N, O, R, S, T> HasObserverName for MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
R: Reducer<T>,
|
||||
N: IsNovel<T>,
|
||||
O: MapObserver<Entry = T>,
|
||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||
S: HasFeedbackStates,
|
||||
S: HasNamedMetadata,
|
||||
{
|
||||
#[inline]
|
||||
fn observer_name(&self) -> &str {
|
||||
self.observer_name.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, N, O, R, S, T> MapFeedback<I, N, O, R, S, T>
|
||||
where
|
||||
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||
R: Reducer<T>,
|
||||
N: IsNovel<T>,
|
||||
O: MapObserver<Entry = T>,
|
||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||
S: HasNamedMetadata,
|
||||
{
|
||||
/// Create new `MapFeedback`
|
||||
#[must_use]
|
||||
pub fn new(feedback_state: &MapFeedbackState<T>, map_observer: &O) -> Self {
|
||||
pub fn new(map_observer: &O) -> Self {
|
||||
Self {
|
||||
indexes: None,
|
||||
novelties: None,
|
||||
name: feedback_state.name().to_string(),
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -507,16 +503,11 @@ where
|
||||
|
||||
/// Create new `MapFeedback` specifying if it must track indexes of used entries and/or novelties
|
||||
#[must_use]
|
||||
pub fn new_tracking(
|
||||
feedback_state: &MapFeedbackState<T>,
|
||||
map_observer: &O,
|
||||
track_indexes: bool,
|
||||
track_novelties: bool,
|
||||
) -> Self {
|
||||
pub fn new_tracking(map_observer: &O, track_indexes: bool, track_novelties: bool) -> Self {
|
||||
Self {
|
||||
indexes: if track_indexes { Some(vec![]) } else { None },
|
||||
novelties: if track_novelties { Some(vec![]) } else { None },
|
||||
name: feedback_state.name().to_string(),
|
||||
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||
observer_name: map_observer.name().to_string(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -673,10 +664,303 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
/// `MapFeedback` Python bindings
|
||||
#[cfg(feature = "python")]
|
||||
pub mod pybind {
|
||||
use crate::bolts::{tuples::Named, AsMutIterator, AsRefIterator, HasLen};
|
||||
use crate::observers::{map::OwnedMapObserver, MapObserver, Observer};
|
||||
use crate::Error;
|
||||
use pyo3::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::slice::{Iter, IterMut};
|
||||
|
||||
macro_rules! define_python_map_observer {
|
||||
($struct_name:ident, $py_name:tt, $struct_name_trait:ident, $py_name_trait:tt, $datatype:ty, $wrapper_name: ident) => {
|
||||
#[pyclass(unsendable, name = $py_name)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
||||
pub struct $struct_name {
|
||||
/// Rust wrapped OwnedMapObserver object
|
||||
pub inner: OwnedMapObserver<$datatype>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name {
|
||||
#[new]
|
||||
fn new(name: String, map: Vec<$datatype>) -> Self {
|
||||
Self {
|
||||
//TODO: Not leak memory
|
||||
inner: OwnedMapObserver::new(Box::leak(name.into_boxed_str()), map),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
enum $wrapper_name {
|
||||
Owned($struct_name),
|
||||
}
|
||||
|
||||
// Should not be exposed to user
|
||||
#[pyclass(unsendable, name = $py_name_trait)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
/// MapObserver + Observer Trait binding
|
||||
pub struct $struct_name_trait {
|
||||
pub wrapper: $wrapper_name,
|
||||
}
|
||||
|
||||
impl $struct_name_trait {
|
||||
fn unwrap(&self) -> &impl MapObserver<Entry = $datatype> {
|
||||
unsafe {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_mut(&mut self) -> &mut impl MapObserver<Entry = $datatype> {
|
||||
unsafe {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upcast<S>(&self) -> &impl Observer<BytesInput, S> {
|
||||
unsafe {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upcast_mut<S>(&mut self) -> &mut impl Observer<BytesInput, S> {
|
||||
unsafe {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name_trait {
|
||||
#[staticmethod]
|
||||
fn new_from_owned(owned_map: $struct_name) -> Self {
|
||||
Self {
|
||||
wrapper: $wrapper_name::Owned(owned_map),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it> AsRefIterator<'it> for $struct_name_trait {
|
||||
type Item = $datatype;
|
||||
type IntoIter = Iter<'it, $datatype>;
|
||||
|
||||
fn as_ref_iter(&'it self) -> Self::IntoIter {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_ref_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'it> AsMutIterator<'it> for $struct_name_trait {
|
||||
type Item = $datatype;
|
||||
type IntoIter = IterMut<'it, $datatype>;
|
||||
|
||||
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_mut_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MapObserver for $struct_name_trait {
|
||||
type Entry = $datatype;
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &$datatype {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner.get(idx),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.get_mut(idx),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn usable_count(&self) -> usize {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.wrapper.usable_count(),
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self) -> u64 {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.hash(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial(&self) -> $datatype {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_mut(&mut self) -> &mut $datatype {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_initial(&mut self, initial: $datatype) {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => {
|
||||
py_wrapper.inner.set_initial(initial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_vec(&self) -> Vec<$datatype> {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for $struct_name_trait {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HasLen for $struct_name_trait {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, S> Observer<I, S> for $struct_name_trait
|
||||
where
|
||||
Self: MapObserver,
|
||||
{
|
||||
#[inline]
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => {
|
||||
py_wrapper.inner.pre_exec(_state, _input)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverI8,
|
||||
"OwnedMapObserverI8",
|
||||
PythonMapObserverI8,
|
||||
"MapObserverI8",
|
||||
i8,
|
||||
PythonMapObserverWrapperI8
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverI16,
|
||||
"OwnedMapObserverI16",
|
||||
PythonMapObserverI16,
|
||||
"MapObserverI16",
|
||||
i16,
|
||||
PythonMapObserverWrapperI16
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverI32,
|
||||
"OwnedMapObserverI32",
|
||||
PythonMapObserverI32,
|
||||
"MapObserverI32",
|
||||
i32,
|
||||
PythonMapObserverWrapperI32
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverI64,
|
||||
"OwnedMapObserverI64",
|
||||
PythonMapObserverI64,
|
||||
"MapObserverI64",
|
||||
i64,
|
||||
PythonMapObserverWrapperI64
|
||||
);
|
||||
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverU8,
|
||||
"OwnedMapObserverU8",
|
||||
PythonMapObserverU8,
|
||||
"MapObserverU8",
|
||||
u8,
|
||||
PythonMapObserverWrapperU8
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverU16,
|
||||
"OwnedMapObserverU16",
|
||||
PythonMapObserverU16,
|
||||
"MapObserverU16",
|
||||
u16,
|
||||
PythonMapObserverWrapperU16
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverU32,
|
||||
"OwnedMapObserverU32",
|
||||
PythonMapObserverU32,
|
||||
"MapObserverU32",
|
||||
u32,
|
||||
PythonMapObserverWrapperU32
|
||||
);
|
||||
define_python_map_observer!(
|
||||
PythonOwnedMapObserverU64,
|
||||
"OwnedMapObserverU64",
|
||||
PythonMapObserverU64,
|
||||
"MapObserverU64",
|
||||
u64,
|
||||
PythonMapObserverWrapperU64
|
||||
);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonOwnedMapObserverI8>()?;
|
||||
m.add_class::<PythonMapObserverI8>()?;
|
||||
m.add_class::<PythonOwnedMapObserverI16>()?;
|
||||
m.add_class::<PythonMapObserverI16>()?;
|
||||
m.add_class::<PythonOwnedMapObserverI32>()?;
|
||||
m.add_class::<PythonMapObserverI32>()?;
|
||||
m.add_class::<PythonOwnedMapObserverI64>()?;
|
||||
m.add_class::<PythonMapObserverI64>()?;
|
||||
|
||||
m.add_class::<PythonOwnedMapObserverU8>()?;
|
||||
m.add_class::<PythonMapObserverU8>()?;
|
||||
m.add_class::<PythonOwnedMapObserverU16>()?;
|
||||
m.add_class::<PythonMapObserverU16>()?;
|
||||
m.add_class::<PythonOwnedMapObserverU32>()?;
|
||||
m.add_class::<PythonMapObserverU32>()?;
|
||||
m.add_class::<PythonOwnedMapObserverU64>()?;
|
||||
m.add_class::<PythonMapObserverU64>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
/// Map Feedback Python bindings
|
||||
pub mod pybind {
|
||||
use crate::feedbacks::map::{MapFeedbackState, MaxMapFeedback};
|
||||
use crate::feedbacks::map::{MapFeedbackMetadata, MaxMapFeedback};
|
||||
use crate::inputs::BytesInput;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
@ -688,10 +972,10 @@ pub mod pybind {
|
||||
|
||||
#[pyclass(unsendable, name = $map_feedback_state_py_name)]
|
||||
#[derive(Clone, Debug)]
|
||||
/// Python class for MapFeedbackState
|
||||
/// Python class for MapFeedbackMetadata
|
||||
pub struct $map_feedback_state_struct_name {
|
||||
/// Rust wrapped MapFeedbackState object
|
||||
pub map_feedback_state: MapFeedbackState<$datatype>,
|
||||
/// Rust wrapped MapFeedbackMetadata object
|
||||
pub map_feedback_state: MapFeedbackMetadata<$datatype>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@ -699,7 +983,7 @@ pub mod pybind {
|
||||
#[staticmethod]
|
||||
fn with_observer(py_observer: &$map_observer_name) -> Self {
|
||||
Self {
|
||||
map_feedback_state: MapFeedbackState::with_observer(py_observer),
|
||||
map_feedback_state: MapFeedbackMetadata::with_observer(py_observer),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -740,8 +1024,8 @@ pub mod pybind {
|
||||
}
|
||||
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateI8,
|
||||
"MapFeedbackStateI8",
|
||||
PythonMapFeedbackMetadataI8,
|
||||
"MapFeedbackMetadataI8",
|
||||
PythonMaxMapFeedbackI8,
|
||||
"MaxMapFeedbackI8",
|
||||
i8,
|
||||
@ -750,8 +1034,8 @@ pub mod pybind {
|
||||
);
|
||||
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateI16,
|
||||
"MapFeedbackStateI16",
|
||||
PythonMapFeedbackMetadataI16,
|
||||
"MapFeedbackMetadataI16",
|
||||
PythonMaxMapFeedbackI16,
|
||||
"MaxMapFeedbackI16",
|
||||
i16,
|
||||
@ -759,8 +1043,8 @@ pub mod pybind {
|
||||
MyStdStateI16
|
||||
);
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateI32,
|
||||
"MapFeedbackStateI32",
|
||||
PythonMapFeedbackMetadataI32,
|
||||
"MapFeedbackMetadataI32",
|
||||
PythonMaxMapFeedbackI32,
|
||||
"MaxMapFeedbackI32",
|
||||
i32,
|
||||
@ -768,8 +1052,8 @@ pub mod pybind {
|
||||
MyStdStateI32
|
||||
);
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateI64,
|
||||
"MapFeedbackStateI64",
|
||||
PythonMapFeedbackMetadataI64,
|
||||
"MapFeedbackMetadataI64",
|
||||
PythonMaxMapFeedbackI64,
|
||||
"MaxMapFeedbackI64",
|
||||
i64,
|
||||
@ -778,8 +1062,8 @@ pub mod pybind {
|
||||
);
|
||||
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateU8,
|
||||
"MapFeedbackStateU8",
|
||||
PythonMapFeedbackMetadataU8,
|
||||
"MapFeedbackMetadataU8",
|
||||
PythonMaxMapFeedbackU8,
|
||||
"MaxMapFeedbackU8",
|
||||
u8,
|
||||
@ -788,8 +1072,8 @@ pub mod pybind {
|
||||
);
|
||||
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateU16,
|
||||
"MapFeedbackStateU16",
|
||||
PythonMapFeedbackMetadataU16,
|
||||
"MapFeedbackMetadataU16",
|
||||
PythonMaxMapFeedbackU16,
|
||||
"MaxMapFeedbackU16",
|
||||
u16,
|
||||
@ -797,8 +1081,8 @@ pub mod pybind {
|
||||
MyStdStateU16
|
||||
);
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateU32,
|
||||
"MapFeedbackStateU32",
|
||||
PythonMapFeedbackMetadataU32,
|
||||
"MapFeedbackMetadataU32",
|
||||
PythonMaxMapFeedbackU32,
|
||||
"MaxMapFeedbackU32",
|
||||
u32,
|
||||
@ -806,8 +1090,8 @@ pub mod pybind {
|
||||
MyStdStateU32
|
||||
);
|
||||
define_python_map_feedback!(
|
||||
PythonMapFeedbackStateU64,
|
||||
"MapFeedbackStateU64",
|
||||
PythonMapFeedbackMetadataU64,
|
||||
"MapFeedbackMetadataU64",
|
||||
PythonMaxMapFeedbackU64,
|
||||
"MaxMapFeedbackU64",
|
||||
u64,
|
||||
@ -817,15 +1101,15 @@ pub mod pybind {
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonMapFeedbackStateI8>()?;
|
||||
m.add_class::<PythonMapFeedbackStateI16>()?;
|
||||
m.add_class::<PythonMapFeedbackStateI32>()?;
|
||||
m.add_class::<PythonMapFeedbackStateI64>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataI8>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataI16>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataI32>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataI64>()?;
|
||||
|
||||
m.add_class::<PythonMapFeedbackStateU8>()?;
|
||||
m.add_class::<PythonMapFeedbackStateU16>()?;
|
||||
m.add_class::<PythonMapFeedbackStateU32>()?;
|
||||
m.add_class::<PythonMapFeedbackStateU64>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataU8>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataU16>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataU32>()?;
|
||||
m.add_class::<PythonMapFeedbackMetadataU64>()?;
|
||||
|
||||
m.add_class::<PythonMaxMapFeedbackI8>()?;
|
||||
m.add_class::<PythonMaxMapFeedbackI16>()?;
|
||||
|
@ -16,7 +16,7 @@ pub mod new_hash_feedback;
|
||||
#[cfg(feature = "std")]
|
||||
pub use new_hash_feedback::NewHashFeedback;
|
||||
#[cfg(feature = "std")]
|
||||
pub use new_hash_feedback::NewHashFeedbackState;
|
||||
pub use new_hash_feedback::NewHashFeedbackMetadata;
|
||||
|
||||
#[cfg(feature = "nautilus")]
|
||||
pub mod nautilus;
|
||||
@ -27,7 +27,7 @@ use alloc::string::{String, ToString};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
bolts::tuples::{MatchName, Named},
|
||||
bolts::tuples::Named,
|
||||
corpus::Testcase,
|
||||
events::EventFirer,
|
||||
executors::ExitKind,
|
||||
@ -51,6 +51,12 @@ where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor,
|
||||
{
|
||||
/// Initializes the feedback state.
|
||||
/// This method is called after that the `State` is created.
|
||||
fn init_state(&mut self, _state: &mut S) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `is_interesting ` return if an input is worth the addition to the corpus
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
@ -116,36 +122,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// [`FeedbackState`] is the data associated with a [`Feedback`] that must persist as part
|
||||
/// of the fuzzer State
|
||||
pub trait FeedbackState: Named + Serialize + serde::de::DeserializeOwned + Debug {
|
||||
/// Reset the internal state
|
||||
fn reset(&mut self) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A haskell-style tuple of feedback states
|
||||
pub trait FeedbackStatesTuple: MatchName + Serialize + serde::de::DeserializeOwned + Debug {
|
||||
/// Resets all the feedback states of the tuple
|
||||
fn reset_all(&mut self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
impl FeedbackStatesTuple for () {
|
||||
fn reset_all(&mut self) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<Head, Tail> FeedbackStatesTuple for (Head, Tail)
|
||||
where
|
||||
Head: FeedbackState,
|
||||
Tail: FeedbackStatesTuple,
|
||||
{
|
||||
fn reset_all(&mut self) -> Result<(), Error> {
|
||||
self.0.reset()?;
|
||||
self.1.reset_all()
|
||||
}
|
||||
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
|
||||
pub trait HasObserverName {
|
||||
/// The name associated with the observer
|
||||
fn observer_name(&self) -> &str;
|
||||
}
|
||||
|
||||
/// A combined feedback consisting of multiple [`Feedback`]s
|
||||
@ -207,6 +187,12 @@ where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor + Debug,
|
||||
{
|
||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||
self.first.init_state(state)?;
|
||||
self.second.init_state(state)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
@ -596,6 +582,10 @@ where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor,
|
||||
{
|
||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||
self.first.init_state(state)
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
@ -984,3 +974,177 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The [`ConstFeedback`] reports the same value, always.
|
||||
/// It can be used to enable or disable feedback results through composition.
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ConstFeedback {
|
||||
/// Always returns `true`
|
||||
True,
|
||||
/// Alsways returns `false`
|
||||
False,
|
||||
}
|
||||
|
||||
impl<I, S> Feedback<I, S> for ConstFeedback
|
||||
where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor,
|
||||
{
|
||||
#[inline]
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_input: &I,
|
||||
_observers: &OT,
|
||||
_exit_kind: &ExitKind,
|
||||
) -> Result<bool, Error>
|
||||
where
|
||||
EM: EventFirer<I>,
|
||||
OT: ObserversTuple<I, S>,
|
||||
{
|
||||
Ok(match self {
|
||||
ConstFeedback::True => true,
|
||||
ConstFeedback::False => false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for ConstFeedback {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
"ConstFeedback"
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstFeedback {
|
||||
/// Creates a new [`ConstFeedback`] from the given boolean
|
||||
#[must_use]
|
||||
pub fn new(val: bool) -> Self {
|
||||
Self::from(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for ConstFeedback {
|
||||
fn from(val: bool) -> Self {
|
||||
if val {
|
||||
Self::True
|
||||
} else {
|
||||
Self::False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `Feedback` Python bindings
|
||||
#[cfg(feature = "python")]
|
||||
pub mod pybind {
|
||||
use crate::inputs::BytesInput;
|
||||
use crate::{
|
||||
bolts::tuples::Named, corpus::Testcase, events::EventFirer, executors::ExitKind,
|
||||
feedbacks::Feedback, observers::ObserversTuple, Error,
|
||||
};
|
||||
use pyo3::prelude::*;
|
||||
|
||||
macro_rules! define_python_feedback {
|
||||
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident) => {
|
||||
use crate::observers::map::pybind::PythonMaxMapFeedbackI8;
|
||||
use crate::state::pybind::$my_std_state_type_name;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum $wrapper_name {
|
||||
MaxMapI8(*mut PythonMaxMapFeedbackI8),
|
||||
}
|
||||
|
||||
#[pyclass(unsendable, name = $py_name_trait)]
|
||||
#[derive(Debug)]
|
||||
/// Observer Trait binding
|
||||
pub struct $struct_name_trait {
|
||||
pub wrapper: $wrapper_name,
|
||||
}
|
||||
|
||||
impl $struct_name_trait {
|
||||
fn unwrap(&self) -> &impl Feedback<BytesInput, $my_std_state_type_name> {
|
||||
unsafe {
|
||||
match self.wrapper {
|
||||
$wrapper_name::MaxMapI8(py_wrapper) => &(*py_wrapper).upcast(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_mut(
|
||||
&mut self,
|
||||
) -> &mut impl Feedback<BytesInput, $my_std_state_type_name> {
|
||||
unsafe {
|
||||
match self.wrapper {
|
||||
$wrapper_name::MaxMapI8(py_wrapper) => &mut (*py_wrapper).upcast_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name_trait {
|
||||
#[staticmethod]
|
||||
fn new_map(map_feedback: &mut PythonMaxMapFeedbackI8) -> Self {
|
||||
Self {
|
||||
observer: $wrapper_name::MaxMapI8(map_feedback),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for $struct_name_trait {
|
||||
fn name(&self) -> &str {
|
||||
self.unwrap().name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Feedback<BytesInput, $my_std_state_type_name> for $struct_name_trait {
|
||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||
self.unwrap_mut().init_state(state)
|
||||
}
|
||||
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
input: &I,
|
||||
observers: &OT,
|
||||
exit_kind: &ExitKind,
|
||||
) -> Result<bool, Error>
|
||||
where
|
||||
EM: EventFirer<I>,
|
||||
OT: ObserversTuple<I, S>,
|
||||
{
|
||||
self.unwrap_mut()
|
||||
.is_interesting(state, manager, input, observers, exit_kind)
|
||||
}
|
||||
|
||||
fn append_metadata(
|
||||
&mut self,
|
||||
state: &mut S,
|
||||
testcase: &mut Testcase<I>,
|
||||
) -> Result<(), Error> {
|
||||
self.unwrap_mut().append_metadata(state, testcase)
|
||||
}
|
||||
|
||||
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
|
||||
self.unwrap_mut().discard_metadata(state, input)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_python_feedback!(
|
||||
PythonFeedback,
|
||||
"Feedback",
|
||||
PythonFeedbackWrapper,
|
||||
PythonStdState,
|
||||
);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonFeedback>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,98 +1,64 @@
|
||||
//! The ``NewHashFeedback`` uses the backtrace hash and a hashset to only keep novel cases
|
||||
|
||||
use std::{fmt::Debug, hash::Hash, marker::PhantomData};
|
||||
use std::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use num_traits::PrimInt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
bolts::tuples::{MatchName, Named},
|
||||
bolts::tuples::Named,
|
||||
events::EventFirer,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, FeedbackState},
|
||||
feedbacks::{Feedback, HasObserverName},
|
||||
inputs::Input,
|
||||
observers::{ObserverWithHashField, ObserversTuple},
|
||||
state::{HasClientPerfMonitor, HasFeedbackStates},
|
||||
state::{HasClientPerfMonitor, HasNamedMetadata},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The prefix of the metadata names
|
||||
pub const NEWHASHFEEDBACK_PREFIX: &str = "newhashfeedback_metadata_";
|
||||
|
||||
/// A state that implements this trait has a hash set
|
||||
pub trait HashSetState<T> {
|
||||
/// creates a new instance with a specific hashset
|
||||
fn with_hash_set(name: &'static str, hash_set: HashSet<T>) -> Self;
|
||||
fn with_hash_set(hash_set: HashSet<T>) -> Self;
|
||||
/// updates the `hash_set` with the given value
|
||||
fn update_hash_set(&mut self, value: T) -> Result<bool, Error>;
|
||||
}
|
||||
|
||||
/// The state of [`NewHashFeedback`]
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
||||
pub struct NewHashFeedbackState<T>
|
||||
where
|
||||
T: PrimInt + Default + Copy + 'static + Serialize + Hash + Debug,
|
||||
{
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NewHashFeedbackMetadata {
|
||||
/// Contains information about untouched entries
|
||||
pub hash_set: HashSet<T>,
|
||||
/// Name identifier of this instance
|
||||
pub name: String,
|
||||
pub hash_set: HashSet<u64>,
|
||||
}
|
||||
|
||||
impl<T> FeedbackState for NewHashFeedbackState<T>
|
||||
where
|
||||
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
|
||||
{
|
||||
fn reset(&mut self) -> Result<(), Error> {
|
||||
#[rustfmt::skip]
|
||||
crate::impl_serdeany!(NewHashFeedbackMetadata);
|
||||
|
||||
impl NewHashFeedbackMetadata {
|
||||
/// Create a new [`NewHashFeedbackMetadata`]
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Reset the internal state
|
||||
pub fn reset(&mut self) -> Result<(), Error> {
|
||||
self.hash_set.clear();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Named for NewHashFeedbackState<T>
|
||||
where
|
||||
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
|
||||
{
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> NewHashFeedbackState<T>
|
||||
where
|
||||
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
|
||||
{
|
||||
/// Create a new [`NewHashFeedbackState`]
|
||||
impl HashSetState<u64> for NewHashFeedbackMetadata {
|
||||
/// Create new [`NewHashFeedbackMetadata`] using a name and a hash set.
|
||||
#[must_use]
|
||||
pub fn new(name: &'static str) -> Self {
|
||||
Self {
|
||||
hash_set: HashSet::<T>::new(),
|
||||
name: name.to_string(),
|
||||
}
|
||||
fn with_hash_set(hash_set: HashSet<u64>) -> Self {
|
||||
Self { hash_set }
|
||||
}
|
||||
|
||||
/// Create a new [`NewHashFeedbackState`] for an observer that implements [`ObserverWithHashField`]
|
||||
pub fn with_observer(backtrace_observer: &(impl ObserverWithHashField + Named)) -> Self {
|
||||
Self {
|
||||
hash_set: HashSet::<T>::new(),
|
||||
name: backtrace_observer.name().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<T> HashSetState<T> for NewHashFeedbackState<T>
|
||||
where
|
||||
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
|
||||
{
|
||||
/// Create new [`NewHashFeedbackState`] using a name and a hash set.
|
||||
#[must_use]
|
||||
fn with_hash_set(name: &'static str, hash_set: HashSet<T>) -> Self {
|
||||
Self {
|
||||
hash_set,
|
||||
name: name.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn update_hash_set(&mut self, value: T) -> Result<bool, Error> {
|
||||
fn update_hash_set(&mut self, value: u64) -> Result<bool, Error> {
|
||||
let r = self.hash_set.insert(value);
|
||||
// println!("Got r={}, the hashset is {:?}", r, &self.hash_set);
|
||||
Ok(r)
|
||||
@ -102,7 +68,7 @@ where
|
||||
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct NewHashFeedback<O> {
|
||||
feedback_name: String,
|
||||
name: String,
|
||||
observer_name: String,
|
||||
o_type: PhantomData<O>,
|
||||
}
|
||||
@ -110,13 +76,18 @@ pub struct NewHashFeedback<O> {
|
||||
impl<I, S, O> Feedback<I, S> for NewHashFeedback<O>
|
||||
where
|
||||
I: Input,
|
||||
S: HasClientPerfMonitor + HasFeedbackStates,
|
||||
S: HasClientPerfMonitor + HasNamedMetadata,
|
||||
O: ObserverWithHashField + Named + Debug,
|
||||
{
|
||||
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||
state.add_named_metadata(NewHashFeedbackMetadata::default(), &self.name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
fn is_interesting<EM, OT>(
|
||||
&mut self,
|
||||
_state: &mut S,
|
||||
state: &mut S,
|
||||
_manager: &mut EM,
|
||||
_input: &I,
|
||||
observers: &OT,
|
||||
@ -130,9 +101,9 @@ where
|
||||
.match_name::<O>(&self.observer_name)
|
||||
.expect("A NewHashFeedback needs a BacktraceObserver");
|
||||
|
||||
let backtrace_state = _state
|
||||
.feedback_states_mut()
|
||||
.match_name_mut::<NewHashFeedbackState<u64>>(&self.observer_name)
|
||||
let backtrace_state = state
|
||||
.named_metadata_mut()
|
||||
.get_mut::<NewHashFeedbackMetadata>(&self.name)
|
||||
.unwrap();
|
||||
|
||||
match observer.hash() {
|
||||
@ -153,7 +124,14 @@ where
|
||||
impl<O> Named for NewHashFeedback<O> {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
&self.feedback_name
|
||||
&self.name
|
||||
}
|
||||
}
|
||||
|
||||
impl<O> HasObserverName for NewHashFeedback<O> {
|
||||
#[inline]
|
||||
fn observer_name(&self) -> &str {
|
||||
&self.observer_name
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,12 +139,12 @@ impl<O> NewHashFeedback<O>
|
||||
where
|
||||
O: ObserverWithHashField + Named + Debug,
|
||||
{
|
||||
/// Returns a new [`NewHashFeedback`]. Carefull, it's recommended to use `new_with_observer`
|
||||
/// Returns a new [`NewHashFeedback`].
|
||||
/// Setting an observer name that doesn't exist would eventually trigger a panic.
|
||||
#[must_use]
|
||||
pub fn new(feedback_name: &str, observer_name: &str) -> Self {
|
||||
pub fn with_names(name: &str, observer_name: &str) -> Self {
|
||||
Self {
|
||||
feedback_name: feedback_name.to_string(),
|
||||
name: name.to_string(),
|
||||
observer_name: observer_name.to_string(),
|
||||
o_type: PhantomData,
|
||||
}
|
||||
@ -174,9 +152,9 @@ where
|
||||
|
||||
/// Returns a new [`NewHashFeedback`].
|
||||
#[must_use]
|
||||
pub fn new_with_observer(feedback_name: &str, observer: &O) -> Self {
|
||||
pub fn new(observer: &O) -> Self {
|
||||
Self {
|
||||
feedback_name: feedback_name.to_string(),
|
||||
name: NEWHASHFEEDBACK_PREFIX.to_string() + observer.name(),
|
||||
observer_name: observer.name().to_string(),
|
||||
o_type: PhantomData,
|
||||
}
|
||||
|
188
libafl/src/feedbacks/owned.rs
Normal file
188
libafl/src/feedbacks/owned.rs
Normal file
@ -0,0 +1,188 @@
|
||||
//! A dynamic collection of owned FeedbackStates
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
use crate::{
|
||||
bolts::anymap::AsAny,
|
||||
feedbacks::{FeedbackState, FeedbackStateTuple},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Combine `FeedbackState` and `AsAny`
|
||||
pub trait AnyFeedbackState: FeedbackState + AsAny {}
|
||||
|
||||
/// An owned list of `FeedbackState` trait objects
|
||||
#[derive(Default)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct FeedbackStatesOwnedList {
|
||||
/// The named trait objects map
|
||||
pub list: Vec<Box<dyn AnyFeedbackState>>,
|
||||
}
|
||||
|
||||
impl FeedbackStatesTuple for FeedbackStatesOwnedList {
|
||||
fn perform_all(
|
||||
&mut self,
|
||||
fuzzer: &mut Z,
|
||||
executor: &mut E,
|
||||
state: &mut S,
|
||||
manager: &mut EM,
|
||||
corpus_idx: usize,
|
||||
) -> Result<(), Error> {
|
||||
for s in &mut self.list {
|
||||
s.perform(fuzzer, executor, state, manager, corpus_idx)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl FeedbackStatesOwnedList {
|
||||
/// Create a new instance
|
||||
#[must_use]
|
||||
pub fn new(list: Vec<Box<dyn AnyFeedbackState>>) -> Self {
|
||||
Self { list }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "python")]
|
||||
/// `FeedbackStatesOwnedList` Python bindings
|
||||
pub mod pybind {
|
||||
use crate::stages::owned::FeedbackStatesOwnedList;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
macro_rules! define_python_stage_owned_list {
|
||||
($struct_name:ident, $py_name:tt, $my_std_state_type_name: ident, $my_std_fuzzer_type_name: ident, $event_manager_name: ident,
|
||||
$executor_name: ident, $stage_name: ident) => {
|
||||
use crate::events::pybind::$event_manager_name;
|
||||
use crate::executors::pybind::$executor_name;
|
||||
use crate::fuzzer::pybind::$my_std_fuzzer_type_name;
|
||||
use crate::stages::pybind::$stage_name;
|
||||
use crate::state::pybind::$my_std_state_type_name;
|
||||
#[pyclass(unsendable, name = $py_name)]
|
||||
|
||||
/// Python class for FeedbackStatesOwnedList
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub struct $struct_name {
|
||||
/// Rust wrapped FeedbackStatesOwnedList object
|
||||
pub stages_owned_list: FeedbackStatesOwnedList<
|
||||
$executor_name,
|
||||
$event_manager_name,
|
||||
$my_std_state_type_name,
|
||||
$my_std_fuzzer_type_name,
|
||||
>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name {
|
||||
//TODO: Add new from list
|
||||
#[new]
|
||||
fn new(stage: &$stage_name) -> Self {
|
||||
// TODO: Be safe
|
||||
unsafe {
|
||||
Self {
|
||||
stages_owned_list: FeedbackStatesOwnedList {
|
||||
list: vec![Box::new(std::mem::transmute_copy::<
|
||||
$stage_name,
|
||||
$stage_name,
|
||||
>(stage))],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListI8,
|
||||
"FeedbackStatesOwnedListI8",
|
||||
MyStdStateI8,
|
||||
MyStdFuzzerI8,
|
||||
PythonEventManagerI8,
|
||||
PythonExecutorI8,
|
||||
PythonFeedbackStateI8
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListI16,
|
||||
"FeedbackStatesOwnedListI16",
|
||||
MyStdStateI16,
|
||||
MyStdFuzzerI16,
|
||||
PythonEventManagerI16,
|
||||
PythonExecutorI16,
|
||||
PythonFeedbackStateI16
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListI32,
|
||||
"FeedbackStatesOwnedListI32",
|
||||
MyStdStateI32,
|
||||
MyStdFuzzerI32,
|
||||
PythonEventManagerI32,
|
||||
PythonExecutorI32,
|
||||
PythonFeedbackStateI32
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListI64,
|
||||
"FeedbackStatesOwnedListI64",
|
||||
MyStdStateI64,
|
||||
MyStdFuzzerI64,
|
||||
PythonEventManagerI64,
|
||||
PythonExecutorI64,
|
||||
PythonFeedbackStateI64
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListU8,
|
||||
"FeedbackStatesOwnedListU8",
|
||||
MyStdStateU8,
|
||||
MyStdFuzzerU8,
|
||||
PythonEventManagerU8,
|
||||
PythonExecutorU8,
|
||||
PythonFeedbackStateU8
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListU16,
|
||||
"FeedbackStatesOwnedListU16",
|
||||
MyStdStateU16,
|
||||
MyStdFuzzerU16,
|
||||
PythonEventManagerU16,
|
||||
PythonExecutorU16,
|
||||
PythonFeedbackStateU16
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListU32,
|
||||
"FeedbackStatesOwnedListU32",
|
||||
MyStdStateU32,
|
||||
MyStdFuzzerU32,
|
||||
PythonEventManagerU32,
|
||||
PythonExecutorU32,
|
||||
PythonFeedbackStateU32
|
||||
);
|
||||
|
||||
define_python_stage_owned_list!(
|
||||
PythonFeedbackStatesOwnedListU64,
|
||||
"FeedbackStatesOwnedListU64",
|
||||
MyStdStateU64,
|
||||
MyStdFuzzerU64,
|
||||
PythonEventManagerU64,
|
||||
PythonExecutorU64,
|
||||
PythonFeedbackStateU64
|
||||
);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonFeedbackStatesOwnedListI8>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListI16>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListI32>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListI64>()?;
|
||||
|
||||
m.add_class::<PythonFeedbackStatesOwnedListU8>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListU16>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListU32>()?;
|
||||
m.add_class::<PythonFeedbackStatesOwnedListU64>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -70,10 +70,10 @@ Welcome to `LibAFL`
|
||||
)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
pub extern crate alloc;
|
||||
#[macro_use]
|
||||
extern crate static_assertions;
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "ctor")]
|
||||
pub use ctor::ctor;
|
||||
|
||||
// Re-export derive(SerdeAny)
|
||||
@ -407,8 +407,10 @@ mod tests {
|
||||
rand,
|
||||
corpus,
|
||||
InMemoryCorpus::<BytesInput>::new(),
|
||||
tuple_list!(),
|
||||
);
|
||||
&mut (),
|
||||
&mut (),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let monitor = SimpleMonitor::new(|s| {
|
||||
println!("{}", s);
|
||||
@ -440,7 +442,6 @@ mod tests {
|
||||
let state_serialized = postcard::to_allocvec(&state).unwrap();
|
||||
let state_deserialized: StdState<
|
||||
InMemoryCorpus<BytesInput>,
|
||||
(),
|
||||
BytesInput,
|
||||
StdRand,
|
||||
InMemoryCorpus<BytesInput>,
|
||||
|
@ -1230,7 +1230,8 @@ mod tests {
|
||||
.add(BytesInput::new(vec![0x42; 0x1337]).into())
|
||||
.unwrap();
|
||||
|
||||
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
|
||||
let mut state =
|
||||
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
|
||||
|
||||
let mut mutations = test_mutations();
|
||||
for _ in 0..2 {
|
||||
|
@ -447,7 +447,8 @@ mod tests {
|
||||
let testcase = corpus.get(0).expect("Corpus did not contain entries");
|
||||
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
||||
|
||||
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
|
||||
let mut state =
|
||||
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
|
||||
|
||||
rand.set_seed(5);
|
||||
|
||||
@ -474,7 +475,8 @@ mod tests {
|
||||
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
||||
let input_prior = input.clone();
|
||||
|
||||
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
|
||||
let mut state =
|
||||
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
|
||||
|
||||
let mut havoc = StdScheduledMutator::new(havoc_mutations());
|
||||
|
||||
|
@ -1487,6 +1487,7 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// `MapObserver` Python bindings
|
||||
#[cfg(feature = "python")]
|
||||
pub mod pybind {
|
||||
@ -1504,7 +1505,7 @@ pub mod pybind {
|
||||
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
||||
pub struct $struct_name {
|
||||
/// Rust wrapped OwnedMapObserver object
|
||||
pub owned_map_observer: OwnedMapObserver<$datatype>,
|
||||
pub inner: OwnedMapObserver<$datatype>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
@ -1513,10 +1514,7 @@ pub mod pybind {
|
||||
fn new(name: String, map: Vec<$datatype>) -> Self {
|
||||
Self {
|
||||
//TODO: Not leak memory
|
||||
owned_map_observer: OwnedMapObserver::new(
|
||||
Box::leak(name.into_boxed_str()),
|
||||
map,
|
||||
),
|
||||
inner: OwnedMapObserver::new(Box::leak(name.into_boxed_str()), map),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1531,15 +1529,49 @@ pub mod pybind {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
/// MapObserver + Observer Trait binding
|
||||
pub struct $struct_name_trait {
|
||||
map_observer: $wrapper_name,
|
||||
pub wrapper: $wrapper_name,
|
||||
}
|
||||
|
||||
impl $struct_name_trait {
|
||||
fn unwrap(&self) -> &impl MapObserver<Entry = $datatype> {
|
||||
unsafe {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_mut(&mut self) -> &mut impl MapObserver<Entry = $datatype> {
|
||||
unsafe {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upcast<S>(&self) -> &impl Observer<BytesInput, S> {
|
||||
unsafe {
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn upcast_mut<S>(&mut self) -> &mut impl Observer<BytesInput, S> {
|
||||
unsafe {
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name_trait {
|
||||
#[staticmethod]
|
||||
fn new_from_owned(owned_map_observer: $struct_name) -> Self {
|
||||
fn new_from_owned(owned_map: $struct_name) -> Self {
|
||||
Self {
|
||||
map_observer: $wrapper_name::Owned(owned_map_observer),
|
||||
wrapper: $wrapper_name::Owned(owned_map),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1549,10 +1581,8 @@ pub mod pybind {
|
||||
type IntoIter = Iter<'it, $datatype>;
|
||||
|
||||
fn as_ref_iter(&'it self) -> Self::IntoIter {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.as_ref_iter()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_ref_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1562,10 +1592,8 @@ pub mod pybind {
|
||||
type IntoIter = IterMut<'it, $datatype>;
|
||||
|
||||
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
|
||||
match &mut self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.as_mut_iter()
|
||||
}
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_mut_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1575,71 +1603,57 @@ pub mod pybind {
|
||||
|
||||
#[inline]
|
||||
fn get(&self, idx: usize) -> &$datatype {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
&map_observer.owned_map_observer.get(idx)
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner.get(idx),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
|
||||
match &mut self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.get_mut(idx)
|
||||
}
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.get_mut(idx),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn usable_count(&self) -> usize {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.usable_count()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.wrapper.usable_count(),
|
||||
}
|
||||
}
|
||||
|
||||
fn hash(&self) -> u64 {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.hash()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.hash(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial(&self) -> $datatype {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.initial()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initial_mut(&mut self) -> &mut $datatype {
|
||||
match &mut self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.initial_mut()
|
||||
}
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set_initial(&mut self, initial: $datatype) {
|
||||
match &mut self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.set_initial(initial);
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => {
|
||||
py_wrapper.inner.set_initial(initial);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_vec(&self) -> Vec<$datatype> {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.to_vec()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.to_vec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1647,10 +1661,8 @@ pub mod pybind {
|
||||
impl Named for $struct_name_trait {
|
||||
#[inline]
|
||||
fn name(&self) -> &str {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.name()
|
||||
}
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.name(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1658,8 +1670,8 @@ pub mod pybind {
|
||||
impl HasLen for $struct_name_trait {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
match &self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => map_observer.owned_map_observer.len(),
|
||||
match &self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1670,9 +1682,9 @@ pub mod pybind {
|
||||
{
|
||||
#[inline]
|
||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||
match &mut self.map_observer {
|
||||
$wrapper_name::Owned(map_observer) => {
|
||||
map_observer.owned_map_observer.pre_exec(_state, _input)
|
||||
match &mut self.wrapper {
|
||||
$wrapper_name::Owned(py_wrapper) => {
|
||||
py_wrapper.inner.pre_exec(_state, _input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,6 +290,125 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// `Observer` Python bindings
|
||||
#[cfg(feature = "python")]
|
||||
pub mod pybind {
|
||||
use crate::bolts::tuples::Named;
|
||||
use crate::executors::ExitKind;
|
||||
use crate::inputs::BytesInput;
|
||||
use crate::observers::Observer;
|
||||
use crate::Error;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
macro_rules! define_python_observer {
|
||||
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident) => {
|
||||
use crate::observers::map::pybind::PythonMapObserverI8;
|
||||
use crate::state::pybind::$my_std_state_type_name;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum $wrapper_name {
|
||||
MapI8(*mut PythonMapObserverI8),
|
||||
}
|
||||
|
||||
#[pyclass(unsendable, name = $py_name_trait)]
|
||||
#[derive(Debug)]
|
||||
/// Observer Trait binding
|
||||
pub struct $struct_name_trait {
|
||||
pub wrapper: $wrapper_name,
|
||||
}
|
||||
|
||||
impl $struct_name_trait {
|
||||
fn unwrap(&self) -> &impl Observer<BytesInput, $my_std_state_type_name> {
|
||||
unsafe {
|
||||
match self.wrapper {
|
||||
$wrapper_name::MapI8(py_wrapper) => &(*py_wrapper).upcast(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unwrap_mut(
|
||||
&mut self,
|
||||
) -> &mut impl Observer<BytesInput, $my_std_state_type_name> {
|
||||
unsafe {
|
||||
match self.wrapper {
|
||||
$wrapper_name::MapI8(py_wrapper) => &mut (*py_wrapper).upcast_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl $struct_name_trait {
|
||||
#[staticmethod]
|
||||
fn new_map(map_observer: &mut PythonMapObserverI8) -> Self {
|
||||
Self {
|
||||
observer: $wrapper_name::MapI8(map_observer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Named for $struct_name_trait {
|
||||
fn name(&self) -> &str {
|
||||
self.unwrap().name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Observer<BytesInput, $my_std_state_type_name> for $struct_name_trait {
|
||||
fn flush(&mut self) -> Result<(), Error> {
|
||||
self.unwrap_mut().flush()
|
||||
}
|
||||
|
||||
fn pre_exec(
|
||||
&mut self,
|
||||
state: &mut $my_std_state_type_name,
|
||||
input: &BytesInput,
|
||||
) -> Result<(), Error> {
|
||||
self.unwrap_mut().pre_exec(state, input)
|
||||
}
|
||||
|
||||
fn post_exec(
|
||||
&mut self,
|
||||
state: &mut $my_std_state_type_name,
|
||||
input: &BytesInput,
|
||||
exit_kind: &ExitKind,
|
||||
) -> Result<(), Error> {
|
||||
self.unwrap_mut().post_exec(state, input, exit_kind)
|
||||
}
|
||||
|
||||
fn pre_exec_child(
|
||||
&mut self,
|
||||
state: &mut $my_std_state_type_name,
|
||||
input: &BytesInput,
|
||||
) -> Result<(), Error> {
|
||||
self.unwrap_mut().pre_exec(state, input)
|
||||
}
|
||||
|
||||
fn post_exec_child(
|
||||
&mut self,
|
||||
state: &mut $my_std_state_type_name,
|
||||
input: &BytesInput,
|
||||
exit_kind: &ExitKind,
|
||||
) -> Result<(), Error> {
|
||||
self.unwrap_mut().post_exec_child(state, input, exit_kind)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
define_python_observer!(
|
||||
PythonObserver,
|
||||
"Observer",
|
||||
PythonObserverWrapper,
|
||||
PythonStdState,
|
||||
);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonObserver>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -188,7 +188,8 @@ mod tests {
|
||||
let idx1 = corpus.add(t1).unwrap();
|
||||
let idx2 = corpus.add(t2).unwrap();
|
||||
|
||||
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
|
||||
let mut state =
|
||||
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
|
||||
scheduler.on_add(state.borrow_mut(), idx1).unwrap();
|
||||
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
|
||||
let next_idx1 = scheduler.next(&mut state).unwrap();
|
||||
|
@ -79,7 +79,7 @@ mod tests {
|
||||
OnDiskCorpus::<BytesInput>::new(PathBuf::from("target/.test/fancy/objective/path"))
|
||||
.unwrap();
|
||||
|
||||
let mut state = StdState::new(rand, q, objective_q, ());
|
||||
let mut state = StdState::new(rand, q, objective_q, &mut (), &mut ()).unwrap();
|
||||
|
||||
let next_idx = scheduler.next(&mut state).unwrap();
|
||||
let filename = state
|
||||
|
@ -1,18 +1,20 @@
|
||||
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
|
||||
|
||||
use crate::{
|
||||
bolts::current_time,
|
||||
bolts::tuples::MatchName,
|
||||
bolts::{current_time, tuples::Named, AsRefIterator},
|
||||
corpus::{Corpus, SchedulerTestcaseMetaData},
|
||||
events::{EventFirer, LogSeverity},
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
feedbacks::MapFeedbackState,
|
||||
feedbacks::{
|
||||
map::{IsNovel, MapFeedback, MapFeedbackMetadata, Reducer},
|
||||
HasObserverName,
|
||||
},
|
||||
fuzzer::Evaluator,
|
||||
inputs::Input,
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::powersched::SchedulerMetadata,
|
||||
stages::Stage,
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata},
|
||||
state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasNamedMetadata},
|
||||
Error,
|
||||
};
|
||||
use alloc::string::{String, ToString};
|
||||
@ -27,9 +29,10 @@ where
|
||||
I: Input,
|
||||
O: MapObserver,
|
||||
OT: ObserversTuple<I, S>,
|
||||
S: HasCorpus<I> + HasMetadata,
|
||||
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
|
||||
{
|
||||
map_observer_name: String,
|
||||
map_name: String,
|
||||
stage_max: usize,
|
||||
phantom: PhantomData<(I, O, OT, S)>,
|
||||
}
|
||||
@ -45,7 +48,7 @@ where
|
||||
O: MapObserver,
|
||||
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
|
||||
OT: ObserversTuple<I, S>,
|
||||
S: HasCorpus<I> + HasMetadata + HasFeedbackStates + HasClientPerfMonitor,
|
||||
S: HasCorpus<I> + HasMetadata + HasClientPerfMonitor + HasNamedMetadata,
|
||||
Z: Evaluator<E, EM, I, S>,
|
||||
{
|
||||
#[inline]
|
||||
@ -147,8 +150,8 @@ where
|
||||
.to_vec();
|
||||
|
||||
let history_map = &mut state
|
||||
.feedback_states_mut()
|
||||
.match_name_mut::<MapFeedbackState<O::Entry>>(&self.map_observer_name)
|
||||
.named_metadata_mut()
|
||||
.get_mut::<MapFeedbackMetadata<O::Entry>>(&self.map_name)
|
||||
.unwrap()
|
||||
.history_map;
|
||||
|
||||
@ -222,12 +225,21 @@ where
|
||||
I: Input,
|
||||
O: MapObserver,
|
||||
OT: ObserversTuple<I, S>,
|
||||
S: HasCorpus<I> + HasMetadata,
|
||||
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
|
||||
{
|
||||
/// Create a new [`CalibrationStage`].
|
||||
pub fn new(map_observer_name: &O) -> Self {
|
||||
#[must_use]
|
||||
pub fn new<N, R>(map_feedback: &MapFeedback<I, N, O, R, S, O::Entry>) -> Self
|
||||
where
|
||||
O::Entry:
|
||||
PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
||||
R: Reducer<O::Entry>,
|
||||
for<'it> O: AsRefIterator<'it, Item = O::Entry>,
|
||||
N: IsNovel<O::Entry>,
|
||||
{
|
||||
Self {
|
||||
map_observer_name: map_observer_name.name().to_string(),
|
||||
map_observer_name: map_feedback.observer_name().to_string(),
|
||||
map_name: map_feedback.name().to_string(),
|
||||
stage_max: CAL_STAGE_START,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ use std::{
|
||||
use crate::{
|
||||
bolts::{
|
||||
rands::Rand,
|
||||
serdeany::{SerdeAny, SerdeAnyMap},
|
||||
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
|
||||
},
|
||||
corpus::Corpus,
|
||||
events::{Event, EventFirer, LogSeverity},
|
||||
feedbacks::FeedbackStatesTuple,
|
||||
feedbacks::Feedback,
|
||||
fuzzer::{Evaluator, ExecuteInputResult},
|
||||
generators::Generator,
|
||||
inputs::Input,
|
||||
@ -110,15 +110,30 @@ pub trait HasMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for elements offering a feedback
|
||||
pub trait HasFeedbackStates {
|
||||
/// The associated feedback type implementing [`FeedbackStatesTuple`].
|
||||
type FeedbackStates: FeedbackStatesTuple;
|
||||
/// The feedback states
|
||||
fn feedback_states(&self) -> &Self::FeedbackStates;
|
||||
/// Trait for elements offering named metadata
|
||||
pub trait HasNamedMetadata {
|
||||
/// A map, storing all metadata
|
||||
fn named_metadata(&self) -> &NamedSerdeAnyMap;
|
||||
/// A map, storing all metadata (mutable)
|
||||
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap;
|
||||
|
||||
/// The feedback states (mutable)
|
||||
fn feedback_states_mut(&mut self) -> &mut Self::FeedbackStates;
|
||||
/// Add a metadata to the metadata map
|
||||
#[inline]
|
||||
fn add_named_metadata<M>(&mut self, meta: M, name: &str)
|
||||
where
|
||||
M: SerdeAny,
|
||||
{
|
||||
self.named_metadata_mut().insert(meta, name);
|
||||
}
|
||||
|
||||
/// Check for a metadata
|
||||
#[inline]
|
||||
fn has_named_metadata<M>(&self, name: &str) -> bool
|
||||
where
|
||||
M: SerdeAny,
|
||||
{
|
||||
self.named_metadata().contains::<M>(name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for the execution counter
|
||||
@ -141,13 +156,12 @@ pub trait HasStartTime {
|
||||
|
||||
/// The state a fuzz run.
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
||||
pub struct StdState<C, FT, I, R, SC>
|
||||
#[serde(bound = "C: serde::Serialize + for<'a> serde::Deserialize<'a>")]
|
||||
pub struct StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
/// RNG instance
|
||||
@ -158,12 +172,12 @@ where
|
||||
start_time: Duration,
|
||||
/// The corpus
|
||||
corpus: C,
|
||||
/// States of the feedback used to evaluate an input
|
||||
feedback_states: FT,
|
||||
// Solutions corpus
|
||||
solutions: SC,
|
||||
/// Metadata stored for this state by one of the components
|
||||
metadata: SerdeAnyMap,
|
||||
/// Metadata stored with names
|
||||
named_metadata: NamedSerdeAnyMap,
|
||||
/// MaxSize testcase size for mutators that appreciate it
|
||||
max_size: usize,
|
||||
/// The stability of the current fuzzing process
|
||||
@ -176,22 +190,20 @@ where
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> State for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> State for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasRand for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasRand for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
type Rand = R;
|
||||
@ -209,12 +221,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasCorpus<I> for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasCorpus<I> for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
type Corpus = C;
|
||||
@ -232,12 +243,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasSolutions<I> for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasSolutions<I> for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
type Solutions = SC;
|
||||
@ -255,12 +265,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasMetadata for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasMetadata for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
/// Get all the metadata into an [`hashbrown::HashMap`]
|
||||
@ -276,35 +285,31 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasFeedbackStates for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasNamedMetadata for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
type FeedbackStates = FT;
|
||||
|
||||
/// The feedback states
|
||||
/// Get all the metadata into an [`hashbrown::HashMap`]
|
||||
#[inline]
|
||||
fn feedback_states(&self) -> &FT {
|
||||
&self.feedback_states
|
||||
fn named_metadata(&self) -> &NamedSerdeAnyMap {
|
||||
&self.named_metadata
|
||||
}
|
||||
|
||||
/// The feedback states (mutable)
|
||||
/// Get all the metadata into an [`hashbrown::HashMap`] (mutable)
|
||||
#[inline]
|
||||
fn feedback_states_mut(&mut self) -> &mut FT {
|
||||
&mut self.feedback_states
|
||||
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap {
|
||||
&mut self.named_metadata
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasExecutions for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasExecutions for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
/// The executions counter
|
||||
@ -320,12 +325,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasMaxSize for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasMaxSize for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
fn max_size(&self) -> usize {
|
||||
@ -337,12 +341,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> HasStartTime for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasStartTime for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
/// The starting time
|
||||
@ -359,12 +362,11 @@ where
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<C, FT, I, R, SC> StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
/// Loads inputs from a directory.
|
||||
@ -480,12 +482,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, FT, I, R, SC> StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
fn generate_initial_internal<G, E, EM, Z>(
|
||||
@ -561,31 +562,43 @@ where
|
||||
}
|
||||
|
||||
/// Creates a new `State`, taking ownership of all of the individual components during fuzzing.
|
||||
pub fn new(rand: R, corpus: C, solutions: SC, feedback_states: FT) -> Self {
|
||||
Self {
|
||||
pub fn new<F, O>(
|
||||
rand: R,
|
||||
corpus: C,
|
||||
solutions: SC,
|
||||
feedback: &mut F,
|
||||
objective: &mut O,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
F: Feedback<I, Self>,
|
||||
O: Feedback<I, Self>,
|
||||
{
|
||||
let mut state = Self {
|
||||
rand,
|
||||
executions: 0,
|
||||
stability: None,
|
||||
start_time: Duration::from_millis(0),
|
||||
metadata: SerdeAnyMap::default(),
|
||||
named_metadata: NamedSerdeAnyMap::default(),
|
||||
corpus,
|
||||
feedback_states,
|
||||
solutions,
|
||||
max_size: DEFAULT_MAX_SIZE,
|
||||
#[cfg(feature = "introspection")]
|
||||
introspection_monitor: ClientPerfMonitor::new(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
};
|
||||
feedback.init_state(&mut state)?;
|
||||
objective.init_state(&mut state)?;
|
||||
Ok(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
impl<C, FT, I, R, SC> HasClientPerfMonitor for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasClientPerfMonitor for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
||||
@ -610,12 +623,11 @@ where
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "introspection"))]
|
||||
impl<C, FT, I, R, SC> HasClientPerfMonitor for StdState<C, FT, I, R, SC>
|
||||
impl<C, I, R, SC> HasClientPerfMonitor for StdState<C, I, R, SC>
|
||||
where
|
||||
C: Corpus<I>,
|
||||
I: Input,
|
||||
R: Rand,
|
||||
FT: FeedbackStatesTuple,
|
||||
SC: Corpus<I>,
|
||||
{
|
||||
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
||||
@ -645,28 +657,20 @@ pub mod pybind {
|
||||
use crate::bolts::rands::pybind::PythonRand;
|
||||
use crate::bolts::tuples::tuple_list;
|
||||
use crate::corpus::pybind::PythonCorpus;
|
||||
use crate::feedbacks::map::MapFeedbackState;
|
||||
use crate::feedbacks::pybind::PythonFeedback;
|
||||
use crate::inputs::BytesInput;
|
||||
use crate::state::StdState;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
macro_rules! define_python_state {
|
||||
($type_name:ident, $struct_name:ident, $py_name:tt, $datatype:ty, $py_map_feedback_state_name:ident, $event_manager_name: ident,
|
||||
$fuzzer_name: ident, $executor_name: ident, $rand_printable_generator: ident) => {
|
||||
($type_name:ident, $struct_name:ident, $py_name:tt) => {
|
||||
use crate::events::pybind::$event_manager_name;
|
||||
use crate::executors::pybind::$executor_name;
|
||||
use crate::feedbacks::map::pybind::$py_map_feedback_state_name;
|
||||
use crate::fuzzer::pybind::$fuzzer_name;
|
||||
use crate::generators::pybind::$rand_printable_generator;
|
||||
|
||||
/// `StdState` with fixed generics
|
||||
pub type $type_name = StdState<
|
||||
PythonCorpus,
|
||||
(MapFeedbackState<$datatype>, ()),
|
||||
BytesInput,
|
||||
PythonRand,
|
||||
PythonCorpus,
|
||||
>;
|
||||
pub type $type_name = StdState<PythonCorpus, BytesInput, PythonRand, PythonCorpus>;
|
||||
|
||||
#[pyclass(unsendable, name = $py_name)]
|
||||
#[derive(Debug)]
|
||||
@ -683,24 +687,20 @@ pub mod pybind {
|
||||
py_rand: PythonRand,
|
||||
corpus: PythonCorpus,
|
||||
solutions: PythonCorpus,
|
||||
py_map_feedback_state: $py_map_feedback_state_name,
|
||||
feedback: &mut PythonFeedback,
|
||||
objective: &mut PythonFeedback,
|
||||
) -> Self {
|
||||
Self {
|
||||
std_state: StdState::new(
|
||||
py_rand,
|
||||
corpus,
|
||||
solutions,
|
||||
tuple_list!(py_map_feedback_state.map_feedback_state),
|
||||
),
|
||||
std_state: StdState::new(py_rand, corpus, solutions, feedback, objective),
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_initial_inputs(
|
||||
&mut self,
|
||||
py_fuzzer: &mut $fuzzer_name,
|
||||
py_executor: &mut $executor_name,
|
||||
py_generator: &mut $rand_printable_generator,
|
||||
py_mgr: &mut $event_manager_name,
|
||||
py_fuzzer: &mut PythonFuzzer,
|
||||
py_executor: &mut PythonExecutor,
|
||||
py_generator: &mut PythonGenerator,
|
||||
py_mgr: &mut PythonEventManager,
|
||||
num: usize,
|
||||
) {
|
||||
self.std_state
|
||||
@ -717,109 +717,11 @@ pub mod pybind {
|
||||
};
|
||||
}
|
||||
|
||||
define_python_state!(
|
||||
MyStdStateI8,
|
||||
PythonStdStateI8,
|
||||
"StdStateI8",
|
||||
i8,
|
||||
PythonMapFeedbackStateI8,
|
||||
PythonEventManagerI8,
|
||||
PythonStdFuzzerI8,
|
||||
PythonExecutorI8,
|
||||
PythonRandPrintablesGeneratorI8
|
||||
);
|
||||
|
||||
define_python_state!(
|
||||
MyStdStateI16,
|
||||
PythonStdStateI16,
|
||||
"StdStateI16",
|
||||
i16,
|
||||
PythonMapFeedbackStateI16,
|
||||
PythonEventManagerI16,
|
||||
PythonStdFuzzerI16,
|
||||
PythonExecutorI16,
|
||||
PythonRandPrintablesGeneratorI16
|
||||
);
|
||||
|
||||
define_python_state!(
|
||||
MyStdStateI32,
|
||||
PythonStdStateI32,
|
||||
"StdStateI32",
|
||||
i32,
|
||||
PythonMapFeedbackStateI32,
|
||||
PythonEventManagerI32,
|
||||
PythonStdFuzzerI32,
|
||||
PythonExecutorI32,
|
||||
PythonRandPrintablesGeneratorI32
|
||||
);
|
||||
|
||||
define_python_state!(
|
||||
MyStdStateI64,
|
||||
PythonStdStateI64,
|
||||
"StdStateI64",
|
||||
i64,
|
||||
PythonMapFeedbackStateI64,
|
||||
PythonEventManagerI64,
|
||||
PythonStdFuzzerI64,
|
||||
PythonExecutorI64,
|
||||
PythonRandPrintablesGeneratorI64
|
||||
);
|
||||
define_python_state!(
|
||||
MyStdStateU8,
|
||||
PythonStdStateU8,
|
||||
"StdStateU8",
|
||||
u8,
|
||||
PythonMapFeedbackStateU8,
|
||||
PythonEventManagerU8,
|
||||
PythonStdFuzzerU8,
|
||||
PythonExecutorU8,
|
||||
PythonRandPrintablesGeneratorU8
|
||||
);
|
||||
define_python_state!(
|
||||
MyStdStateU16,
|
||||
PythonStdStateU16,
|
||||
"StdStateU16",
|
||||
u16,
|
||||
PythonMapFeedbackStateU16,
|
||||
PythonEventManagerU16,
|
||||
PythonStdFuzzerU16,
|
||||
PythonExecutorU16,
|
||||
PythonRandPrintablesGeneratorU16
|
||||
);
|
||||
define_python_state!(
|
||||
MyStdStateU32,
|
||||
PythonStdStateU32,
|
||||
"StdStateU32",
|
||||
u32,
|
||||
PythonMapFeedbackStateU32,
|
||||
PythonEventManagerU32,
|
||||
PythonStdFuzzerU32,
|
||||
PythonExecutorU32,
|
||||
PythonRandPrintablesGeneratorU32
|
||||
);
|
||||
define_python_state!(
|
||||
MyStdStateU64,
|
||||
PythonStdStateU64,
|
||||
"StdStateU64",
|
||||
u64,
|
||||
PythonMapFeedbackStateU64,
|
||||
PythonEventManagerU64,
|
||||
PythonStdFuzzerU64,
|
||||
PythonExecutorU64,
|
||||
PythonRandPrintablesGeneratorU64
|
||||
);
|
||||
define_python_state!(PythonStdState, PythonStdStateWrapper, "StdState",);
|
||||
|
||||
/// Register the classes to the python module
|
||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<PythonStdStateI8>()?;
|
||||
m.add_class::<PythonStdStateI16>()?;
|
||||
m.add_class::<PythonStdStateI32>()?;
|
||||
m.add_class::<PythonStdStateI64>()?;
|
||||
|
||||
m.add_class::<PythonStdStateU8>()?;
|
||||
m.add_class::<PythonStdStateU16>()?;
|
||||
m.add_class::<PythonStdStateU32>()?;
|
||||
m.add_class::<PythonStdStateU64>()?;
|
||||
m.add_class::<PythonStdStateWrapper>()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5cccc33456c48ad83008eb618e7da5d005c72d89
|
||||
Subproject commit 45cde0269ae22aef4cca2e1fb98c3b24f7bb2984
|
@ -17,7 +17,7 @@ use libafl::{
|
||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||
executors::{forkserver::ForkserverExecutorBuilder, TimeoutForkserverExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandBytesGenerator,
|
||||
monitors::MultiMonitor,
|
||||
@ -111,7 +111,7 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
||||
|
||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
||||
let mut run_client = |state: Option<_>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
// Coverage map shared between target and fuzzer
|
||||
@ -130,20 +130,17 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
||||
// Create an observation channel to keep track of the execution time
|
||||
let time_observer = TimeObserver::new("time");
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -155,10 +152,10 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
||||
// Corpus in which we store solutions (crashes in this example),
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// Create a dictionary if not existing
|
||||
|
@ -19,7 +19,7 @@ use libafl::{
|
||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandBytesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -138,7 +138,7 @@ where
|
||||
|
||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
||||
let mut run_client = |state: Option<_>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
@ -151,20 +151,17 @@ where
|
||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -176,10 +173,10 @@ where
|
||||
// Corpus in which we store solutions (crashes in this example),
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// Create a dictionary if not existing
|
||||
|
@ -18,7 +18,7 @@ use libafl::{
|
||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||
feedback_or, feedback_or_fast,
|
||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
generators::RandBytesGenerator,
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
@ -141,7 +141,7 @@ where
|
||||
|
||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||
|
||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
||||
let mut run_client = |state: Option<_>,
|
||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||
_core_id| {
|
||||
// Create an observation channel using the coverage map
|
||||
@ -157,20 +157,17 @@ where
|
||||
let cmplog = unsafe { &mut cmplog::CMPLOG_MAP };
|
||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||
|
||||
// The state of the edges feedback.
|
||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
||||
|
||||
// Feedback to rate the interestingness of an input
|
||||
// This one is composed by two Feedbacks in OR
|
||||
let feedback = feedback_or!(
|
||||
let mut feedback = feedback_or!(
|
||||
// New maximization map feedback linked to the edges observer and the feedback state
|
||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
|
||||
MaxMapFeedback::new_tracking(&edges_observer, true, false),
|
||||
// Time feedback, this one does not need a feedback state
|
||||
TimeFeedback::new_with_observer(&time_observer)
|
||||
);
|
||||
|
||||
// A feedback to choose if an input is a solution or not
|
||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
||||
|
||||
// If not restarting, create a State from scratch
|
||||
let mut state = state.unwrap_or_else(|| {
|
||||
@ -182,10 +179,10 @@ where
|
||||
// Corpus in which we store solutions (crashes in this example),
|
||||
// on disk so the user can get them after stopping the fuzzer
|
||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||
// States of the feedbacks.
|
||||
// They are the data related to the feedbacks that you want to persist in the State.
|
||||
tuple_list!(feedback_state),
|
||||
&mut feedback,
|
||||
&mut objective,
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// Create a dictionary if not existing
|
||||
|
Loading…
x
Reference in New Issue
Block a user