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"] }
|
pyo3 = { version = "0.15", features = ["extension-module"] }
|
||||||
libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] }
|
libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] }
|
||||||
libafl_sugar = { path = "../../libafl_sugar", 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]
|
[build-dependencies]
|
||||||
pyo3-build-config = { version = "0.15" }
|
pyo3-build-config = { version = "0.15" }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use libafl;
|
//use libafl;
|
||||||
use libafl_qemu;
|
use libafl_qemu;
|
||||||
use libafl_sugar;
|
use libafl_sugar;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
@ -14,9 +14,9 @@ pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
|
|||||||
libafl_qemu::python_module(py, qemu_module)?;
|
libafl_qemu::python_module(py, qemu_module)?;
|
||||||
m.add_submodule(qemu_module)?;
|
m.add_submodule(qemu_module)?;
|
||||||
|
|
||||||
let libafl_module = PyModule::new(py, "libafl")?;
|
//let libafl_module = PyModule::new(py, "libafl")?;
|
||||||
libafl::python_module(py, libafl_module)?;
|
//libafl::python_module(py, libafl_module)?;
|
||||||
m.add_submodule(libafl_module)?;
|
//m.add_submodule(libafl_module)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -114,8 +114,9 @@ let mut state = StdState::new(
|
|||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
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.
|
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());
|
.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.
|
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::{
|
use libafl::{
|
||||||
bolts::{current_nanos, rands::StdRand, tuples::tuple_list},
|
bolts::{current_nanos, rands::StdRand, tuples::tuple_list},
|
||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
feedbacks::{MapFeedbackState, MaxMapFeedback, CrashFeedback},
|
feedbacks::{MaxMapFeedback, CrashFeedback},
|
||||||
fuzzer::StdFuzzer,
|
fuzzer::StdFuzzer,
|
||||||
state::StdState,
|
state::StdState,
|
||||||
observers::StdMapObserver,
|
observers::StdMapObserver,
|
||||||
};
|
};
|
||||||
|
|
||||||
// The state of the edges feedback.
|
|
||||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -310,10 +308,9 @@ let mut state = StdState::new(
|
|||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective
|
||||||
tuple_list!(feedback_state),
|
).unwrap();
|
||||||
);
|
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -41,7 +41,7 @@ pub fn main() {
|
|||||||
signals_set(2);
|
signals_set(2);
|
||||||
if buf.len() > 2 && buf[2] == b'c' {
|
if buf.len() > 2 && buf[2] == b'c' {
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
panic!("=(");
|
panic!("Artificial bug triggered =)");
|
||||||
|
|
||||||
// panic!() raises a STATUS_STACK_BUFFER_OVERRUN exception which cannot be caught by the exception handler.
|
// 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.
|
// Here we make it raise STATUS_ACCESS_VIOLATION instead.
|
||||||
@ -58,16 +58,14 @@ pub fn main() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
let observer =
|
||||||
|
unsafe { StdMapObserver::new_from_ptr("signals", SIGNALS.as_mut_ptr(), SIGNALS.len()) };
|
||||||
// The state of the edges feedback.
|
|
||||||
let feedback_state = MapFeedbackState::with_observer(&observer);
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -79,9 +77,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -13,7 +13,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::{Automaton, GramatronGenerator},
|
generators::{Automaton, GramatronGenerator},
|
||||||
inputs::GramatronInput,
|
inputs::GramatronInput,
|
||||||
@ -61,14 +61,11 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -80,9 +77,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -9,7 +9,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
||||||
inputs::{GeneralizedInput, HasTargetBytes},
|
inputs::{GeneralizedInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -92,14 +92,11 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -111,9 +108,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if state.metadata().get::<Tokens>().is_none() {
|
if state.metadata().get::<Tokens>().is_none() {
|
||||||
state.add_metadata(Tokens::from([b"FOO".to_vec(), b"BAR".to_vec()]));
|
state.add_metadata(Tokens::from([b"FOO".to_vec(), b"BAR".to_vec()]));
|
||||||
|
@ -9,9 +9,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::{NautilusContext, NautilusGenerator},
|
generators::{NautilusContext, NautilusGenerator},
|
||||||
inputs::NautilusInput,
|
inputs::NautilusInput,
|
||||||
@ -51,17 +49,14 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
let feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
MaxMapFeedback::new(&feedback_state, &observer),
|
MaxMapFeedback::new(&observer),
|
||||||
NautilusFeedback::new(&context)
|
NautilusFeedback::new(&context)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -73,9 +68,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if state.metadata().get::<NautilusChunksMetadata>().is_none() {
|
if state.metadata().get::<NautilusChunksMetadata>().is_none() {
|
||||||
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));
|
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));
|
||||||
|
@ -9,7 +9,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
|
||||||
inputs::{EncodedInput, InputDecoder, InputEncoder, NaiveTokenizer, TokenInputEncoderDecoder},
|
inputs::{EncodedInput, InputDecoder, InputEncoder, NaiveTokenizer, TokenInputEncoderDecoder},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -69,14 +69,11 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -88,9 +85,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -14,7 +14,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{ExitKind, InProcessForkExecutor},
|
executors::{ExitKind, InProcessForkExecutor},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -68,14 +68,11 @@ pub fn main() {
|
|||||||
let observer = StdMapObserver::new("signals", signals_clone.as_mut_slice());
|
let observer = StdMapObserver::new("signals", signals_clone.as_mut_slice());
|
||||||
// Create a stacktrace observer to add the observers tuple
|
// 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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -87,9 +84,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -9,7 +9,7 @@ use libafl::{
|
|||||||
corpus::InMemoryCorpus,
|
corpus::InMemoryCorpus,
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -77,14 +77,11 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -96,9 +93,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
InMemoryCorpus::new(),
|
InMemoryCorpus::new(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| {
|
let monitor = SimpleMonitor::new(|s| {
|
||||||
|
@ -14,9 +14,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::InProcessForkExecutor,
|
executors::InProcessForkExecutor,
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -59,17 +57,13 @@ pub fn main() {
|
|||||||
libafl::observers::HarnessType::Child,
|
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
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
@ -82,9 +76,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, st_feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -8,9 +8,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -48,17 +46,13 @@ pub fn main() {
|
|||||||
libafl::observers::HarnessType::InProcess,
|
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
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
@ -71,9 +65,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, st_feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -10,9 +10,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::command::CommandConfigurator,
|
executors::command::CommandConfigurator,
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{HasTargetBytes, Input},
|
inputs::{HasTargetBytes, Input},
|
||||||
@ -43,22 +41,15 @@ pub fn main() {
|
|||||||
// Create a stacktrace observer
|
// Create a stacktrace observer
|
||||||
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
|
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
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
NewHashFeedback::<ASANBacktraceObserver>::new_with_observer(
|
NewHashFeedback::<ASANBacktraceObserver>::new(&bt_observer)
|
||||||
"ASANBacktraceObserver",
|
|
||||||
&bt_observer
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
// let objective = CrashFeedback::new();
|
// let mut objective = CrashFeedback::new();
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -70,9 +61,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, bt_feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -10,9 +10,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::forkserver::ForkserverExecutor,
|
executors::forkserver::ForkserverExecutor,
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::BytesInput,
|
inputs::BytesInput,
|
||||||
@ -54,20 +52,13 @@ pub fn main() {
|
|||||||
|
|
||||||
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
// We want to do the same crash deduplication that AFL does
|
// We want to do the same crash deduplication that AFL does
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(CrashFeedback::new(), NewHashFeedback::new(&bt_observer));
|
||||||
CrashFeedback::new(),
|
|
||||||
NewHashFeedback::new_with_observer("NewHashFeedback", &bt_observer)
|
|
||||||
);
|
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -79,9 +70,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, bt_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -15,9 +15,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{ExitKind, InProcessForkExecutor},
|
executors::{ExitKind, InProcessForkExecutor},
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -76,17 +74,13 @@ pub fn main() {
|
|||||||
libafl::observers::HarnessType::Child,
|
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
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
|
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
@ -99,9 +93,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, bt_feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -9,9 +9,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedback_and,
|
feedback_and,
|
||||||
feedbacks::{
|
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
|
||||||
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
|
|
||||||
},
|
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -70,17 +68,13 @@ pub fn main() {
|
|||||||
libafl::observers::HarnessType::InProcess,
|
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
|
// 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
|
// A feedback to choose if an input is a solution or not
|
||||||
let objective = feedback_and!(
|
let mut objective = feedback_and!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
NewHashFeedback::<BacktraceObserver>::new_with_observer("NewHashFeedback", &bt_observer)
|
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// create a State from scratch
|
// create a State from scratch
|
||||||
@ -93,9 +87,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, hash_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are displayed to the user
|
// The Monitor trait define how the fuzzer stats are displayed to the user
|
||||||
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
let mon = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use libafl::{
|
use libafl::{
|
||||||
bolts::{
|
bolts::{
|
||||||
@ -12,7 +12,7 @@ use libafl::{
|
|||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::forkserver::{ForkserverExecutor, TimeoutForkserverExecutor},
|
executors::forkserver::{ForkserverExecutor, TimeoutForkserverExecutor},
|
||||||
feedback_and_fast, feedback_or,
|
feedback_and_fast, feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::BytesInput,
|
inputs::BytesInput,
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -33,7 +33,7 @@ use libafl::bolts::shmem::StdShMemProvider;
|
|||||||
|
|
||||||
#[allow(clippy::similar_names)]
|
#[allow(clippy::similar_names)]
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let res = App::new("forkserver_simple")
|
let res = Command::new("forkserver_simple")
|
||||||
.about("Example Forkserver fuzer")
|
.about("Example Forkserver fuzer")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("executable")
|
Arg::new("executable")
|
||||||
@ -63,7 +63,7 @@ pub fn main() {
|
|||||||
.arg(
|
.arg(
|
||||||
Arg::new("arguments")
|
Arg::new("arguments")
|
||||||
.help("Arguments passed to the target")
|
.help("Arguments passed to the target")
|
||||||
.setting(clap::ArgSettings::MultipleValues)
|
.multiple_values(true)
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
@ -101,28 +101,22 @@ pub fn main() {
|
|||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// A feedback to choose if an input is a solution or not
|
||||||
// We want to do the same crash deduplication that AFL does
|
// 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
|
// Must be a crash
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
// Take it onlt if trigger new coverage over crashes
|
// 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
|
// create a State from scratch
|
||||||
@ -135,9 +129,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state, objective_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
@ -163,7 +160,7 @@ pub fn main() {
|
|||||||
|
|
||||||
let mut tokens = Tokens::new();
|
let mut tokens = Tokens::new();
|
||||||
let forkserver = ForkserverExecutor::builder()
|
let forkserver = ForkserverExecutor::builder()
|
||||||
.program(res.value_of("executable").unwrap().to_string())
|
.program(res.value_of("executable").unwrap())
|
||||||
.debug_child(debug_child)
|
.debug_child(debug_child)
|
||||||
.shmem_provider(&mut shmem_provider)
|
.shmem_provider(&mut shmem_provider)
|
||||||
.autotokens(&mut tokens)
|
.autotokens(&mut tokens)
|
||||||
|
@ -20,8 +20,8 @@ use libafl::{
|
|||||||
corpus::{ondisk::OnDiskMetadataFormat, CachedOnDiskCorpus, Corpus, OnDiskCorpus},
|
corpus::{ondisk::OnDiskMetadataFormat, CachedOnDiskCorpus, Corpus, OnDiskCorpus},
|
||||||
events::{llmp::LlmpRestartingEventManager, EventConfig},
|
events::{llmp::LlmpRestartingEventManager, EventConfig},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_and_fast, feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -72,9 +72,13 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
|
|
||||||
let shmem_provider = StdShMemProvider::new()?;
|
let shmem_provider = StdShMemProvider::new()?;
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
let mut run_client = |state: Option<_>,
|
||||||
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||||
core_id| {
|
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 lib = libloading::Library::new(options.clone().harness.unwrap()).unwrap();
|
||||||
let target_func: libloading::Symbol<
|
let target_func: libloading::Symbol<
|
||||||
unsafe extern "C" fn(data: *const u8, size: usize) -> i32,
|
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) {
|
if options.asan && options.asan_cores.contains(core_id) {
|
||||||
(|state: Option<StdState<_, _, _, _, _>>,
|
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
|
||||||
_core_id| {
|
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
let coverage = CoverageRuntime::new();
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
// Feedbacks to recognize an input as solution
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let objective = feedback_or_fast!(
|
let mut objective = feedback_or_fast!(
|
||||||
CrashFeedback::new(),
|
CrashFeedback::new(),
|
||||||
TimeoutFeedback::new(),
|
TimeoutFeedback::new(),
|
||||||
AsanErrorsFeedback::new()
|
// true enables the AsanErrorFeedback
|
||||||
|
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
|
||||||
);
|
);
|
||||||
#[cfg(windows)]
|
#[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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
let mut state = state.unwrap_or_else(|| {
|
||||||
@ -149,10 +150,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
Some(OnDiskMetadataFormat::JsonPretty),
|
Some(OnDiskMetadataFormat::JsonPretty),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
@ -216,9 +217,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
})(state, mgr, core_id)
|
})(state, mgr, core_id)
|
||||||
} else if options.cmplog && options.cmplog_cores.contains(core_id) {
|
} else if options.cmplog && options.cmplog_cores.contains(core_id) {
|
||||||
(|state: Option<StdState<_, _, _, _, _>>,
|
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
|
||||||
_core_id| {
|
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
let coverage = CoverageRuntime::new();
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
#[cfg(unix)]
|
||||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
let mut state = state.unwrap_or_else(|| {
|
||||||
@ -265,10 +268,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
Some(OnDiskMetadataFormat::JsonPretty),
|
Some(OnDiskMetadataFormat::JsonPretty),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
@ -348,9 +351,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
})(state, mgr, core_id)
|
})(state, mgr, core_id)
|
||||||
} else {
|
} else {
|
||||||
(|state: Option<StdState<_, _, _, _, _>>,
|
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
|
||||||
_core_id| {
|
|
||||||
let gum = Gum::obtain();
|
let gum = Gum::obtain();
|
||||||
|
|
||||||
let coverage = CoverageRuntime::new();
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Feedbacks to recognize an input as solution
|
#[cfg(unix)]
|
||||||
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
|
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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
let mut state = state.unwrap_or_else(|| {
|
||||||
@ -396,10 +401,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
|
|||||||
Some(OnDiskMetadataFormat::JsonPretty),
|
Some(OnDiskMetadataFormat::JsonPretty),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: MiMalloc = MiMalloc;
|
static GLOBAL: MiMalloc = MiMalloc;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use core::{cell::RefCell, time::Duration};
|
use core::{cell::RefCell, time::Duration};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use nix::{self, unistd::dup};
|
use nix::{self, unistd::dup};
|
||||||
@ -30,7 +30,7 @@ use libafl::{
|
|||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -64,7 +64,7 @@ pub fn libafl_main() {
|
|||||||
// Needed only on no_std
|
// Needed only on no_std
|
||||||
//RegistryBuilder::register::<Tokens>();
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
let res = match App::new("libafl_fuzzbench")
|
let res = match Command::new("libafl_fuzzbench")
|
||||||
.version("0.7.1")
|
.version("0.7.1")
|
||||||
.author("AFLplusplus team")
|
.author("AFLplusplus team")
|
||||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||||
@ -113,7 +113,7 @@ pub fn libafl_main() {
|
|||||||
env::current_exe()
|
env::current_exe()
|
||||||
.unwrap_or_else(|_| "fuzzer".into())
|
.unwrap_or_else(|_| "fuzzer".into())
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
err.info,
|
err,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,20 +260,21 @@ fn fuzz(
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Let's fuzz :)");
|
println!("Let's fuzz :)");
|
||||||
@ -300,8 +304,6 @@ fn fuzz(
|
|||||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
}
|
}
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "fuzzbench_qemu"
|
name = "fuzzbench_fork_qemu"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use nix::{self, unistd::dup};
|
use nix::{self, unistd::dup};
|
||||||
@ -27,7 +27,7 @@ use libafl::{
|
|||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{ExitKind, ShadowExecutor},
|
executors::{ExitKind, ShadowExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -62,7 +62,7 @@ pub fn main() {
|
|||||||
// Needed only on no_std
|
// Needed only on no_std
|
||||||
//RegistryBuilder::register::<Tokens>();
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
let res = match App::new("libafl_qemu_fuzzbench")
|
let res = match Command::new("libafl_qemu_fuzzbench")
|
||||||
.version("0.4.0")
|
.version("0.4.0")
|
||||||
.author("AFLplusplus team")
|
.author("AFLplusplus team")
|
||||||
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
||||||
@ -101,7 +101,7 @@ pub fn main() {
|
|||||||
env::current_exe()
|
env::current_exe()
|
||||||
.unwrap_or_else(|_| "fuzzer".into())
|
.unwrap_or_else(|_| "fuzzer".into())
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
err.info,
|
err,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -240,20 +240,21 @@ fn fuzz(
|
|||||||
let cmplog_observer =
|
let cmplog_observer =
|
||||||
CmpLogObserver::new("cmplog", unsafe { CMPLOG_MAP_PTR.as_mut().unwrap() }, true);
|
CmpLogObserver::new("cmplog", unsafe { CMPLOG_MAP_PTR.as_mut().unwrap() }, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
//! A singlethreaded QEMU fuzzer that can auto-restart.
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use core::{cell::RefCell, time::Duration};
|
use core::{cell::RefCell, time::Duration};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use nix::{self, unistd::dup};
|
use nix::{self, unistd::dup};
|
||||||
@ -27,7 +27,7 @@ use libafl::{
|
|||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -68,7 +68,7 @@ pub fn main() {
|
|||||||
// Needed only on no_std
|
// Needed only on no_std
|
||||||
//RegistryBuilder::register::<Tokens>();
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
let res = match App::new("libafl_qemu_fuzzbench")
|
let res = match Command::new("libafl_qemu_fuzzbench")
|
||||||
.version("0.4.0")
|
.version("0.4.0")
|
||||||
.author("AFLplusplus team")
|
.author("AFLplusplus team")
|
||||||
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
|
||||||
@ -113,7 +113,7 @@ pub fn main() {
|
|||||||
env::current_exe()
|
env::current_exe()
|
||||||
.unwrap_or_else(|_| "fuzzer".into())
|
.unwrap_or_else(|_| "fuzzer".into())
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
err.info,
|
err,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -253,20 +253,21 @@ fn fuzz(
|
|||||||
// Create an observation channel using cmplog map
|
// Create an observation channel using cmplog map
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: MiMalloc = MiMalloc;
|
static GLOBAL: MiMalloc = MiMalloc;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use content_inspector::inspect;
|
use content_inspector::inspect;
|
||||||
use core::{cell::RefCell, time::Duration};
|
use core::{cell::RefCell, time::Duration};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -31,7 +31,7 @@ use libafl::{
|
|||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, GeneralizedInput, HasTargetBytes},
|
inputs::{BytesInput, GeneralizedInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -70,7 +70,7 @@ pub fn libafl_main() {
|
|||||||
// Needed only on no_std
|
// Needed only on no_std
|
||||||
//RegistryBuilder::register::<Tokens>();
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
let res = match App::new("libafl_fuzzbench")
|
let res = match Command::new("libafl_fuzzbench")
|
||||||
.version("0.7.1")
|
.version("0.7.1")
|
||||||
.author("AFLplusplus team")
|
.author("AFLplusplus team")
|
||||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||||
@ -119,7 +119,7 @@ pub fn libafl_main() {
|
|||||||
env::current_exe()
|
env::current_exe()
|
||||||
.unwrap_or_else(|_| "fuzzer".into())
|
.unwrap_or_else(|_| "fuzzer".into())
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
err.info,
|
err,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -321,20 +321,20 @@ fn fuzz_binary(
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Let's fuzz :)");
|
println!("Let's fuzz :)");
|
||||||
@ -361,8 +364,6 @@ fn fuzz_binary(
|
|||||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
}
|
}
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
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 = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
// New maximization map feedback linked to the edges observer and the feedback state
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
map_feedback,
|
||||||
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, true),
|
|
||||||
// Time feedback, this one does not need a feedback state
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Let's fuzz :)");
|
println!("Let's fuzz :)");
|
||||||
@ -571,8 +576,6 @@ fn fuzz_text(
|
|||||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
}
|
}
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
|
|||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: MiMalloc = MiMalloc;
|
static GLOBAL: MiMalloc = MiMalloc;
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{Arg, Command};
|
||||||
use core::{cell::RefCell, time::Duration};
|
use core::{cell::RefCell, time::Duration};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use nix::{self, unistd::dup};
|
use nix::{self, unistd::dup};
|
||||||
@ -30,7 +30,7 @@ use libafl::{
|
|||||||
events::SimpleRestartingEventManager,
|
events::SimpleRestartingEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -64,7 +64,7 @@ pub fn libafl_main() {
|
|||||||
// Needed only on no_std
|
// Needed only on no_std
|
||||||
//RegistryBuilder::register::<Tokens>();
|
//RegistryBuilder::register::<Tokens>();
|
||||||
|
|
||||||
let res = match App::new("libafl_fuzzbench")
|
let res = match Command::new("libafl_fuzzbench")
|
||||||
.version("0.7.1")
|
.version("0.7.1")
|
||||||
.author("AFLplusplus team")
|
.author("AFLplusplus team")
|
||||||
.about("LibAFL-based fuzzer for Fuzzbench")
|
.about("LibAFL-based fuzzer for Fuzzbench")
|
||||||
@ -113,7 +113,7 @@ pub fn libafl_main() {
|
|||||||
env::current_exe()
|
env::current_exe()
|
||||||
.unwrap_or_else(|_| "fuzzer".into())
|
.unwrap_or_else(|_| "fuzzer".into())
|
||||||
.to_string_lossy(),
|
.to_string_lossy(),
|
||||||
err.info,
|
err,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,20 +260,21 @@ fn fuzz(
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("Let's fuzz :)");
|
println!("Let's fuzz :)");
|
||||||
@ -300,8 +304,6 @@ fn fuzz(
|
|||||||
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
println!("Warning: LLVMFuzzerInitialize failed with -1")
|
||||||
}
|
}
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
|
|
||||||
// Setup a randomic Input2State stage
|
// Setup a randomic Input2State stage
|
||||||
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
|
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)
|
//! This is the drop-in replacement for libfuzzer, to be used together with [`Atheris`](https://github.com/google/atheris)
|
||||||
//! for python instrumentation and fuzzing.
|
//! 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 core::{convert::TryInto, ffi::c_void, slice, time::Duration};
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
@ -25,7 +25,7 @@ use libafl::{
|
|||||||
events::EventConfig,
|
events::EventConfig,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandBytesGenerator,
|
generators::RandBytesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -124,7 +124,7 @@ pub fn LLVMFuzzerRunDriver(
|
|||||||
|
|
||||||
println!("Args: {:?}", std::env::args());
|
println!("Args: {:?}", std::env::args());
|
||||||
|
|
||||||
let matches = App::new("libafl_atheris")
|
let matches = Command::new("libafl_atheris")
|
||||||
.version("0.1.0")
|
.version("0.1.0")
|
||||||
.setting(AppSettings::AllowExternalSubcommands)
|
.setting(AppSettings::AllowExternalSubcommands)
|
||||||
.arg(Arg::new("script")) // The python script is the first arg
|
.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.
|
// 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
|
// Create an observation channel using the coverage map
|
||||||
let edges_observer = unsafe {
|
let edges_observer = unsafe {
|
||||||
HitcountsMapObserver::new(StdMapObserver::new_from_ptr(
|
HitcountsMapObserver::new(StdMapObserver::new_from_ptr(
|
||||||
@ -230,20 +230,17 @@ pub fn LLVMFuzzerRunDriver(
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(output_dir.clone()).unwrap(),
|
OnDiskCorpus::new(output_dir.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a dictionary if not existing
|
// Create a dictionary if not existing
|
||||||
|
@ -17,7 +17,7 @@ use libafl::{
|
|||||||
events::{setup_restarting_mgr_std, EventConfig},
|
events::{setup_restarting_mgr_std, EventConfig},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
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
|
// Create an observation channel using the allocations map
|
||||||
let allocs_observer = StdMapObserver::new("allocs", unsafe { &mut libafl_alloc_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
|
// Feedback to rate the interestingness of an input
|
||||||
let feedback = feedback_or!(
|
let mut feedback = feedback_or!(
|
||||||
MaxMapFeedback::new(&edges_feedback_state, &edges_observer),
|
MaxMapFeedback::new(&edges_observer),
|
||||||
MaxMapFeedback::new(&cmps_feedback_state, &cmps_observer),
|
MaxMapFeedback::new(&cmps_observer),
|
||||||
MaxMapFeedback::new(&allocs_feedback_state, &allocs_observer)
|
MaxMapFeedback::new(&allocs_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(
|
&mut feedback,
|
||||||
edges_feedback_state,
|
// Same for objective feedbacks
|
||||||
cmps_feedback_state,
|
&mut objective,
|
||||||
allocs_feedback_state
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -20,7 +20,7 @@ use libafl::{
|
|||||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
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 mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
||||||
|
|
||||||
let mut stages = tuple_list!(calibration, power);
|
let mut stages = tuple_list!(calibration, power);
|
||||||
|
@ -24,7 +24,7 @@ use libafl::{
|
|||||||
events::EventConfig,
|
events::EventConfig,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -143,7 +143,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
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
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||||
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(&opt.output).unwrap(),
|
OnDiskCorpus::new(&opt.output).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -24,7 +24,7 @@ use libafl::{
|
|||||||
events::EventConfig,
|
events::EventConfig,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -141,7 +141,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
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
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { edges_map_from_ptr() };
|
let edges = unsafe { edges_map_from_ptr() };
|
||||||
let edges_observer =
|
let edges_observer =
|
||||||
@ -150,20 +150,17 @@ pub fn libafl_main() {
|
|||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(opt.output.clone()).unwrap(),
|
OnDiskCorpus::new(opt.output.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -24,7 +24,7 @@ use libafl::{
|
|||||||
events::EventConfig,
|
events::EventConfig,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::tui::TuiMonitor,
|
monitors::tui::TuiMonitor,
|
||||||
@ -141,7 +141,7 @@ pub fn libafl_main() {
|
|||||||
|
|
||||||
let monitor = TuiMonitor::new("Test fuzzer on libpng".into(), true);
|
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
|
// Create an observation channel using the coverage map
|
||||||
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
|
||||||
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(&opt.output).unwrap(),
|
OnDiskCorpus::new(&opt.output).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -11,7 +11,7 @@ use libafl::{
|
|||||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
||||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{MapFeedbackState, MaxMapFeedback, ReachabilityFeedback},
|
feedbacks::{MaxMapFeedback, ReachabilityFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -75,14 +75,11 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
|
|||||||
let reachability_observer =
|
let reachability_observer =
|
||||||
unsafe { StdMapObserver::new_from_ptr("png.c", __libafl_target_list, TARGET_SIZE) };
|
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
|
// 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
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -12,7 +12,7 @@ use libafl::{
|
|||||||
events::{setup_restarting_mgr_std, EventConfig},
|
events::{setup_restarting_mgr_std, EventConfig},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
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 = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -25,7 +25,7 @@ use libafl::{
|
|||||||
command::CommandConfigurator, inprocess::InProcessExecutor, ExitKind, ShadowExecutor,
|
command::CommandConfigurator, inprocess::InProcessExecutor, ExitKind, ShadowExecutor,
|
||||||
},
|
},
|
||||||
feedback_or,
|
feedback_or,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes, Input},
|
inputs::{BytesInput, HasTargetBytes, Input},
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -116,20 +116,18 @@ fn fuzz(
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
)
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
).unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
println!("We're a client, let's fuzz :)");
|
||||||
|
@ -7,7 +7,7 @@ use libafl::{
|
|||||||
corpus::{InMemoryCorpus, OnDiskCorpus},
|
corpus::{InMemoryCorpus, OnDiskCorpus},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandPrintablesGenerator,
|
generators::RandPrintablesGenerator,
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -41,14 +41,11 @@ fn input_generator() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -60,9 +57,12 @@ fn input_generator() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -12,7 +12,7 @@ use libafl::{
|
|||||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase},
|
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase},
|
||||||
events::SimpleEventManager,
|
events::SimpleEventManager,
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback},
|
||||||
fuzzer::StdFuzzer,
|
fuzzer::StdFuzzer,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::SimpleMonitor,
|
monitors::SimpleMonitor,
|
||||||
@ -36,14 +36,11 @@ pub fn main() {
|
|||||||
// Create an observation channel using the signals map
|
// Create an observation channel using the signals map
|
||||||
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
|
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
|
// 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
|
// 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
|
// create a State from scratch
|
||||||
let mut state = StdState::new(
|
let mut state = StdState::new(
|
||||||
@ -55,9 +52,12 @@ pub fn main() {
|
|||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
);
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// The Monitor trait define how the fuzzer stats are reported to the user
|
// The Monitor trait define how the fuzzer stats are reported to the user
|
||||||
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
let monitor = SimpleMonitor::new(|s| println!("{}", s));
|
||||||
|
@ -17,7 +17,7 @@ use libafl::{
|
|||||||
events::EventConfig,
|
events::EventConfig,
|
||||||
executors::{ExitKind, TimeoutExecutor},
|
executors::{ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -50,7 +50,7 @@ pub fn fuzz() {
|
|||||||
let broker_port = 1337;
|
let broker_port = 1337;
|
||||||
let cores = Cores::from_cmdline("0-11").unwrap();
|
let cores = Cores::from_cmdline("0-11").unwrap();
|
||||||
let corpus_dirs = [PathBuf::from("./corpus")];
|
let corpus_dirs = [PathBuf::from("./corpus")];
|
||||||
let objective_dir = PathBuf::from("./crashes");
|
let mut objective_dir = PathBuf::from("./crashes");
|
||||||
|
|
||||||
// Initialize QEMU
|
// Initialize QEMU
|
||||||
env::remove_var("LD_LIBRARY_PATH");
|
env::remove_var("LD_LIBRARY_PATH");
|
||||||
@ -120,20 +120,17 @@ pub fn fuzz() {
|
|||||||
// Create an observation channel to keep track of the execution time
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir.clone()).unwrap(),
|
OnDiskCorpus::new(objective_dir.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// A minimization+queue policy to get testcasess from the corpus
|
// A minimization+queue policy to get testcasess from the corpus
|
||||||
|
@ -12,15 +12,15 @@ use libafl::{
|
|||||||
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::StdFuzzer,
|
||||||
inputs::HasTargetBytes,
|
inputs::HasTargetBytes,
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||||
schedulers::{powersched::PowerSchedule, PowerQueueScheduler},
|
schedulers::{powersched::PowerSchedule, PowerQueueScheduler},
|
||||||
stages::{calibrate::CalibrationStage, power::StdPowerMutationalStage},
|
stages::{calibrate::CalibrationStage, power::StdPowerMutationalStage},
|
||||||
state::{HasCorpus, StdState},
|
state::{HasCorpus, StdState},
|
||||||
Error,
|
Error, Fuzzer,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM};
|
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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("time");
|
let time_observer = TimeObserver::new("time");
|
||||||
|
|
||||||
// The state of the edges feedback.
|
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
|
||||||
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
|
|
||||||
|
let calibration = CalibrationStage::new(&map_feedback);
|
||||||
|
|
||||||
// Feedback to rate the interestingness of an input
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer),
|
TimeFeedback::new_with_observer(&time_observer),
|
||||||
PacketLenFeedback::new()
|
PacketLenFeedback::new()
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(objective_dir).unwrap(),
|
OnDiskCorpus::new(objective_dir).unwrap(),
|
||||||
// States of the feedbacks.
|
// States of the feedbacks.
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
// The feedbacks can report the data that should persist in the State.
|
||||||
tuple_list!(feedback_state),
|
&mut feedback,
|
||||||
|
// Same for objective feedbacks
|
||||||
|
&mut objective,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
println!("We're a client, let's fuzz :)");
|
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
|
// Setup a lain mutator with a mutational stage
|
||||||
let mutator = LainMutator::new();
|
let mutator = LainMutator::new();
|
||||||
|
|
||||||
let calibration = CalibrationStage::new(&edges_observer);
|
|
||||||
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
|
||||||
|
|
||||||
let mut stages = tuple_list!(calibration, power);
|
let mut stages = tuple_list!(calibration, power);
|
||||||
|
@ -45,6 +45,7 @@ impl<S> Feedback<PacketData, S> for PacketLenFeedback
|
|||||||
where
|
where
|
||||||
S: HasClientPerfMonitor,
|
S: HasClientPerfMonitor,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
_state: &mut S,
|
||||||
@ -72,11 +73,6 @@ where
|
|||||||
.insert(PacketLenMetadata { length: self.len });
|
.insert(PacketLenMetadata { length: self.len });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn discard_metadata(&mut self, _state: &mut S, _input: &PacketData) -> Result<(), Error> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Named for PacketLenFeedback {
|
impl Named for PacketLenFeedback {
|
||||||
|
@ -13,13 +13,13 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "derive", "llmp_compression", "rand_trait", "fork"]
|
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.
|
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).
|
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`
|
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
|
||||||
introspection = [] # Include performance statistics of the fuzzing pipeline
|
introspection = [] # Include performance statistics of the fuzzing pipeline
|
||||||
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
|
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
|
||||||
python = ["pyo3"]
|
#python = ["pyo3"]
|
||||||
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
|
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
|
||||||
cli = ["clap"] # expose bolts::cli
|
cli = ["clap"] # expose bolts::cli
|
||||||
qemu_cli = ["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
|
postcard = { version = "0.7", features = ["alloc"] } # no_std compatible serde serialization fromat
|
||||||
bincode = {version = "1.3", optional = true }
|
bincode = {version = "1.3", optional = true }
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
ctor = "0.1.20"
|
|
||||||
num_enum = { version = "0.5.4", default-features = false }
|
num_enum = { version = "0.5.4", default-features = false }
|
||||||
typed-builder = "0.9.1" # Implement the builder pattern at compiletime
|
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
|
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"] }
|
intervaltree = { version = "0.2.7", default-features = false, features = ["serde"] }
|
||||||
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
|
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"] }
|
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
|
||||||
miniz_oxide = { version = "0.4.4", optional = true}
|
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 }
|
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
|
*REGISTRY
|
||||||
.deserializers
|
.deserializers
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.expect("Empty types registry")
|
||||||
.get(&id)
|
.get(&id)
|
||||||
.expect("Cannot deserialize an unregistered type")
|
.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>>>,
|
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)]
|
#[allow(unused_qualifications)]
|
||||||
impl NamedSerdeAnyMap {
|
impl NamedSerdeAnyMap {
|
||||||
/// Get an element by name
|
/// Get an element by name
|
||||||
@ -496,15 +505,18 @@ macro_rules! create_serde_registry_for_trait {
|
|||||||
/// Insert an element into this map.
|
/// Insert an element into this map.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_qualifications)]
|
#[allow(unused_qualifications)]
|
||||||
pub fn insert(&mut self, val: Box<dyn $trait_name>, name: &str) {
|
pub fn insert<T>(&mut self, val: T, name: &str)
|
||||||
let id = unpack_type_id((*val).type_id());
|
where
|
||||||
|
T: $trait_name,
|
||||||
|
{
|
||||||
|
let id = unpack_type_id(TypeId::of::<T>());
|
||||||
if !self.map.contains_key(&id) {
|
if !self.map.contains_key(&id) {
|
||||||
self.map.insert(id, HashMap::default());
|
self.map.insert(id, HashMap::default());
|
||||||
}
|
}
|
||||||
self.map
|
self.map
|
||||||
.get_mut(&id)
|
.get_mut(&id)
|
||||||
.unwrap()
|
.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.
|
/// 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);
|
create_serde_registry_for_trait!(serdeany_registry, crate::bolts::serdeany::SerdeAny);
|
||||||
pub use serdeany_registry::*;
|
pub use serdeany_registry::*;
|
||||||
|
|
||||||
/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`]
|
/// Register a `SerdeAny` type in the [`RegistryBuilder`]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_serdeany {
|
macro_rules! register_at_startup {
|
||||||
($struct_name:ident) => {
|
($struct_type:ty) => {
|
||||||
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
|
const _: () = {
|
||||||
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)]
|
|
||||||
#[$crate::ctor]
|
#[$crate::ctor]
|
||||||
fn $struct_name() {
|
fn constructor() {
|
||||||
$crate::bolts::serdeany::RegistryBuilder::register::<$struct_name>();
|
$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"))]
|
#[cfg(not(feature = "std"))]
|
||||||
#[macro_export]
|
#[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 {
|
macro_rules! impl_serdeany {
|
||||||
($struct_name:ident) => {
|
($struct_name:ident < $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ > $(, < $( $opt:tt ),+ >)*) =>
|
||||||
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
|
{
|
||||||
|
impl < $( $lt $( : $clt $(+ $dlt )* )? ),+ >
|
||||||
|
$crate::bolts::serdeany::SerdeAny
|
||||||
|
for $struct_name < $( $lt ),+ >
|
||||||
|
{
|
||||||
fn as_any(&self) -> &dyn ::core::any::Any {
|
fn as_any(&self) -> &dyn ::core::any::Any {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -634,10 +641,37 @@ macro_rules! impl_serdeany {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn as_any_boxed(
|
fn as_any_boxed(
|
||||||
self: ::alloc::boxed::Box<Self>,
|
self: $crate::alloc::boxed::Box<$struct_name < $( $lt ),+ >>,
|
||||||
) -> ::alloc::boxed::Box<dyn ::core::any::Any> {
|
) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
|
||||||
self
|
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};
|
use crate::{inputs::Input, Error};
|
||||||
|
|
||||||
/// Corpus with all current testcases
|
/// 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
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
{
|
{
|
||||||
|
@ -967,7 +967,7 @@ mod tests {
|
|||||||
|
|
||||||
let solutions = InMemoryCorpus::<BytesInput>::new();
|
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();
|
let mut shmem_provider = StdShMemProvider::new().unwrap();
|
||||||
|
|
||||||
|
@ -1682,10 +1682,10 @@ pub mod pybind {
|
|||||||
use pyo3::types::PyBytes;
|
use pyo3::types::PyBytes;
|
||||||
|
|
||||||
macro_rules! define_python_in_process_executor {
|
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::events::pybind::$event_manager_name;
|
||||||
use crate::fuzzer::pybind::$std_fuzzer_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};
|
use crate::state::pybind::{$my_std_state_type_name, $std_state_name};
|
||||||
|
|
||||||
#[pyclass(unsendable, name = $py_name)]
|
#[pyclass(unsendable, name = $py_name)]
|
||||||
@ -1695,7 +1695,7 @@ pub mod pybind {
|
|||||||
/// Rust wrapped OwnedInProcessExecutor object
|
/// Rust wrapped OwnedInProcessExecutor object
|
||||||
pub owned_in_process_executor: OwnedInProcessExecutor<
|
pub owned_in_process_executor: OwnedInProcessExecutor<
|
||||||
BytesInput,
|
BytesInput,
|
||||||
($map_observer_name, ()),
|
($observer_name, ()),
|
||||||
$my_std_state_type_name,
|
$my_std_state_type_name,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
@ -1705,7 +1705,7 @@ pub mod pybind {
|
|||||||
#[new]
|
#[new]
|
||||||
fn new(
|
fn new(
|
||||||
harness: PyObject,
|
harness: PyObject,
|
||||||
py_observer: $map_observer_name,
|
py_observer: $observer_name,
|
||||||
py_fuzzer: &mut $std_fuzzer_name,
|
py_fuzzer: &mut $std_fuzzer_name,
|
||||||
py_state: &mut $std_state_name,
|
py_state: &mut $std_state_name,
|
||||||
py_event_manager: &mut $event_manager_name,
|
py_event_manager: &mut $event_manager_name,
|
||||||
@ -1734,9 +1734,9 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
define_python_in_process_executor!(
|
define_python_in_process_executor!(
|
||||||
PythonOwnedInProcessExecutorI8,
|
PythonOwnedInProcessExecutor,
|
||||||
"OwnedInProcessExecutorI8",
|
"OwnedInProcessExecutor",
|
||||||
MyStdStateI8,
|
PythonStdState,
|
||||||
PythonStdStateI8,
|
PythonStdStateI8,
|
||||||
PythonEventManagerI8,
|
PythonEventManagerI8,
|
||||||
PythonMapObserverI8,
|
PythonMapObserverI8,
|
||||||
|
@ -195,11 +195,11 @@ pub mod pybind {
|
|||||||
|
|
||||||
macro_rules! define_python_executor {
|
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,
|
($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::events::pybind::$event_manager_name;
|
||||||
use crate::executors::inprocess::pybind::$in_process_executor_name;
|
use crate::executors::inprocess::pybind::$in_process_executor_name;
|
||||||
use crate::fuzzer::pybind::$my_std_fuzzer_type_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;
|
use crate::state::pybind::$my_std_state_type_name;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -211,44 +211,37 @@ pub mod pybind {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Executor + HasObservers Trait binding
|
/// Executor + HasObservers Trait binding
|
||||||
pub struct $struct_name_trait {
|
pub struct $struct_name_trait {
|
||||||
executor: $wrapper_name,
|
wrapper: $wrapper_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl $struct_name_trait {
|
impl $struct_name_trait {
|
||||||
fn get_executor(
|
fn unwrap(
|
||||||
&self,
|
&self,
|
||||||
) -> &(impl Executor<
|
) -> &(impl Executor<
|
||||||
$event_manager_name,
|
$event_manager_name,
|
||||||
BytesInput,
|
BytesInput,
|
||||||
$my_std_state_type_name,
|
$my_std_state_type_name,
|
||||||
$my_std_fuzzer_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 {
|
unsafe {
|
||||||
match self.executor {
|
match self.wrapper {
|
||||||
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
|
$wrapper_name::OwnedInProcess(py_wrapper) => &(*py_wrapper).upcast(),
|
||||||
&(*py_owned_inprocess_executor).owned_in_process_executor
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_mut_executor(
|
fn unwrap_mut(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> &mut (impl Executor<
|
) -> &mut (impl Executor<
|
||||||
$event_manager_name,
|
$event_manager_name,
|
||||||
BytesInput,
|
BytesInput,
|
||||||
$my_std_state_type_name,
|
$my_std_state_type_name,
|
||||||
$my_std_fuzzer_type_name,
|
$my_std_fuzzer_type_name,
|
||||||
> + HasObservers<
|
> + HasObservers<BytesInput, ($observer_name, ()), $my_std_state_type_name>) {
|
||||||
BytesInput,
|
|
||||||
($map_observer_name, ()),
|
|
||||||
$my_std_state_type_name,
|
|
||||||
>) {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.executor {
|
match self.wrapper {
|
||||||
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
|
$wrapper_name::OwnedInProcess(py_wrapper) => {
|
||||||
&mut (*py_owned_inprocess_executor).owned_in_process_executor
|
&mut (*py_wrapper).upcast_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,20 +255,20 @@ pub mod pybind {
|
|||||||
owned_inprocess_executor: &mut $in_process_executor_name,
|
owned_inprocess_executor: &mut $in_process_executor_name,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
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]
|
// #[inline]
|
||||||
fn observers(&self) -> &($map_observer_name, ()) {
|
fn observers(&self) -> &($observer_name, ()) {
|
||||||
self.get_executor().observers()
|
self.unwrap().observers()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observers_mut(&mut self) -> &mut ($map_observer_name, ()) {
|
fn observers_mut(&mut self) -> &mut ($observer_name, ()) {
|
||||||
self.get_mut_executor().observers_mut()
|
self.unwrap_mut().observers_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,112 +288,26 @@ pub mod pybind {
|
|||||||
mgr: &mut $event_manager_name,
|
mgr: &mut $event_manager_name,
|
||||||
input: &BytesInput,
|
input: &BytesInput,
|
||||||
) -> Result<ExitKind, Error> {
|
) -> Result<ExitKind, Error> {
|
||||||
self.get_mut_executor()
|
self.unwrap_mut().run_target(fuzzer, state, mgr, input)
|
||||||
.run_target(fuzzer, state, mgr, input)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
define_python_executor!(
|
define_python_executor!(
|
||||||
PythonExecutorI8,
|
PythonExecutor,
|
||||||
"ExecutorI8",
|
"Executor",
|
||||||
PythonExecutorWrapperI8,
|
PythonExecutorWrapper,
|
||||||
MyStdStateI8,
|
PythonStdState,
|
||||||
MyStdFuzzerI8,
|
PythonStdFuzzer,
|
||||||
PythonEventManagerI8,
|
PythonEventManager,
|
||||||
PythonOwnedInProcessExecutorI8,
|
PythonOwnedInProcessExecutor,
|
||||||
PythonMapObserverI8
|
PythonObserver
|
||||||
);
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Register the classes to the python module
|
/// Register the classes to the python module
|
||||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<PythonExecutorI8>()?;
|
m.add_class::<PythonExecutor>()?;
|
||||||
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>()?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,24 +7,24 @@ use alloc::{
|
|||||||
use core::ops::{BitAnd, BitOr};
|
use core::ops::{BitAnd, BitOr};
|
||||||
use core::{fmt::Debug, marker::PhantomData};
|
use core::{fmt::Debug, marker::PhantomData};
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::{
|
bolts::{tuples::Named, AsMutSlice, AsRefIterator, AsSlice, HasRefCnt},
|
||||||
tuples::{MatchName, Named},
|
|
||||||
AsMutSlice, AsRefIterator, AsSlice, HasRefCnt,
|
|
||||||
},
|
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
events::{Event, EventFirer},
|
events::{Event, EventFirer},
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{Feedback, FeedbackState},
|
feedbacks::{Feedback, HasObserverName},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
monitors::UserStats,
|
monitors::UserStats,
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::{MapObserver, ObserversTuple},
|
||||||
state::{HasClientPerfMonitor, HasFeedbackStates, HasMetadata},
|
state::{HasClientPerfMonitor, HasMetadata, HasNamedMetadata},
|
||||||
Error,
|
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``.
|
/// 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>;
|
pub type AflMapFeedback<I, O, S, T> = MapFeedback<I, DifferentIsNovel, O, OrReducer, S, T>;
|
||||||
|
|
||||||
@ -272,71 +272,44 @@ impl MapNoveltiesMetadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The state of [`MapFeedback`]
|
/// The state of [`MapFeedback`]
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
#[serde(bound = "T: DeserializeOwned")]
|
||||||
pub struct MapFeedbackState<T>
|
pub struct MapFeedbackMetadata<T>
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + Serialize,
|
T: Default + Copy + 'static + Serialize,
|
||||||
{
|
{
|
||||||
/// Contains information about untouched entries
|
/// Contains information about untouched entries
|
||||||
pub history_map: Vec<T>,
|
pub history_map: Vec<T>,
|
||||||
/// Name identifier of this instance
|
|
||||||
pub name: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> FeedbackState for MapFeedbackState<T>
|
crate::impl_serdeany!(
|
||||||
where
|
MapFeedbackMetadata<T: Debug + Default + Copy + 'static + Serialize + DeserializeOwned>,
|
||||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
<u8>,<u16>,<u32>,<u64>,<i8>,<i16>,<i32>,<i64>,<f32>,<f64>,<bool>,<char>
|
||||||
{
|
);
|
||||||
fn reset(&mut self) -> Result<(), Error> {
|
|
||||||
self.history_map.iter_mut().for_each(|x| *x = T::default());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Named for MapFeedbackState<T>
|
impl<T> MapFeedbackMetadata<T>
|
||||||
where
|
where
|
||||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
|
T: Default + Copy + 'static + Serialize + DeserializeOwned,
|
||||||
{
|
{
|
||||||
#[inline]
|
/// Create new `MapFeedbackMetadata`
|
||||||
fn name(&self) -> &str {
|
|
||||||
self.name.as_str()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> MapFeedbackState<T>
|
|
||||||
where
|
|
||||||
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
|
|
||||||
{
|
|
||||||
/// Create new `MapFeedbackState`
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(name: &'static str, map_size: usize) -> Self {
|
pub fn new(map_size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
history_map: vec![T::default(); map_size],
|
history_map: vec![T::default(); map_size],
|
||||||
name: name.to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create new `MapFeedbackState` for the observer type.
|
/// Create new `MapFeedbackMetadata` using a name and a map.
|
||||||
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.
|
|
||||||
/// The map can be shared.
|
/// The map can be shared.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_history_map(name: &'static str, history_map: Vec<T>) -> Self {
|
pub fn with_history_map(history_map: Vec<T>) -> Self {
|
||||||
Self {
|
Self { history_map }
|
||||||
history_map,
|
|
||||||
name: name.to_string(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct MapFeedback<I, N, O, R, S, T>
|
pub struct MapFeedback<I, N, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
O: MapObserver<Entry = T>,
|
O: MapObserver<Entry = T>,
|
||||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
S: HasFeedbackStates,
|
S: HasNamedMetadata,
|
||||||
{
|
{
|
||||||
/// Indexes used in the last observation
|
/// Indexes used in the last observation
|
||||||
indexes: Option<Vec<usize>>,
|
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>
|
impl<I, N, O, R, S, T> Feedback<I, S> for MapFeedback<I, N, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
O: MapObserver<Entry = T>,
|
O: MapObserver<Entry = T>,
|
||||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
I: Input,
|
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)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -393,11 +371,14 @@ where
|
|||||||
let initial = observer.initial();
|
let initial = observer.initial();
|
||||||
|
|
||||||
let map_state = state
|
let map_state = state
|
||||||
.feedback_states_mut()
|
.named_metadata_mut()
|
||||||
.match_name_mut::<MapFeedbackState<T>>(&self.name)
|
.get_mut::<MapFeedbackMetadata<T>>(&self.name)
|
||||||
.unwrap();
|
.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());
|
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>
|
impl<I, N, O, R, S, T> Named for MapFeedback<I, N, O, R, S, T>
|
||||||
where
|
where
|
||||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
O: MapObserver<Entry = T>,
|
O: MapObserver<Entry = T>,
|
||||||
for<'it> O: AsRefIterator<'it, Item = T>,
|
for<'it> O: AsRefIterator<'it, Item = T>,
|
||||||
S: HasFeedbackStates,
|
S: HasNamedMetadata,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
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
|
where
|
||||||
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
|
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
|
||||||
R: Reducer<T>,
|
R: Reducer<T>,
|
||||||
N: IsNovel<T>,
|
N: IsNovel<T>,
|
||||||
O: MapObserver<Entry = T>,
|
O: MapObserver<Entry = T>,
|
||||||
for<'it> O: AsRefIterator<'it, Item = 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`
|
/// Create new `MapFeedback`
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(feedback_state: &MapFeedbackState<T>, map_observer: &O) -> Self {
|
pub fn new(map_observer: &O) -> Self {
|
||||||
Self {
|
Self {
|
||||||
indexes: None,
|
indexes: None,
|
||||||
novelties: None,
|
novelties: None,
|
||||||
name: feedback_state.name().to_string(),
|
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
|
||||||
observer_name: map_observer.name().to_string(),
|
observer_name: map_observer.name().to_string(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
@ -507,16 +503,11 @@ where
|
|||||||
|
|
||||||
/// Create new `MapFeedback` specifying if it must track indexes of used entries and/or novelties
|
/// Create new `MapFeedback` specifying if it must track indexes of used entries and/or novelties
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_tracking(
|
pub fn new_tracking(map_observer: &O, track_indexes: bool, track_novelties: bool) -> Self {
|
||||||
feedback_state: &MapFeedbackState<T>,
|
|
||||||
map_observer: &O,
|
|
||||||
track_indexes: bool,
|
|
||||||
track_novelties: bool,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
indexes: if track_indexes { Some(vec![]) } else { None },
|
indexes: if track_indexes { Some(vec![]) } else { None },
|
||||||
novelties: if track_novelties { 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(),
|
observer_name: map_observer.name().to_string(),
|
||||||
phantom: PhantomData,
|
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")]
|
#[cfg(feature = "python")]
|
||||||
/// Map Feedback Python bindings
|
/// Map Feedback Python bindings
|
||||||
pub mod pybind {
|
pub mod pybind {
|
||||||
use crate::feedbacks::map::{MapFeedbackState, MaxMapFeedback};
|
use crate::feedbacks::map::{MapFeedbackMetadata, MaxMapFeedback};
|
||||||
use crate::inputs::BytesInput;
|
use crate::inputs::BytesInput;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
@ -688,10 +972,10 @@ pub mod pybind {
|
|||||||
|
|
||||||
#[pyclass(unsendable, name = $map_feedback_state_py_name)]
|
#[pyclass(unsendable, name = $map_feedback_state_py_name)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
/// Python class for MapFeedbackState
|
/// Python class for MapFeedbackMetadata
|
||||||
pub struct $map_feedback_state_struct_name {
|
pub struct $map_feedback_state_struct_name {
|
||||||
/// Rust wrapped MapFeedbackState object
|
/// Rust wrapped MapFeedbackMetadata object
|
||||||
pub map_feedback_state: MapFeedbackState<$datatype>,
|
pub map_feedback_state: MapFeedbackMetadata<$datatype>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
@ -699,7 +983,7 @@ pub mod pybind {
|
|||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
fn with_observer(py_observer: &$map_observer_name) -> Self {
|
fn with_observer(py_observer: &$map_observer_name) -> Self {
|
||||||
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!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateI8,
|
PythonMapFeedbackMetadataI8,
|
||||||
"MapFeedbackStateI8",
|
"MapFeedbackMetadataI8",
|
||||||
PythonMaxMapFeedbackI8,
|
PythonMaxMapFeedbackI8,
|
||||||
"MaxMapFeedbackI8",
|
"MaxMapFeedbackI8",
|
||||||
i8,
|
i8,
|
||||||
@ -750,8 +1034,8 @@ pub mod pybind {
|
|||||||
);
|
);
|
||||||
|
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateI16,
|
PythonMapFeedbackMetadataI16,
|
||||||
"MapFeedbackStateI16",
|
"MapFeedbackMetadataI16",
|
||||||
PythonMaxMapFeedbackI16,
|
PythonMaxMapFeedbackI16,
|
||||||
"MaxMapFeedbackI16",
|
"MaxMapFeedbackI16",
|
||||||
i16,
|
i16,
|
||||||
@ -759,8 +1043,8 @@ pub mod pybind {
|
|||||||
MyStdStateI16
|
MyStdStateI16
|
||||||
);
|
);
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateI32,
|
PythonMapFeedbackMetadataI32,
|
||||||
"MapFeedbackStateI32",
|
"MapFeedbackMetadataI32",
|
||||||
PythonMaxMapFeedbackI32,
|
PythonMaxMapFeedbackI32,
|
||||||
"MaxMapFeedbackI32",
|
"MaxMapFeedbackI32",
|
||||||
i32,
|
i32,
|
||||||
@ -768,8 +1052,8 @@ pub mod pybind {
|
|||||||
MyStdStateI32
|
MyStdStateI32
|
||||||
);
|
);
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateI64,
|
PythonMapFeedbackMetadataI64,
|
||||||
"MapFeedbackStateI64",
|
"MapFeedbackMetadataI64",
|
||||||
PythonMaxMapFeedbackI64,
|
PythonMaxMapFeedbackI64,
|
||||||
"MaxMapFeedbackI64",
|
"MaxMapFeedbackI64",
|
||||||
i64,
|
i64,
|
||||||
@ -778,8 +1062,8 @@ pub mod pybind {
|
|||||||
);
|
);
|
||||||
|
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateU8,
|
PythonMapFeedbackMetadataU8,
|
||||||
"MapFeedbackStateU8",
|
"MapFeedbackMetadataU8",
|
||||||
PythonMaxMapFeedbackU8,
|
PythonMaxMapFeedbackU8,
|
||||||
"MaxMapFeedbackU8",
|
"MaxMapFeedbackU8",
|
||||||
u8,
|
u8,
|
||||||
@ -788,8 +1072,8 @@ pub mod pybind {
|
|||||||
);
|
);
|
||||||
|
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateU16,
|
PythonMapFeedbackMetadataU16,
|
||||||
"MapFeedbackStateU16",
|
"MapFeedbackMetadataU16",
|
||||||
PythonMaxMapFeedbackU16,
|
PythonMaxMapFeedbackU16,
|
||||||
"MaxMapFeedbackU16",
|
"MaxMapFeedbackU16",
|
||||||
u16,
|
u16,
|
||||||
@ -797,8 +1081,8 @@ pub mod pybind {
|
|||||||
MyStdStateU16
|
MyStdStateU16
|
||||||
);
|
);
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateU32,
|
PythonMapFeedbackMetadataU32,
|
||||||
"MapFeedbackStateU32",
|
"MapFeedbackMetadataU32",
|
||||||
PythonMaxMapFeedbackU32,
|
PythonMaxMapFeedbackU32,
|
||||||
"MaxMapFeedbackU32",
|
"MaxMapFeedbackU32",
|
||||||
u32,
|
u32,
|
||||||
@ -806,8 +1090,8 @@ pub mod pybind {
|
|||||||
MyStdStateU32
|
MyStdStateU32
|
||||||
);
|
);
|
||||||
define_python_map_feedback!(
|
define_python_map_feedback!(
|
||||||
PythonMapFeedbackStateU64,
|
PythonMapFeedbackMetadataU64,
|
||||||
"MapFeedbackStateU64",
|
"MapFeedbackMetadataU64",
|
||||||
PythonMaxMapFeedbackU64,
|
PythonMaxMapFeedbackU64,
|
||||||
"MaxMapFeedbackU64",
|
"MaxMapFeedbackU64",
|
||||||
u64,
|
u64,
|
||||||
@ -817,15 +1101,15 @@ pub mod pybind {
|
|||||||
|
|
||||||
/// Register the classes to the python module
|
/// Register the classes to the python module
|
||||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<PythonMapFeedbackStateI8>()?;
|
m.add_class::<PythonMapFeedbackMetadataI8>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateI16>()?;
|
m.add_class::<PythonMapFeedbackMetadataI16>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateI32>()?;
|
m.add_class::<PythonMapFeedbackMetadataI32>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateI64>()?;
|
m.add_class::<PythonMapFeedbackMetadataI64>()?;
|
||||||
|
|
||||||
m.add_class::<PythonMapFeedbackStateU8>()?;
|
m.add_class::<PythonMapFeedbackMetadataU8>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateU16>()?;
|
m.add_class::<PythonMapFeedbackMetadataU16>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateU32>()?;
|
m.add_class::<PythonMapFeedbackMetadataU32>()?;
|
||||||
m.add_class::<PythonMapFeedbackStateU64>()?;
|
m.add_class::<PythonMapFeedbackMetadataU64>()?;
|
||||||
|
|
||||||
m.add_class::<PythonMaxMapFeedbackI8>()?;
|
m.add_class::<PythonMaxMapFeedbackI8>()?;
|
||||||
m.add_class::<PythonMaxMapFeedbackI16>()?;
|
m.add_class::<PythonMaxMapFeedbackI16>()?;
|
||||||
|
@ -16,7 +16,7 @@ pub mod new_hash_feedback;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use new_hash_feedback::NewHashFeedback;
|
pub use new_hash_feedback::NewHashFeedback;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub use new_hash_feedback::NewHashFeedbackState;
|
pub use new_hash_feedback::NewHashFeedbackMetadata;
|
||||||
|
|
||||||
#[cfg(feature = "nautilus")]
|
#[cfg(feature = "nautilus")]
|
||||||
pub mod nautilus;
|
pub mod nautilus;
|
||||||
@ -27,7 +27,7 @@ use alloc::string::{String, ToString};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchName, Named},
|
bolts::tuples::Named,
|
||||||
corpus::Testcase,
|
corpus::Testcase,
|
||||||
events::EventFirer,
|
events::EventFirer,
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
@ -51,6 +51,12 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor,
|
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
|
/// `is_interesting ` return if an input is worth the addition to the corpus
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
@ -116,36 +122,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [`FeedbackState`] is the data associated with a [`Feedback`] that must persist as part
|
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
|
||||||
/// of the fuzzer State
|
pub trait HasObserverName {
|
||||||
pub trait FeedbackState: Named + Serialize + serde::de::DeserializeOwned + Debug {
|
/// The name associated with the observer
|
||||||
/// Reset the internal state
|
fn observer_name(&self) -> &str;
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A combined feedback consisting of multiple [`Feedback`]s
|
/// A combined feedback consisting of multiple [`Feedback`]s
|
||||||
@ -207,6 +187,12 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor + Debug,
|
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)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -596,6 +582,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor,
|
S: HasClientPerfMonitor,
|
||||||
{
|
{
|
||||||
|
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
|
||||||
|
self.first.init_state(state)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::wrong_self_convention)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&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
|
//! 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 hashbrown::HashSet;
|
||||||
use num_traits::PrimInt;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::tuples::{MatchName, Named},
|
bolts::tuples::Named,
|
||||||
events::EventFirer,
|
events::EventFirer,
|
||||||
executors::ExitKind,
|
executors::ExitKind,
|
||||||
feedbacks::{Feedback, FeedbackState},
|
feedbacks::{Feedback, HasObserverName},
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{ObserverWithHashField, ObserversTuple},
|
observers::{ObserverWithHashField, ObserversTuple},
|
||||||
state::{HasClientPerfMonitor, HasFeedbackStates},
|
state::{HasClientPerfMonitor, HasNamedMetadata},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// The prefix of the metadata names
|
||||||
|
pub const NEWHASHFEEDBACK_PREFIX: &str = "newhashfeedback_metadata_";
|
||||||
|
|
||||||
/// A state that implements this trait has a hash set
|
/// A state that implements this trait has a hash set
|
||||||
pub trait HashSetState<T> {
|
pub trait HashSetState<T> {
|
||||||
/// creates a new instance with a specific hashset
|
/// 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
|
/// updates the `hash_set` with the given value
|
||||||
fn update_hash_set(&mut self, value: T) -> Result<bool, Error>;
|
fn update_hash_set(&mut self, value: T) -> Result<bool, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The state of [`NewHashFeedback`]
|
/// The state of [`NewHashFeedback`]
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "T: serde::de::DeserializeOwned")]
|
pub struct NewHashFeedbackMetadata {
|
||||||
pub struct NewHashFeedbackState<T>
|
|
||||||
where
|
|
||||||
T: PrimInt + Default + Copy + 'static + Serialize + Hash + Debug,
|
|
||||||
{
|
|
||||||
/// Contains information about untouched entries
|
/// Contains information about untouched entries
|
||||||
pub hash_set: HashSet<T>,
|
pub hash_set: HashSet<u64>,
|
||||||
/// Name identifier of this instance
|
|
||||||
pub name: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> FeedbackState for NewHashFeedbackState<T>
|
#[rustfmt::skip]
|
||||||
where
|
crate::impl_serdeany!(NewHashFeedbackMetadata);
|
||||||
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
|
|
||||||
{
|
impl NewHashFeedbackMetadata {
|
||||||
fn reset(&mut self) -> Result<(), Error> {
|
/// 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();
|
self.hash_set.clear();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Named for NewHashFeedbackState<T>
|
impl HashSetState<u64> for NewHashFeedbackMetadata {
|
||||||
where
|
/// Create new [`NewHashFeedbackMetadata`] using a name and a hash set.
|
||||||
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`]
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(name: &'static str) -> Self {
|
fn with_hash_set(hash_set: HashSet<u64>) -> Self {
|
||||||
Self {
|
Self { hash_set }
|
||||||
hash_set: HashSet::<T>::new(),
|
|
||||||
name: name.to_string(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new [`NewHashFeedbackState`] for an observer that implements [`ObserverWithHashField`]
|
fn update_hash_set(&mut self, value: u64) -> Result<bool, Error> {
|
||||||
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> {
|
|
||||||
let r = self.hash_set.insert(value);
|
let r = self.hash_set.insert(value);
|
||||||
// println!("Got r={}, the hashset is {:?}", r, &self.hash_set);
|
// println!("Got r={}, the hashset is {:?}", r, &self.hash_set);
|
||||||
Ok(r)
|
Ok(r)
|
||||||
@ -102,7 +68,7 @@ where
|
|||||||
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
|
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct NewHashFeedback<O> {
|
pub struct NewHashFeedback<O> {
|
||||||
feedback_name: String,
|
name: String,
|
||||||
observer_name: String,
|
observer_name: String,
|
||||||
o_type: PhantomData<O>,
|
o_type: PhantomData<O>,
|
||||||
}
|
}
|
||||||
@ -110,13 +76,18 @@ pub struct NewHashFeedback<O> {
|
|||||||
impl<I, S, O> Feedback<I, S> for NewHashFeedback<O>
|
impl<I, S, O> Feedback<I, S> for NewHashFeedback<O>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
S: HasClientPerfMonitor + HasFeedbackStates,
|
S: HasClientPerfMonitor + HasNamedMetadata,
|
||||||
O: ObserverWithHashField + Named + Debug,
|
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)]
|
#[allow(clippy::wrong_self_convention)]
|
||||||
fn is_interesting<EM, OT>(
|
fn is_interesting<EM, OT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
_state: &mut S,
|
state: &mut S,
|
||||||
_manager: &mut EM,
|
_manager: &mut EM,
|
||||||
_input: &I,
|
_input: &I,
|
||||||
observers: &OT,
|
observers: &OT,
|
||||||
@ -130,9 +101,9 @@ where
|
|||||||
.match_name::<O>(&self.observer_name)
|
.match_name::<O>(&self.observer_name)
|
||||||
.expect("A NewHashFeedback needs a BacktraceObserver");
|
.expect("A NewHashFeedback needs a BacktraceObserver");
|
||||||
|
|
||||||
let backtrace_state = _state
|
let backtrace_state = state
|
||||||
.feedback_states_mut()
|
.named_metadata_mut()
|
||||||
.match_name_mut::<NewHashFeedbackState<u64>>(&self.observer_name)
|
.get_mut::<NewHashFeedbackMetadata>(&self.name)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
match observer.hash() {
|
match observer.hash() {
|
||||||
@ -153,7 +124,14 @@ where
|
|||||||
impl<O> Named for NewHashFeedback<O> {
|
impl<O> Named for NewHashFeedback<O> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
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
|
where
|
||||||
O: ObserverWithHashField + Named + Debug,
|
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.
|
/// Setting an observer name that doesn't exist would eventually trigger a panic.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(feedback_name: &str, observer_name: &str) -> Self {
|
pub fn with_names(name: &str, observer_name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
feedback_name: feedback_name.to_string(),
|
name: name.to_string(),
|
||||||
observer_name: observer_name.to_string(),
|
observer_name: observer_name.to_string(),
|
||||||
o_type: PhantomData,
|
o_type: PhantomData,
|
||||||
}
|
}
|
||||||
@ -174,9 +152,9 @@ where
|
|||||||
|
|
||||||
/// Returns a new [`NewHashFeedback`].
|
/// Returns a new [`NewHashFeedback`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new_with_observer(feedback_name: &str, observer: &O) -> Self {
|
pub fn new(observer: &O) -> Self {
|
||||||
Self {
|
Self {
|
||||||
feedback_name: feedback_name.to_string(),
|
name: NEWHASHFEEDBACK_PREFIX.to_string() + observer.name(),
|
||||||
observer_name: observer.name().to_string(),
|
observer_name: observer.name().to_string(),
|
||||||
o_type: PhantomData,
|
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]
|
#[macro_use]
|
||||||
extern crate alloc;
|
pub extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate static_assertions;
|
extern crate static_assertions;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "ctor")]
|
||||||
pub use ctor::ctor;
|
pub use ctor::ctor;
|
||||||
|
|
||||||
// Re-export derive(SerdeAny)
|
// Re-export derive(SerdeAny)
|
||||||
@ -407,8 +407,10 @@ mod tests {
|
|||||||
rand,
|
rand,
|
||||||
corpus,
|
corpus,
|
||||||
InMemoryCorpus::<BytesInput>::new(),
|
InMemoryCorpus::<BytesInput>::new(),
|
||||||
tuple_list!(),
|
&mut (),
|
||||||
);
|
&mut (),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let monitor = SimpleMonitor::new(|s| {
|
let monitor = SimpleMonitor::new(|s| {
|
||||||
println!("{}", s);
|
println!("{}", s);
|
||||||
@ -440,7 +442,6 @@ mod tests {
|
|||||||
let state_serialized = postcard::to_allocvec(&state).unwrap();
|
let state_serialized = postcard::to_allocvec(&state).unwrap();
|
||||||
let state_deserialized: StdState<
|
let state_deserialized: StdState<
|
||||||
InMemoryCorpus<BytesInput>,
|
InMemoryCorpus<BytesInput>,
|
||||||
(),
|
|
||||||
BytesInput,
|
BytesInput,
|
||||||
StdRand,
|
StdRand,
|
||||||
InMemoryCorpus<BytesInput>,
|
InMemoryCorpus<BytesInput>,
|
||||||
|
@ -1230,7 +1230,8 @@ mod tests {
|
|||||||
.add(BytesInput::new(vec![0x42; 0x1337]).into())
|
.add(BytesInput::new(vec![0x42; 0x1337]).into())
|
||||||
.unwrap();
|
.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();
|
let mut mutations = test_mutations();
|
||||||
for _ in 0..2 {
|
for _ in 0..2 {
|
||||||
|
@ -447,7 +447,8 @@ mod tests {
|
|||||||
let testcase = corpus.get(0).expect("Corpus did not contain entries");
|
let testcase = corpus.get(0).expect("Corpus did not contain entries");
|
||||||
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
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);
|
rand.set_seed(5);
|
||||||
|
|
||||||
@ -474,7 +475,8 @@ mod tests {
|
|||||||
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
|
||||||
let input_prior = input.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());
|
let mut havoc = StdScheduledMutator::new(havoc_mutations());
|
||||||
|
|
||||||
|
@ -1487,6 +1487,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `MapObserver` Python bindings
|
/// `MapObserver` Python bindings
|
||||||
#[cfg(feature = "python")]
|
#[cfg(feature = "python")]
|
||||||
pub mod pybind {
|
pub mod pybind {
|
||||||
@ -1504,7 +1505,7 @@ pub mod pybind {
|
|||||||
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
|
||||||
pub struct $struct_name {
|
pub struct $struct_name {
|
||||||
/// Rust wrapped OwnedMapObserver object
|
/// Rust wrapped OwnedMapObserver object
|
||||||
pub owned_map_observer: OwnedMapObserver<$datatype>,
|
pub inner: OwnedMapObserver<$datatype>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pymethods]
|
#[pymethods]
|
||||||
@ -1513,10 +1514,7 @@ pub mod pybind {
|
|||||||
fn new(name: String, map: Vec<$datatype>) -> Self {
|
fn new(name: String, map: Vec<$datatype>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
//TODO: Not leak memory
|
//TODO: Not leak memory
|
||||||
owned_map_observer: OwnedMapObserver::new(
|
inner: OwnedMapObserver::new(Box::leak(name.into_boxed_str()), map),
|
||||||
Box::leak(name.into_boxed_str()),
|
|
||||||
map,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1531,15 +1529,49 @@ pub mod pybind {
|
|||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
/// MapObserver + Observer Trait binding
|
/// MapObserver + Observer Trait binding
|
||||||
pub struct $struct_name_trait {
|
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]
|
#[pymethods]
|
||||||
impl $struct_name_trait {
|
impl $struct_name_trait {
|
||||||
#[staticmethod]
|
#[staticmethod]
|
||||||
fn new_from_owned(owned_map_observer: $struct_name) -> Self {
|
fn new_from_owned(owned_map: $struct_name) -> Self {
|
||||||
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>;
|
type IntoIter = Iter<'it, $datatype>;
|
||||||
|
|
||||||
fn as_ref_iter(&'it self) -> Self::IntoIter {
|
fn as_ref_iter(&'it self) -> Self::IntoIter {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_ref_iter(),
|
||||||
map_observer.owned_map_observer.as_ref_iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1562,10 +1592,8 @@ pub mod pybind {
|
|||||||
type IntoIter = IterMut<'it, $datatype>;
|
type IntoIter = IterMut<'it, $datatype>;
|
||||||
|
|
||||||
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
|
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
|
||||||
match &mut self.map_observer {
|
match &mut self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_mut_iter(),
|
||||||
map_observer.owned_map_observer.as_mut_iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1575,71 +1603,57 @@ pub mod pybind {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, idx: usize) -> &$datatype {
|
fn get(&self, idx: usize) -> &$datatype {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner.get(idx),
|
||||||
&map_observer.owned_map_observer.get(idx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
|
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
|
||||||
match &mut self.map_observer {
|
match &mut self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.get_mut(idx),
|
||||||
map_observer.owned_map_observer.get_mut(idx)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn usable_count(&self) -> usize {
|
fn usable_count(&self) -> usize {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.wrapper.usable_count(),
|
||||||
map_observer.owned_map_observer.usable_count()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash(&self) -> u64 {
|
fn hash(&self) -> u64 {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.hash(),
|
||||||
map_observer.owned_map_observer.hash()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn initial(&self) -> $datatype {
|
fn initial(&self) -> $datatype {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial(),
|
||||||
map_observer.owned_map_observer.initial()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn initial_mut(&mut self) -> &mut $datatype {
|
fn initial_mut(&mut self) -> &mut $datatype {
|
||||||
match &mut self.map_observer {
|
match &mut self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial_mut(),
|
||||||
map_observer.owned_map_observer.initial_mut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_initial(&mut self, initial: $datatype) {
|
fn set_initial(&mut self, initial: $datatype) {
|
||||||
match &mut self.map_observer {
|
match &mut self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => {
|
||||||
map_observer.owned_map_observer.set_initial(initial);
|
py_wrapper.inner.set_initial(initial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_vec(&self) -> Vec<$datatype> {
|
fn to_vec(&self) -> Vec<$datatype> {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.to_vec(),
|
||||||
map_observer.owned_map_observer.to_vec()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1647,10 +1661,8 @@ pub mod pybind {
|
|||||||
impl Named for $struct_name_trait {
|
impl Named for $struct_name_trait {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.name(),
|
||||||
map_observer.owned_map_observer.name()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1658,8 +1670,8 @@ pub mod pybind {
|
|||||||
impl HasLen for $struct_name_trait {
|
impl HasLen for $struct_name_trait {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
match &self.map_observer {
|
match &self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => map_observer.owned_map_observer.len(),
|
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1670,9 +1682,9 @@ pub mod pybind {
|
|||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
|
||||||
match &mut self.map_observer {
|
match &mut self.wrapper {
|
||||||
$wrapper_name::Owned(map_observer) => {
|
$wrapper_name::Owned(py_wrapper) => {
|
||||||
map_observer.owned_map_observer.pre_exec(_state, _input)
|
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(feature = "std")]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -188,7 +188,8 @@ mod tests {
|
|||||||
let idx1 = corpus.add(t1).unwrap();
|
let idx1 = corpus.add(t1).unwrap();
|
||||||
let idx2 = corpus.add(t2).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(), idx1).unwrap();
|
||||||
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
|
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
|
||||||
let next_idx1 = scheduler.next(&mut state).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"))
|
OnDiskCorpus::<BytesInput>::new(PathBuf::from("target/.test/fancy/objective/path"))
|
||||||
.unwrap();
|
.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 next_idx = scheduler.next(&mut state).unwrap();
|
||||||
let filename = state
|
let filename = state
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
|
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
bolts::current_time,
|
bolts::{current_time, tuples::Named, AsRefIterator},
|
||||||
bolts::tuples::MatchName,
|
|
||||||
corpus::{Corpus, SchedulerTestcaseMetaData},
|
corpus::{Corpus, SchedulerTestcaseMetaData},
|
||||||
events::{EventFirer, LogSeverity},
|
events::{EventFirer, LogSeverity},
|
||||||
executors::{Executor, ExitKind, HasObservers},
|
executors::{Executor, ExitKind, HasObservers},
|
||||||
feedbacks::MapFeedbackState,
|
feedbacks::{
|
||||||
|
map::{IsNovel, MapFeedback, MapFeedbackMetadata, Reducer},
|
||||||
|
HasObserverName,
|
||||||
|
},
|
||||||
fuzzer::Evaluator,
|
fuzzer::Evaluator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
observers::{MapObserver, ObserversTuple},
|
observers::{MapObserver, ObserversTuple},
|
||||||
schedulers::powersched::SchedulerMetadata,
|
schedulers::powersched::SchedulerMetadata,
|
||||||
stages::Stage,
|
stages::Stage,
|
||||||
state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata},
|
state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasNamedMetadata},
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
use alloc::string::{String, ToString};
|
use alloc::string::{String, ToString};
|
||||||
@ -27,9 +29,10 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasCorpus<I> + HasMetadata,
|
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
|
||||||
{
|
{
|
||||||
map_observer_name: String,
|
map_observer_name: String,
|
||||||
|
map_name: String,
|
||||||
stage_max: usize,
|
stage_max: usize,
|
||||||
phantom: PhantomData<(I, O, OT, S)>,
|
phantom: PhantomData<(I, O, OT, S)>,
|
||||||
}
|
}
|
||||||
@ -45,7 +48,7 @@ where
|
|||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
|
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasCorpus<I> + HasMetadata + HasFeedbackStates + HasClientPerfMonitor,
|
S: HasCorpus<I> + HasMetadata + HasClientPerfMonitor + HasNamedMetadata,
|
||||||
Z: Evaluator<E, EM, I, S>,
|
Z: Evaluator<E, EM, I, S>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -147,8 +150,8 @@ where
|
|||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
let history_map = &mut state
|
let history_map = &mut state
|
||||||
.feedback_states_mut()
|
.named_metadata_mut()
|
||||||
.match_name_mut::<MapFeedbackState<O::Entry>>(&self.map_observer_name)
|
.get_mut::<MapFeedbackMetadata<O::Entry>>(&self.map_name)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.history_map;
|
.history_map;
|
||||||
|
|
||||||
@ -222,12 +225,21 @@ where
|
|||||||
I: Input,
|
I: Input,
|
||||||
O: MapObserver,
|
O: MapObserver,
|
||||||
OT: ObserversTuple<I, S>,
|
OT: ObserversTuple<I, S>,
|
||||||
S: HasCorpus<I> + HasMetadata,
|
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
|
||||||
{
|
{
|
||||||
/// Create a new [`CalibrationStage`].
|
/// 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 {
|
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,
|
stage_max: CAL_STAGE_START,
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,11 @@ use std::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
bolts::{
|
bolts::{
|
||||||
rands::Rand,
|
rands::Rand,
|
||||||
serdeany::{SerdeAny, SerdeAnyMap},
|
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
|
||||||
},
|
},
|
||||||
corpus::Corpus,
|
corpus::Corpus,
|
||||||
events::{Event, EventFirer, LogSeverity},
|
events::{Event, EventFirer, LogSeverity},
|
||||||
feedbacks::FeedbackStatesTuple,
|
feedbacks::Feedback,
|
||||||
fuzzer::{Evaluator, ExecuteInputResult},
|
fuzzer::{Evaluator, ExecuteInputResult},
|
||||||
generators::Generator,
|
generators::Generator,
|
||||||
inputs::Input,
|
inputs::Input,
|
||||||
@ -110,15 +110,30 @@ pub trait HasMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for elements offering a feedback
|
/// Trait for elements offering named metadata
|
||||||
pub trait HasFeedbackStates {
|
pub trait HasNamedMetadata {
|
||||||
/// The associated feedback type implementing [`FeedbackStatesTuple`].
|
/// A map, storing all metadata
|
||||||
type FeedbackStates: FeedbackStatesTuple;
|
fn named_metadata(&self) -> &NamedSerdeAnyMap;
|
||||||
/// The feedback states
|
/// A map, storing all metadata (mutable)
|
||||||
fn feedback_states(&self) -> &Self::FeedbackStates;
|
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap;
|
||||||
|
|
||||||
/// The feedback states (mutable)
|
/// Add a metadata to the metadata map
|
||||||
fn feedback_states_mut(&mut self) -> &mut Self::FeedbackStates;
|
#[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
|
/// Trait for the execution counter
|
||||||
@ -141,13 +156,12 @@ pub trait HasStartTime {
|
|||||||
|
|
||||||
/// The state a fuzz run.
|
/// The state a fuzz run.
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
#[serde(bound = "FT: serde::de::DeserializeOwned")]
|
#[serde(bound = "C: serde::Serialize + for<'a> serde::Deserialize<'a>")]
|
||||||
pub struct StdState<C, FT, I, R, SC>
|
pub struct StdState<C, I, R, SC>
|
||||||
where
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// RNG instance
|
/// RNG instance
|
||||||
@ -158,12 +172,12 @@ where
|
|||||||
start_time: Duration,
|
start_time: Duration,
|
||||||
/// The corpus
|
/// The corpus
|
||||||
corpus: C,
|
corpus: C,
|
||||||
/// States of the feedback used to evaluate an input
|
|
||||||
feedback_states: FT,
|
|
||||||
// Solutions corpus
|
// Solutions corpus
|
||||||
solutions: SC,
|
solutions: SC,
|
||||||
/// Metadata stored for this state by one of the components
|
/// Metadata stored for this state by one of the components
|
||||||
metadata: SerdeAnyMap,
|
metadata: SerdeAnyMap,
|
||||||
|
/// Metadata stored with names
|
||||||
|
named_metadata: NamedSerdeAnyMap,
|
||||||
/// MaxSize testcase size for mutators that appreciate it
|
/// MaxSize testcase size for mutators that appreciate it
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
/// The stability of the current fuzzing process
|
/// The stability of the current fuzzing process
|
||||||
@ -176,22 +190,20 @@ where
|
|||||||
phantom: PhantomData<I>,
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
type Rand = R;
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
type Corpus = C;
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
type Solutions = SC;
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// Get all the metadata into an [`hashbrown::HashMap`]
|
/// 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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
type FeedbackStates = FT;
|
/// Get all the metadata into an [`hashbrown::HashMap`]
|
||||||
|
|
||||||
/// The feedback states
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn feedback_states(&self) -> &FT {
|
fn named_metadata(&self) -> &NamedSerdeAnyMap {
|
||||||
&self.feedback_states
|
&self.named_metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The feedback states (mutable)
|
/// Get all the metadata into an [`hashbrown::HashMap`] (mutable)
|
||||||
#[inline]
|
#[inline]
|
||||||
fn feedback_states_mut(&mut self) -> &mut FT {
|
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap {
|
||||||
&mut self.feedback_states
|
&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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// The executions counter
|
/// 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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
fn max_size(&self) -> usize {
|
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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// The starting time
|
/// The starting time
|
||||||
@ -359,12 +362,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
/// Loads inputs from a directory.
|
/// 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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
fn generate_initial_internal<G, E, EM, Z>(
|
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.
|
/// 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 {
|
pub fn new<F, O>(
|
||||||
Self {
|
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,
|
rand,
|
||||||
executions: 0,
|
executions: 0,
|
||||||
stability: None,
|
stability: None,
|
||||||
start_time: Duration::from_millis(0),
|
start_time: Duration::from_millis(0),
|
||||||
metadata: SerdeAnyMap::default(),
|
metadata: SerdeAnyMap::default(),
|
||||||
|
named_metadata: NamedSerdeAnyMap::default(),
|
||||||
corpus,
|
corpus,
|
||||||
feedback_states,
|
|
||||||
solutions,
|
solutions,
|
||||||
max_size: DEFAULT_MAX_SIZE,
|
max_size: DEFAULT_MAX_SIZE,
|
||||||
#[cfg(feature = "introspection")]
|
#[cfg(feature = "introspection")]
|
||||||
introspection_monitor: ClientPerfMonitor::new(),
|
introspection_monitor: ClientPerfMonitor::new(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
};
|
||||||
|
feedback.init_state(&mut state)?;
|
||||||
|
objective.init_state(&mut state)?;
|
||||||
|
Ok(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "introspection")]
|
#[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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
||||||
@ -610,12 +623,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "introspection"))]
|
#[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
|
where
|
||||||
C: Corpus<I>,
|
C: Corpus<I>,
|
||||||
I: Input,
|
I: Input,
|
||||||
R: Rand,
|
R: Rand,
|
||||||
FT: FeedbackStatesTuple,
|
|
||||||
SC: Corpus<I>,
|
SC: Corpus<I>,
|
||||||
{
|
{
|
||||||
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
fn introspection_monitor(&self) -> &ClientPerfMonitor {
|
||||||
@ -645,28 +657,20 @@ pub mod pybind {
|
|||||||
use crate::bolts::rands::pybind::PythonRand;
|
use crate::bolts::rands::pybind::PythonRand;
|
||||||
use crate::bolts::tuples::tuple_list;
|
use crate::bolts::tuples::tuple_list;
|
||||||
use crate::corpus::pybind::PythonCorpus;
|
use crate::corpus::pybind::PythonCorpus;
|
||||||
use crate::feedbacks::map::MapFeedbackState;
|
use crate::feedbacks::pybind::PythonFeedback;
|
||||||
use crate::inputs::BytesInput;
|
use crate::inputs::BytesInput;
|
||||||
use crate::state::StdState;
|
use crate::state::StdState;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
|
||||||
macro_rules! define_python_state {
|
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,
|
($type_name:ident, $struct_name:ident, $py_name:tt) => {
|
||||||
$fuzzer_name: ident, $executor_name: ident, $rand_printable_generator: ident) => {
|
|
||||||
use crate::events::pybind::$event_manager_name;
|
use crate::events::pybind::$event_manager_name;
|
||||||
use crate::executors::pybind::$executor_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::fuzzer::pybind::$fuzzer_name;
|
||||||
use crate::generators::pybind::$rand_printable_generator;
|
use crate::generators::pybind::$rand_printable_generator;
|
||||||
|
|
||||||
/// `StdState` with fixed generics
|
/// `StdState` with fixed generics
|
||||||
pub type $type_name = StdState<
|
pub type $type_name = StdState<PythonCorpus, BytesInput, PythonRand, PythonCorpus>;
|
||||||
PythonCorpus,
|
|
||||||
(MapFeedbackState<$datatype>, ()),
|
|
||||||
BytesInput,
|
|
||||||
PythonRand,
|
|
||||||
PythonCorpus,
|
|
||||||
>;
|
|
||||||
|
|
||||||
#[pyclass(unsendable, name = $py_name)]
|
#[pyclass(unsendable, name = $py_name)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -683,24 +687,20 @@ pub mod pybind {
|
|||||||
py_rand: PythonRand,
|
py_rand: PythonRand,
|
||||||
corpus: PythonCorpus,
|
corpus: PythonCorpus,
|
||||||
solutions: PythonCorpus,
|
solutions: PythonCorpus,
|
||||||
py_map_feedback_state: $py_map_feedback_state_name,
|
feedback: &mut PythonFeedback,
|
||||||
|
objective: &mut PythonFeedback,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
std_state: StdState::new(
|
std_state: StdState::new(py_rand, corpus, solutions, feedback, objective),
|
||||||
py_rand,
|
|
||||||
corpus,
|
|
||||||
solutions,
|
|
||||||
tuple_list!(py_map_feedback_state.map_feedback_state),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_initial_inputs(
|
fn generate_initial_inputs(
|
||||||
&mut self,
|
&mut self,
|
||||||
py_fuzzer: &mut $fuzzer_name,
|
py_fuzzer: &mut PythonFuzzer,
|
||||||
py_executor: &mut $executor_name,
|
py_executor: &mut PythonExecutor,
|
||||||
py_generator: &mut $rand_printable_generator,
|
py_generator: &mut PythonGenerator,
|
||||||
py_mgr: &mut $event_manager_name,
|
py_mgr: &mut PythonEventManager,
|
||||||
num: usize,
|
num: usize,
|
||||||
) {
|
) {
|
||||||
self.std_state
|
self.std_state
|
||||||
@ -717,109 +717,11 @@ pub mod pybind {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
define_python_state!(
|
define_python_state!(PythonStdState, PythonStdStateWrapper, "StdState",);
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Register the classes to the python module
|
/// Register the classes to the python module
|
||||||
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||||
m.add_class::<PythonStdStateI8>()?;
|
m.add_class::<PythonStdStateWrapper>()?;
|
||||||
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>()?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 5cccc33456c48ad83008eb618e7da5d005c72d89
|
Subproject commit 45cde0269ae22aef4cca2e1fb98c3b24f7bb2984
|
@ -17,7 +17,7 @@ use libafl::{
|
|||||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||||
executors::{forkserver::ForkserverExecutorBuilder, TimeoutForkserverExecutor},
|
executors::{forkserver::ForkserverExecutorBuilder, TimeoutForkserverExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandBytesGenerator,
|
generators::RandBytesGenerator,
|
||||||
monitors::MultiMonitor,
|
monitors::MultiMonitor,
|
||||||
@ -111,7 +111,7 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
// Coverage map shared between target and fuzzer
|
// 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
|
// Create an observation channel to keep track of the execution time
|
||||||
let time_observer = TimeObserver::new("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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
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),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a dictionary if not existing
|
// Create a dictionary if not existing
|
||||||
|
@ -19,7 +19,7 @@ use libafl::{
|
|||||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||||
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor, TimeoutExecutor},
|
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandBytesGenerator,
|
generators::RandBytesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -138,7 +138,7 @@ where
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
@ -151,20 +151,17 @@ where
|
|||||||
let cmplog = unsafe { &mut CMPLOG_MAP };
|
let cmplog = unsafe { &mut CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
let mut state = state.unwrap_or_else(|| {
|
||||||
@ -176,10 +173,10 @@ where
|
|||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a dictionary if not existing
|
// Create a dictionary if not existing
|
||||||
|
@ -18,7 +18,7 @@ use libafl::{
|
|||||||
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
|
||||||
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
|
||||||
feedback_or, feedback_or_fast,
|
feedback_or, feedback_or_fast,
|
||||||
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
|
||||||
fuzzer::{Fuzzer, StdFuzzer},
|
fuzzer::{Fuzzer, StdFuzzer},
|
||||||
generators::RandBytesGenerator,
|
generators::RandBytesGenerator,
|
||||||
inputs::{BytesInput, HasTargetBytes},
|
inputs::{BytesInput, HasTargetBytes},
|
||||||
@ -141,7 +141,7 @@ where
|
|||||||
|
|
||||||
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
let monitor = MultiMonitor::new(|s| println!("{}", s));
|
||||||
|
|
||||||
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
|
let mut run_client = |state: Option<_>,
|
||||||
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
|
||||||
_core_id| {
|
_core_id| {
|
||||||
// Create an observation channel using the coverage map
|
// Create an observation channel using the coverage map
|
||||||
@ -157,20 +157,17 @@ where
|
|||||||
let cmplog = unsafe { &mut cmplog::CMPLOG_MAP };
|
let cmplog = unsafe { &mut cmplog::CMPLOG_MAP };
|
||||||
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
|
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
|
// Feedback to rate the interestingness of an input
|
||||||
// This one is composed by two Feedbacks in OR
|
// 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
|
// 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
|
// Time feedback, this one does not need a feedback state
|
||||||
TimeFeedback::new_with_observer(&time_observer)
|
TimeFeedback::new_with_observer(&time_observer)
|
||||||
);
|
);
|
||||||
|
|
||||||
// A feedback to choose if an input is a solution or not
|
// 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
|
// If not restarting, create a State from scratch
|
||||||
let mut state = state.unwrap_or_else(|| {
|
let mut state = state.unwrap_or_else(|| {
|
||||||
@ -182,10 +179,10 @@ where
|
|||||||
// Corpus in which we store solutions (crashes in this example),
|
// Corpus in which we store solutions (crashes in this example),
|
||||||
// on disk so the user can get them after stopping the fuzzer
|
// on disk so the user can get them after stopping the fuzzer
|
||||||
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
OnDiskCorpus::new(crashes.clone()).unwrap(),
|
||||||
// States of the feedbacks.
|
&mut feedback,
|
||||||
// They are the data related to the feedbacks that you want to persist in the State.
|
&mut objective,
|
||||||
tuple_list!(feedback_state),
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create a dictionary if not existing
|
// Create a dictionary if not existing
|
||||||
|
Loading…
x
Reference in New Issue
Block a user