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:
Andrea Fioraldi 2022-05-24 16:05:22 +02:00 committed by GitHub
parent fa839bb08d
commit da537aae83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
61 changed files with 1684 additions and 1111 deletions

View File

@ -7,8 +7,8 @@ edition = "2021"
pyo3 = { version = "0.15", features = ["extension-module"] }
libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] }
libafl_sugar = { path = "../../libafl_sugar", version = "0.7", features = ["python"] }
libafl = { path = "../../libafl", version = "0.7", features = ["python"] }
#libafl = { path = "../../libafl", version = "0.7", features = ["python"] }
libafl = { path = "../../libafl", version = "0.7" }
[build-dependencies]
pyo3-build-config = { version = "0.15" }

View File

@ -1,4 +1,4 @@
use libafl;
//use libafl;
use libafl_qemu;
use libafl_sugar;
use pyo3::prelude::*;
@ -14,9 +14,9 @@ pub fn python_module(py: Python, m: &PyModule) -> PyResult<()> {
libafl_qemu::python_module(py, qemu_module)?;
m.add_submodule(qemu_module)?;
let libafl_module = PyModule::new(py, "libafl")?;
libafl::python_module(py, libafl_module)?;
m.add_submodule(libafl_module)?;
//let libafl_module = PyModule::new(py, "libafl")?;
//libafl::python_module(py, libafl_module)?;
//m.add_submodule(libafl_module)?;
Ok(())
}

View File

@ -114,8 +114,9 @@ let mut state = StdState::new(
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
(),
);
&mut (),
&mut ()
).unwrap();
```
It takes a random number generator, that is part of the fuzzer state, in this case, we use the default one `StdRand` but you can choose a different one. We seed it with the current nanoseconds.
@ -273,7 +274,7 @@ let mut executor = InProcessExecutor::new(
.expect("Failed to create the Executor".into());
```
Now that the fuzzer can observe which condition is satisfied, we need a way to rate an input as interesting (i.e. worth of addition to the corpus) based on this observation. Here comes the notion of Feedback. The Feedback is part of the State and provides a way to rate input and its corresponding execution as interesting looking for the information in the observers. Feedbacks can maintain a cumulative state of the information seen so far in a so-called FeedbackState instance, in our case it maintains the set of conditions satisfied in the previous runs.
Now that the fuzzer can observe which condition is satisfied, we need a way to rate an input as interesting (i.e. worth of addition to the corpus) based on this observation. Here comes the notion of Feedback. The Feedback is part of the State and provides a way to rate input and its corresponding execution as interesting looking for the information in the observers. Feedbacks can maintain a cumulative state of the information seen so far in a metadata in the State, in our case it maintains the set of conditions satisfied in the previous runs.
We use MaxMapFeedback, a feedback that implements a novelty search over the map of the MapObserver. Basically, if there is a value in the observer's map that is greater than the maximum value registered so far for the same entry, it rates the input as interesting and updates its state.
@ -286,20 +287,17 @@ extern crate libafl;
use libafl::{
bolts::{current_nanos, rands::StdRand, tuples::tuple_list},
corpus::{InMemoryCorpus, OnDiskCorpus},
feedbacks::{MapFeedbackState, MaxMapFeedback, CrashFeedback},
feedbacks::{MaxMapFeedback, CrashFeedback},
fuzzer::StdFuzzer,
state::StdState,
observers::StdMapObserver,
};
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&feedback_state, &observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -310,10 +308,9 @@ let mut state = StdState::new(
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
&mut feedback,
&mut objective
).unwrap();
// ...

View File

@ -8,7 +8,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -41,7 +41,7 @@ pub fn main() {
signals_set(2);
if buf.len() > 2 && buf[2] == b'c' {
#[cfg(unix)]
panic!("=(");
panic!("Artificial bug triggered =)");
// panic!() raises a STATUS_STACK_BUFFER_OVERRUN exception which cannot be caught by the exception handler.
// Here we make it raise STATUS_ACCESS_VIOLATION instead.
@ -58,16 +58,14 @@ pub fn main() {
};
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let observer =
unsafe { StdMapObserver::new_from_ptr("signals", SIGNALS.as_mut_ptr(), SIGNALS.len()) };
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -79,9 +77,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -13,7 +13,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::{Automaton, GramatronGenerator},
inputs::GramatronInput,
@ -61,14 +61,11 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -80,9 +77,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -9,7 +9,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
inputs::{GeneralizedInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -92,14 +92,11 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new_tracking(&feedback_state, &observer, false, true);
let mut feedback = MaxMapFeedback::new_tracking(&observer, false, true);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -111,9 +108,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
if state.metadata().get::<Tokens>().is_none() {
state.add_metadata(Tokens::from([b"FOO".to_vec(), b"BAR".to_vec()]));

View File

@ -9,9 +9,7 @@ use libafl::{
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedback_or,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NautilusChunksMetadata, NautilusFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::{NautilusContext, NautilusGenerator},
inputs::NautilusInput,
@ -51,17 +49,14 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = feedback_or!(
MaxMapFeedback::new(&feedback_state, &observer),
let mut feedback = feedback_or!(
MaxMapFeedback::new(&observer),
NautilusFeedback::new(&context)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -73,9 +68,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
if state.metadata().get::<NautilusChunksMetadata>().is_none() {
state.add_metadata(NautilusChunksMetadata::new("/tmp/".into()));

View File

@ -9,7 +9,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Evaluator, Fuzzer, StdFuzzer},
inputs::{EncodedInput, InputDecoder, InputEncoder, NaiveTokenizer, TokenInputEncoderDecoder},
monitors::SimpleMonitor,
@ -69,14 +69,11 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -88,9 +85,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -14,7 +14,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{ExitKind, InProcessForkExecutor},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -68,14 +68,11 @@ pub fn main() {
let observer = StdMapObserver::new("signals", signals_clone.as_mut_slice());
// Create a stacktrace observer to add the observers tuple
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -87,9 +84,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -9,7 +9,7 @@ use libafl::{
corpus::InMemoryCorpus,
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -77,14 +77,11 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -96,9 +93,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
InMemoryCorpus::new(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| {

View File

@ -14,9 +14,7 @@ use libafl::{
events::SimpleEventManager,
executors::InProcessForkExecutor,
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -59,17 +57,13 @@ pub fn main() {
libafl::observers::HarnessType::Child,
);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let st_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = feedback_and!(
let mut objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
);
// create a State from scratch
@ -82,9 +76,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, st_feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -8,9 +8,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -48,17 +46,13 @@ pub fn main() {
libafl::observers::HarnessType::InProcess,
);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let st_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = feedback_and!(
let mut objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
);
// create a State from scratch
@ -71,9 +65,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, st_feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -10,9 +10,7 @@ use libafl::{
events::SimpleEventManager,
executors::command::CommandConfigurator,
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{HasTargetBytes, Input},
@ -43,22 +41,15 @@ pub fn main() {
// Create a stacktrace observer
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let bt_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = feedback_and!(
let mut objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::<ASANBacktraceObserver>::new_with_observer(
"ASANBacktraceObserver",
&bt_observer
)
NewHashFeedback::<ASANBacktraceObserver>::new(&bt_observer)
);
// let objective = CrashFeedback::new();
// let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -70,9 +61,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, bt_feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -10,9 +10,7 @@ use libafl::{
events::SimpleEventManager,
executors::forkserver::ForkserverExecutor,
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::BytesInput,
@ -54,20 +52,13 @@ pub fn main() {
let bt_observer = ASANBacktraceObserver::new("ASANBacktraceObserver");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let bt_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false);
let mut feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
// A feedback to choose if an input is a solution or not
// We want to do the same crash deduplication that AFL does
let objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::new_with_observer("NewHashFeedback", &bt_observer)
);
let mut objective = feedback_and!(CrashFeedback::new(), NewHashFeedback::new(&bt_observer));
// create a State from scratch
let mut state = StdState::new(
@ -79,9 +70,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, bt_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -15,9 +15,7 @@ use libafl::{
events::SimpleEventManager,
executors::{ExitKind, InProcessForkExecutor},
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -76,17 +74,13 @@ pub fn main() {
libafl::observers::HarnessType::Child,
);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let bt_feedback_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = feedback_and!(
let mut objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::<BacktraceObserver>::new_with_observer("BacktraceObserver", &bt_observer)
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
);
// create a State from scratch
@ -99,9 +93,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, bt_feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -9,9 +9,7 @@ use libafl::{
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedback_and,
feedbacks::{
CrashFeedback, MapFeedbackState, MaxMapFeedback, NewHashFeedback, NewHashFeedbackState,
},
feedbacks::{CrashFeedback, MaxMapFeedback, NewHashFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -70,17 +68,13 @@ pub fn main() {
libafl::observers::HarnessType::InProcess,
);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
let hash_state = NewHashFeedbackState::<u64>::with_observer(&bt_observer);
// Feedback to rate the interestingness of an input, obtained by ANDing the interestingness of both feedbacks
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = feedback_and!(
let mut objective = feedback_and!(
CrashFeedback::new(),
NewHashFeedback::<BacktraceObserver>::new_with_observer("NewHashFeedback", &bt_observer)
NewHashFeedback::<BacktraceObserver>::new(&bt_observer)
);
// create a State from scratch
@ -93,9 +87,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, hash_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are displayed to the user
let mon = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -1,4 +1,4 @@
use clap::{App, Arg};
use clap::{Arg, Command};
use core::time::Duration;
use libafl::{
bolts::{
@ -12,7 +12,7 @@ use libafl::{
events::SimpleEventManager,
executors::forkserver::{ForkserverExecutor, TimeoutForkserverExecutor},
feedback_and_fast, feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::BytesInput,
monitors::SimpleMonitor,
@ -33,7 +33,7 @@ use libafl::bolts::shmem::StdShMemProvider;
#[allow(clippy::similar_names)]
pub fn main() {
let res = App::new("forkserver_simple")
let res = Command::new("forkserver_simple")
.about("Example Forkserver fuzer")
.arg(
Arg::new("executable")
@ -63,7 +63,7 @@ pub fn main() {
.arg(
Arg::new("arguments")
.help("Arguments passed to the target")
.setting(clap::ArgSettings::MultipleValues)
.multiple_values(true)
.takes_value(true),
)
.arg(
@ -101,28 +101,22 @@ pub fn main() {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// The state of the edges feedback for crashes.
let objective_state = MapFeedbackState::new("crash_edges", MAP_SIZE);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
// We want to do the same crash deduplication that AFL does
let objective = feedback_and_fast!(
let mut objective = feedback_and_fast!(
// Must be a crash
CrashFeedback::new(),
// Take it onlt if trigger new coverage over crashes
MaxMapFeedback::new(&objective_state, &edges_observer)
MaxMapFeedback::<_, _, _, u8>::new(&edges_observer)
);
// create a State from scratch
@ -135,9 +129,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state, objective_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));
@ -163,7 +160,7 @@ pub fn main() {
let mut tokens = Tokens::new();
let forkserver = ForkserverExecutor::builder()
.program(res.value_of("executable").unwrap().to_string())
.program(res.value_of("executable").unwrap())
.debug_child(debug_child)
.shmem_provider(&mut shmem_provider)
.autotokens(&mut tokens)

View File

@ -20,8 +20,8 @@ use libafl::{
corpus::{ondisk::OnDiskMetadataFormat, CachedOnDiskCorpus, Corpus, OnDiskCorpus},
events::{llmp::LlmpRestartingEventManager, EventConfig},
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedback_and_fast, feedback_or, feedback_or_fast,
feedbacks::{ConstFeedback, CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -72,9 +72,13 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
let shmem_provider = StdShMemProvider::new()?;
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
let mut run_client = |state: Option<_>,
mgr: LlmpRestartingEventManager<_, _, _, _>,
core_id| {
// The restarting state will spawn the same process again as child, then restarted it each time it crashes.
// println!("{:?}", mgr.mgr_id());
let lib = libloading::Library::new(options.clone().harness.unwrap()).unwrap();
let target_func: libloading::Symbol<
unsafe extern "C" fn(data: *const u8, size: usize) -> i32,
@ -88,9 +92,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
};
if options.asan && options.asan_cores.contains(core_id) {
(|state: Option<StdState<_, _, _, _, _>>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
let gum = Gum::obtain();
let coverage = CoverageRuntime::new();
@ -114,26 +116,25 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// Feedbacks to recognize an input as solution
#[cfg(unix)]
let objective = feedback_or_fast!(
let mut objective = feedback_or_fast!(
CrashFeedback::new(),
TimeoutFeedback::new(),
AsanErrorsFeedback::new()
// true enables the AsanErrorFeedback
feedback_and_fast!(ConstFeedback::from(true), AsanErrorsFeedback::new())
);
#[cfg(windows)]
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -149,10 +150,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
Some(OnDiskMetadataFormat::JsonPretty),
)
.unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");
@ -216,9 +217,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
Ok(())
})(state, mgr, core_id)
} else if options.cmplog && options.cmplog_cores.contains(core_id) {
(|state: Option<StdState<_, _, _, _, _>>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
let gum = Gum::obtain();
let coverage = CoverageRuntime::new();
@ -237,19 +236,23 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// Feedbacks to recognize an input as solution
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
#[cfg(unix)]
let mut objective = feedback_or_fast!(
CrashFeedback::new(),
TimeoutFeedback::new(),
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
);
#[cfg(windows)]
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -265,10 +268,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
Some(OnDiskMetadataFormat::JsonPretty),
)
.unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");
@ -348,9 +351,7 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
Ok(())
})(state, mgr, core_id)
} else {
(|state: Option<StdState<_, _, _, _, _>>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
(|state: Option<_>, mut mgr: LlmpRestartingEventManager<_, _, _, _>, _core_id| {
let gum = Gum::obtain();
let coverage = CoverageRuntime::new();
@ -368,19 +369,23 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// Feedbacks to recognize an input as solution
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
#[cfg(unix)]
let mut objective = feedback_or_fast!(
CrashFeedback::new(),
TimeoutFeedback::new(),
feedback_and_fast!(ConstFeedback::from(false), AsanErrorsFeedback::new())
);
#[cfg(windows)]
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -396,10 +401,10 @@ unsafe fn fuzz(options: FuzzerOptions) -> Result<(), Error> {
Some(OnDiskMetadataFormat::JsonPretty),
)
.unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
use clap::{App, Arg};
use clap::{Arg, Command};
use core::{cell::RefCell, time::Duration};
#[cfg(unix)]
use nix::{self, unistd::dup};
@ -30,7 +30,7 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -64,7 +64,7 @@ pub fn libafl_main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_fuzzbench")
let res = match Command::new("libafl_fuzzbench")
.version("0.7.1")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer for Fuzzbench")
@ -113,7 +113,7 @@ pub fn libafl_main() {
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
err,
);
return;
}
@ -260,20 +260,21 @@ fn fuzz(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -286,9 +287,12 @@ fn fuzz(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("Let's fuzz :)");
@ -300,8 +304,6 @@ fn fuzz(
println!("Warning: LLVMFuzzerInitialize failed with -1")
}
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -1,5 +1,5 @@
[package]
name = "fuzzbench_qemu"
name = "fuzzbench_fork_qemu"
version = "0.7.1"
authors = ["Andrea Fioraldi <andreafioraldi@gmail.com>", "Dominik Maier <domenukk@gmail.com>"]
edition = "2021"

View File

@ -1,6 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use clap::{App, Arg};
use clap::{Arg, Command};
use core::cell::RefCell;
#[cfg(unix)]
use nix::{self, unistd::dup};
@ -27,7 +27,7 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{ExitKind, ShadowExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -62,7 +62,7 @@ pub fn main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_qemu_fuzzbench")
let res = match Command::new("libafl_qemu_fuzzbench")
.version("0.4.0")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
@ -101,7 +101,7 @@ pub fn main() {
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
err,
);
return;
}
@ -240,20 +240,21 @@ fn fuzz(
let cmplog_observer =
CmpLogObserver::new("cmplog", unsafe { CMPLOG_MAP_PTR.as_mut().unwrap() }, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -266,13 +267,14 @@ fn fuzz(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -1,6 +1,6 @@
//! A singlethreaded QEMU fuzzer that can auto-restart.
use clap::{App, Arg};
use clap::{Arg, Command};
use core::{cell::RefCell, time::Duration};
#[cfg(unix)]
use nix::{self, unistd::dup};
@ -27,7 +27,7 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -68,7 +68,7 @@ pub fn main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_qemu_fuzzbench")
let res = match Command::new("libafl_qemu_fuzzbench")
.version("0.4.0")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer with QEMU for Fuzzbench")
@ -113,7 +113,7 @@ pub fn main() {
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
err,
);
return;
}
@ -253,20 +253,21 @@ fn fuzz(
// Create an observation channel using cmplog map
let cmplog_observer = CmpLogObserver::new("cmplog", unsafe { &mut cmplog::CMPLOG_MAP }, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -279,13 +280,14 @@ fn fuzz(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
use clap::{App, Arg};
use clap::{Arg, Command};
use content_inspector::inspect;
use core::{cell::RefCell, time::Duration};
#[cfg(unix)]
@ -31,7 +31,7 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, GeneralizedInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -70,7 +70,7 @@ pub fn libafl_main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_fuzzbench")
let res = match Command::new("libafl_fuzzbench")
.version("0.7.1")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer for Fuzzbench")
@ -119,7 +119,7 @@ pub fn libafl_main() {
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
err,
);
return;
}
@ -321,20 +321,20 @@ fn fuzz_binary(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, true),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -347,9 +347,12 @@ fn fuzz_binary(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("Let's fuzz :)");
@ -361,8 +364,6 @@ fn fuzz_binary(
println!("Warning: LLVMFuzzerInitialize failed with -1")
}
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));
@ -531,20 +532,21 @@ fn fuzz_text(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// New maximization map feedback linked to the edges observer and the feedback state
let mut map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, true);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, true),
let mut feedback = feedback_or!(
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -557,9 +559,12 @@ fn fuzz_text(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("Let's fuzz :)");
@ -571,8 +576,6 @@ fn fuzz_text(
println!("Warning: LLVMFuzzerInitialize failed with -1")
}
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -3,7 +3,7 @@ use mimalloc::MiMalloc;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
use clap::{App, Arg};
use clap::{Arg, Command};
use core::{cell::RefCell, time::Duration};
#[cfg(unix)]
use nix::{self, unistd::dup};
@ -30,7 +30,7 @@ use libafl::{
events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -64,7 +64,7 @@ pub fn libafl_main() {
// Needed only on no_std
//RegistryBuilder::register::<Tokens>();
let res = match App::new("libafl_fuzzbench")
let res = match Command::new("libafl_fuzzbench")
.version("0.7.1")
.author("AFLplusplus team")
.about("LibAFL-based fuzzer for Fuzzbench")
@ -113,7 +113,7 @@ pub fn libafl_main() {
env::current_exe()
.unwrap_or_else(|_| "fuzzer".into())
.to_string_lossy(),
err.info,
err,
);
return;
}
@ -260,20 +260,21 @@ fn fuzz(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -286,9 +287,12 @@ fn fuzz(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("Let's fuzz :)");
@ -300,8 +304,6 @@ fn fuzz(
println!("Warning: LLVMFuzzerInitialize failed with -1")
}
let calibration = CalibrationStage::new(&edges_observer);
// Setup a randomic Input2State stage
let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new())));

View File

@ -3,7 +3,7 @@
//! This is the drop-in replacement for libfuzzer, to be used together with [`Atheris`](https://github.com/google/atheris)
//! for python instrumentation and fuzzing.
use clap::{App, AppSettings, Arg};
use clap::{AppSettings, Arg, Command};
use core::{convert::TryInto, ffi::c_void, slice, time::Duration};
use std::{
env,
@ -25,7 +25,7 @@ use libafl::{
events::EventConfig,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandBytesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -124,7 +124,7 @@ pub fn LLVMFuzzerRunDriver(
println!("Args: {:?}", std::env::args());
let matches = App::new("libafl_atheris")
let matches = Command::new("libafl_atheris")
.version("0.1.0")
.setting(AppSettings::AllowExternalSubcommands)
.arg(Arg::new("script")) // The python script is the first arg
@ -213,7 +213,7 @@ pub fn LLVMFuzzerRunDriver(
// TODO: we need to handle Atheris calls to `exit` on errors somhow.
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut mgr, _core_id| {
let mut run_client = |state: Option<_>, mut mgr, _core_id| {
// Create an observation channel using the coverage map
let edges_observer = unsafe {
HitcountsMapObserver::new(StdMapObserver::new_from_ptr(
@ -230,20 +230,17 @@ pub fn LLVMFuzzerRunDriver(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -256,9 +253,12 @@ pub fn LLVMFuzzerRunDriver(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(output_dir.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
// Create a dictionary if not existing

View File

@ -17,7 +17,7 @@ use libafl::{
events::{setup_restarting_mgr_std, EventConfig},
executors::{inprocess::InProcessExecutor, ExitKind},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -86,24 +86,15 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// Create an observation channel using the allocations map
let allocs_observer = StdMapObserver::new("allocs", unsafe { &mut libafl_alloc_map });
// The state of the edges feedback.
let edges_feedback_state = MapFeedbackState::with_observer(&edges_observer);
// The state of the cmps feedback.
let cmps_feedback_state = MapFeedbackState::with_observer(&cmps_observer);
// The state of the allocs feedback.
let allocs_feedback_state = MapFeedbackState::with_observer(&allocs_observer);
// Feedback to rate the interestingness of an input
let feedback = feedback_or!(
MaxMapFeedback::new(&edges_feedback_state, &edges_observer),
MaxMapFeedback::new(&cmps_feedback_state, &cmps_observer),
MaxMapFeedback::new(&allocs_feedback_state, &allocs_observer)
let mut feedback = feedback_or!(
MaxMapFeedback::new(&edges_observer),
MaxMapFeedback::new(&cmps_observer),
MaxMapFeedback::new(&allocs_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -116,13 +107,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(
edges_feedback_state,
cmps_feedback_state,
allocs_feedback_state
),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -20,7 +20,7 @@ use libafl::{
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -81,20 +81,21 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -107,9 +108,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");
@ -129,7 +133,6 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let mutator = StdScheduledMutator::new(havoc_mutations().merge(tokens_mutations()));
let calibration = CalibrationStage::new(&edges_observer);
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
let mut stages = tuple_list!(calibration, power);

View File

@ -24,7 +24,7 @@ use libafl::{
events::EventConfig,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -143,7 +143,7 @@ pub fn libafl_main() {
let monitor = MultiMonitor::new(|s| println!("{}", s));
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
// Create an observation channel using the coverage map
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
@ -151,20 +151,17 @@ pub fn libafl_main() {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -177,9 +174,12 @@ pub fn libafl_main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(&opt.output).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -24,7 +24,7 @@ use libafl::{
events::EventConfig,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -141,7 +141,7 @@ pub fn libafl_main() {
let monitor = MultiMonitor::new(|s| println!("{}", s));
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
// Create an observation channel using the coverage map
let edges = unsafe { edges_map_from_ptr() };
let edges_observer =
@ -150,20 +150,17 @@ pub fn libafl_main() {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -176,9 +173,12 @@ pub fn libafl_main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(opt.output.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -24,7 +24,7 @@ use libafl::{
events::EventConfig,
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::tui::TuiMonitor,
@ -141,7 +141,7 @@ pub fn libafl_main() {
let monitor = TuiMonitor::new("Test fuzzer on libpng".into(), true);
let mut run_client = |state: Option<StdState<_, _, _, _, _>>, mut restarting_mgr, _core_id| {
let mut run_client = |state: Option<_>, mut restarting_mgr, _core_id| {
// Create an observation channel using the coverage map
let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] };
let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges));
@ -149,20 +149,17 @@ pub fn libafl_main() {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -175,9 +172,12 @@ pub fn libafl_main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(&opt.output).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -11,7 +11,7 @@ use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{MapFeedbackState, MaxMapFeedback, ReachabilityFeedback},
feedbacks::{MaxMapFeedback, ReachabilityFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -75,14 +75,11 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let reachability_observer =
unsafe { StdMapObserver::new_from_ptr("png.c", __libafl_target_list, TARGET_SIZE) };
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &edges_observer);
let mut feedback = MaxMapFeedback::new(&edges_observer);
// A feedback to choose if an input is a solution or not
let objective = ReachabilityFeedback::new(&reachability_observer);
let mut objective = ReachabilityFeedback::new(&reachability_observer);
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -95,9 +92,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -12,7 +12,7 @@ use libafl::{
events::{setup_restarting_mgr_std, EventConfig},
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -77,20 +77,17 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -103,9 +100,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -25,7 +25,7 @@ use libafl::{
command::CommandConfigurator, inprocess::InProcessExecutor, ExitKind, ShadowExecutor,
},
feedback_or,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes, Input},
monitors::MultiMonitor,
@ -116,20 +116,18 @@ fn fuzz(
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -142,9 +140,11 @@ fn fuzz(
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
)
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
).unwrap()
});
println!("We're a client, let's fuzz :)");

View File

@ -7,7 +7,7 @@ use libafl::{
corpus::{InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager,
executors::{inprocess::InProcessExecutor, ExitKind},
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandPrintablesGenerator,
monitors::SimpleMonitor,
@ -41,14 +41,11 @@ fn input_generator() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -60,9 +57,12 @@ fn input_generator() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -12,7 +12,7 @@ use libafl::{
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus, Testcase},
events::SimpleEventManager,
executors::ExitKind,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback},
fuzzer::StdFuzzer,
inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor,
@ -36,14 +36,11 @@ pub fn main() {
// Create an observation channel using the signals map
let observer = StdMapObserver::new("signals", unsafe { &mut SIGNALS });
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&observer);
// Feedback to rate the interestingness of an input
let feedback = MaxMapFeedback::<BytesInput, _, _, _>::new(&feedback_state, &observer);
let mut feedback = MaxMapFeedback::<BytesInput, _, _, _>::new(&observer);
// A feedback to choose if an input is a solution or not
let objective = CrashFeedback::new();
let mut objective = CrashFeedback::new();
// create a State from scratch
let mut state = StdState::new(
@ -55,9 +52,12 @@ pub fn main() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(PathBuf::from("./crashes")).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
);
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap();
// The Monitor trait define how the fuzzer stats are reported to the user
let monitor = SimpleMonitor::new(|s| println!("{}", s));

View File

@ -17,7 +17,7 @@ use libafl::{
events::EventConfig,
executors::{ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes},
monitors::MultiMonitor,
@ -50,7 +50,7 @@ pub fn fuzz() {
let broker_port = 1337;
let cores = Cores::from_cmdline("0-11").unwrap();
let corpus_dirs = [PathBuf::from("./corpus")];
let objective_dir = PathBuf::from("./crashes");
let mut objective_dir = PathBuf::from("./crashes");
// Initialize QEMU
env::remove_var("LD_LIBRARY_PATH");
@ -120,20 +120,17 @@ pub fn fuzz() {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -146,9 +143,12 @@ pub fn fuzz() {
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
// A minimization+queue policy to get testcasess from the corpus

View File

@ -12,15 +12,15 @@ use libafl::{
events::{setup_restarting_mgr_std, EventConfig, EventRestarter},
executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::StdFuzzer,
inputs::HasTargetBytes,
monitors::MultiMonitor,
observers::{HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{powersched::PowerSchedule, PowerQueueScheduler},
stages::{calibrate::CalibrationStage, power::StdPowerMutationalStage},
state::{HasCorpus, StdState},
Error,
Error, Fuzzer,
};
use libafl_targets::{libfuzzer_initialize, libfuzzer_test_one_input, EDGES_MAP, MAX_EDGES_NUM};
@ -88,21 +88,22 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false);
let calibration = CalibrationStage::new(&map_feedback);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
map_feedback,
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer),
PacketLenFeedback::new()
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -115,9 +116,12 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(objective_dir).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
// The feedbacks can report the data that should persist in the State.
&mut feedback,
// Same for objective feedbacks
&mut objective,
)
.unwrap()
});
println!("We're a client, let's fuzz :)");
@ -125,7 +129,6 @@ fn fuzz(corpus_dirs: &[PathBuf], objective_dir: PathBuf, broker_port: u16) -> Re
// Setup a lain mutator with a mutational stage
let mutator = LainMutator::new();
let calibration = CalibrationStage::new(&edges_observer);
let power = StdPowerMutationalStage::new(mutator, &edges_observer);
let mut stages = tuple_list!(calibration, power);

View File

@ -45,6 +45,7 @@ impl<S> Feedback<PacketData, S> for PacketLenFeedback
where
S: HasClientPerfMonitor,
{
#[inline]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
@ -72,11 +73,6 @@ where
.insert(PacketLenMetadata { length: self.len });
Ok(())
}
#[inline]
fn discard_metadata(&mut self, _state: &mut S, _input: &PacketData) -> Result<(), Error> {
Ok(())
}
}
impl Named for PacketLenFeedback {

View File

@ -13,13 +13,13 @@ categories = ["development-tools::testing", "emulators", "embedded", "os", "no-s
[features]
default = ["std", "derive", "llmp_compression", "rand_trait", "fork"]
std = ["serde_json", "serde_json/std", "hostname", "core_affinity", "nix", "serde/std", "bincode", "wait-timeout", "regex", "build_id", "uuid", "tui_monitor", "backtrace"] # print, env, launcher ... support
std = ["serde_json", "serde_json/std", "hostname", "core_affinity", "nix", "serde/std", "bincode", "wait-timeout", "regex", "build_id", "uuid", "tui_monitor", "ctor", "backtrace"] # print, env, launcher ... support
derive = ["libafl_derive"] # provide derive(SerdeAny) macro.
fork = [] # uses the fork() syscall to spawn children, instead of launching a new command, if supported by the OS (has no effect on Windows, no_std).
rand_trait = ["rand_core"] # If set, libafl's rand implementations will implement `rand::Rng`
introspection = [] # Include performance statistics of the fuzzing pipeline
concolic_mutation = ["z3"] # include a simple concolic mutator based on z3
python = ["pyo3"]
#python = ["pyo3"]
tui_monitor = ["tui", "crossterm"] # enable TuiMonitor with crossterm
cli = ["clap"] # expose bolts::cli
qemu_cli = ["cli"]
@ -59,13 +59,13 @@ erased-serde = { version = "0.3.12", default-features = false, features = ["allo
postcard = { version = "0.7", features = ["alloc"] } # no_std compatible serde serialization fromat
bincode = {version = "1.3", optional = true }
static_assertions = "1.1.0"
ctor = "0.1.20"
num_enum = { version = "0.5.4", default-features = false }
typed-builder = "0.9.1" # Implement the builder pattern at compiletime
ahash = { version = "0.7", default-features=false, features=["compile-time-rng"] } # The hash function already used in hashbrown
intervaltree = { version = "0.2.7", default-features = false, features = ["serde"] }
backtrace = {version = "0.3", optional = true} # Used to get the stacktrace in StacktraceObserver
ctor = { optional = true, version = "0.1" }
serde_json = { version = "1.0", optional = true, default-features = false, features = ["alloc"] }
miniz_oxide = { version = "0.4.4", optional = true}
core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", rev = "6648a7a", optional = true }

View File

@ -103,7 +103,7 @@ macro_rules! create_serde_registry_for_trait {
*REGISTRY
.deserializers
.as_ref()
.unwrap()
.expect("Empty types registry")
.get(&id)
.expect("Cannot deserialize an unregistered type")
};
@ -302,6 +302,15 @@ macro_rules! create_serde_registry_for_trait {
map: HashMap<u64, HashMap<u64, Box<dyn $trait_name>>>,
}
// Cloning by serializing and deserializing. It ain't fast, but it's honest work.
// We unwrap postcard, it should not have a reason to fail.
impl Clone for NamedSerdeAnyMap {
fn clone(&self) -> Self {
let serialized = postcard::to_allocvec(&self).unwrap();
postcard::from_bytes(&serialized).unwrap()
}
}
#[allow(unused_qualifications)]
impl NamedSerdeAnyMap {
/// Get an element by name
@ -496,15 +505,18 @@ macro_rules! create_serde_registry_for_trait {
/// Insert an element into this map.
#[inline]
#[allow(unused_qualifications)]
pub fn insert(&mut self, val: Box<dyn $trait_name>, name: &str) {
let id = unpack_type_id((*val).type_id());
pub fn insert<T>(&mut self, val: T, name: &str)
where
T: $trait_name,
{
let id = unpack_type_id(TypeId::of::<T>());
if !self.map.contains_key(&id) {
self.map.insert(id, HashMap::default());
}
self.map
.get_mut(&id)
.unwrap()
.insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), val);
.insert(xxhash_rust::xxh3::xxh3_64(name.as_bytes()), Box::new(val));
}
/// Returns the `len` of this map.
@ -590,41 +602,36 @@ macro_rules! create_serde_registry_for_trait {
create_serde_registry_for_trait!(serdeany_registry, crate::bolts::serdeany::SerdeAny);
pub use serdeany_registry::*;
/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`]
/// Register a `SerdeAny` type in the [`RegistryBuilder`]
#[cfg(feature = "std")]
#[macro_export]
macro_rules! impl_serdeany {
($struct_name:ident) => {
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
fn as_any(&self) -> &dyn ::core::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
self
}
fn as_any_boxed(
self: ::std::boxed::Box<Self>,
) -> ::std::boxed::Box<dyn ::core::any::Any> {
self
}
}
#[allow(non_snake_case)]
macro_rules! register_at_startup {
($struct_type:ty) => {
const _: () = {
#[$crate::ctor]
fn $struct_name() {
$crate::bolts::serdeany::RegistryBuilder::register::<$struct_name>();
fn constructor() {
$crate::bolts::serdeany::RegistryBuilder::register::<$struct_type>();
}
};
};
}
/// Implement [`SerdeAny`] for a type
/// Do nothing for `no_std`, you have to register it manually in `main()` with [`RegistryBuilder::register`]
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! register_at_startup {
($struct_type:ty) => {};
}
/// Implement a [`SerdeAny`], registering it in the [`RegistryBuilder`] when on std
#[macro_export]
macro_rules! impl_serdeany {
($struct_name:ident) => {
impl $crate::bolts::serdeany::SerdeAny for $struct_name {
($struct_name:ident < $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ > $(, < $( $opt:tt ),+ >)*) =>
{
impl < $( $lt $( : $clt $(+ $dlt )* )? ),+ >
$crate::bolts::serdeany::SerdeAny
for $struct_name < $( $lt ),+ >
{
fn as_any(&self) -> &dyn ::core::any::Any {
self
}
@ -634,10 +641,37 @@ macro_rules! impl_serdeany {
}
fn as_any_boxed(
self: ::alloc::boxed::Box<Self>,
) -> ::alloc::boxed::Box<dyn ::core::any::Any> {
self: $crate::alloc::boxed::Box<$struct_name < $( $lt ),+ >>,
) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
self
}
}
$(
$crate::register_at_startup!($struct_name < $( $opt ),+ >);
)*
};
($struct_name:ident) =>
{
impl
$crate::bolts::serdeany::SerdeAny
for $struct_name
{
fn as_any(&self) -> &dyn ::core::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn ::core::any::Any {
self
}
fn as_any_boxed(
self: $crate::alloc::boxed::Box<$struct_name>,
) -> $crate::alloc::boxed::Box<dyn ::core::any::Any> {
self
}
}
$crate::register_at_startup!($struct_name);
};
}

View File

@ -21,7 +21,7 @@ use core::cell::RefCell;
use crate::{inputs::Input, Error};
/// Corpus with all current testcases
pub trait Corpus<I>: serde::Serialize + serde::de::DeserializeOwned
pub trait Corpus<I>: serde::Serialize + for<'de> serde::Deserialize<'de>
where
I: Input,
{

View File

@ -967,7 +967,7 @@ mod tests {
let solutions = InMemoryCorpus::<BytesInput>::new();
let mut state = StdState::new(rand, corpus, solutions, tuple_list!());
let mut state = StdState::new(rand, corpus, solutions, &mut (), &mut ()).unwrap();
let mut shmem_provider = StdShMemProvider::new().unwrap();

View File

@ -1682,10 +1682,10 @@ pub mod pybind {
use pyo3::types::PyBytes;
macro_rules! define_python_in_process_executor {
($struct_name:ident, $py_name:tt, $my_std_state_type_name: ident, $std_state_name: ident, $event_manager_name: ident, $map_observer_name: ident, $std_fuzzer_name: ident) => {
($struct_name:ident, $py_name:tt, $my_std_state_type_name: ident, $std_state_name: ident, $event_manager_name: ident, $observer_name: ident, $std_fuzzer_name: ident) => {
use crate::events::pybind::$event_manager_name;
use crate::fuzzer::pybind::$std_fuzzer_name;
use crate::observers::pybind::$map_observer_name;
use crate::observers::map::pybind::$observer_name;
use crate::state::pybind::{$my_std_state_type_name, $std_state_name};
#[pyclass(unsendable, name = $py_name)]
@ -1695,7 +1695,7 @@ pub mod pybind {
/// Rust wrapped OwnedInProcessExecutor object
pub owned_in_process_executor: OwnedInProcessExecutor<
BytesInput,
($map_observer_name, ()),
($observer_name, ()),
$my_std_state_type_name,
>,
}
@ -1705,7 +1705,7 @@ pub mod pybind {
#[new]
fn new(
harness: PyObject,
py_observer: $map_observer_name,
py_observer: $observer_name,
py_fuzzer: &mut $std_fuzzer_name,
py_state: &mut $std_state_name,
py_event_manager: &mut $event_manager_name,
@ -1734,9 +1734,9 @@ pub mod pybind {
}
define_python_in_process_executor!(
PythonOwnedInProcessExecutorI8,
"OwnedInProcessExecutorI8",
MyStdStateI8,
PythonOwnedInProcessExecutor,
"OwnedInProcessExecutor",
PythonStdState,
PythonStdStateI8,
PythonEventManagerI8,
PythonMapObserverI8,

View File

@ -195,11 +195,11 @@ pub mod pybind {
macro_rules! define_python_executor {
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident, $my_std_fuzzer_type_name: ident,
$event_manager_name: ident, $in_process_executor_name: ident, $map_observer_name: ident) => {
$event_manager_name: ident, $in_process_executor_name: ident, $observer_name: ident) => {
use crate::events::pybind::$event_manager_name;
use crate::executors::inprocess::pybind::$in_process_executor_name;
use crate::fuzzer::pybind::$my_std_fuzzer_type_name;
use crate::observers::map::pybind::$map_observer_name;
use crate::observers::pybind::$observer_name;
use crate::state::pybind::$my_std_state_type_name;
#[derive(Debug)]
@ -211,44 +211,37 @@ pub mod pybind {
#[derive(Debug)]
/// Executor + HasObservers Trait binding
pub struct $struct_name_trait {
executor: $wrapper_name,
wrapper: $wrapper_name,
}
impl $struct_name_trait {
fn get_executor(
fn unwrap(
&self,
) -> &(impl Executor<
$event_manager_name,
BytesInput,
$my_std_state_type_name,
$my_std_fuzzer_type_name,
> + HasObservers<BytesInput, ($map_observer_name, ()), $my_std_state_type_name>)
{
> + HasObservers<BytesInput, ($observer_name, ()), $my_std_state_type_name>) {
unsafe {
match self.executor {
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
&(*py_owned_inprocess_executor).owned_in_process_executor
}
match self.wrapper {
$wrapper_name::OwnedInProcess(py_wrapper) => &(*py_wrapper).upcast(),
}
}
}
fn get_mut_executor(
fn unwrap_mut(
&mut self,
) -> &mut (impl Executor<
$event_manager_name,
BytesInput,
$my_std_state_type_name,
$my_std_fuzzer_type_name,
> + HasObservers<
BytesInput,
($map_observer_name, ()),
$my_std_state_type_name,
>) {
> + HasObservers<BytesInput, ($observer_name, ()), $my_std_state_type_name>) {
unsafe {
match self.executor {
$wrapper_name::OwnedInProcess(py_owned_inprocess_executor) => {
&mut (*py_owned_inprocess_executor).owned_in_process_executor
match self.wrapper {
$wrapper_name::OwnedInProcess(py_wrapper) => {
&mut (*py_wrapper).upcast_mut()
}
}
}
@ -262,20 +255,20 @@ pub mod pybind {
owned_inprocess_executor: &mut $in_process_executor_name,
) -> Self {
Self {
executor: $wrapper_name::OwnedInProcess(owned_inprocess_executor),
wrapper: $wrapper_name::OwnedInProcess(owned_inprocess_executor),
}
}
}
impl<I, S> HasObservers<I, ($map_observer_name, ()), S> for $struct_name_trait {
impl<I, S> HasObservers<I, ($observer_name, ()), S> for $struct_name_trait {
// #[inline]
fn observers(&self) -> &($map_observer_name, ()) {
self.get_executor().observers()
fn observers(&self) -> &($observer_name, ()) {
self.unwrap().observers()
}
#[inline]
fn observers_mut(&mut self) -> &mut ($map_observer_name, ()) {
self.get_mut_executor().observers_mut()
fn observers_mut(&mut self) -> &mut ($observer_name, ()) {
self.unwrap_mut().observers_mut()
}
}
@ -295,112 +288,26 @@ pub mod pybind {
mgr: &mut $event_manager_name,
input: &BytesInput,
) -> Result<ExitKind, Error> {
self.get_mut_executor()
.run_target(fuzzer, state, mgr, input)
self.unwrap_mut().run_target(fuzzer, state, mgr, input)
}
}
};
}
define_python_executor!(
PythonExecutorI8,
"ExecutorI8",
PythonExecutorWrapperI8,
MyStdStateI8,
MyStdFuzzerI8,
PythonEventManagerI8,
PythonOwnedInProcessExecutorI8,
PythonMapObserverI8
);
define_python_executor!(
PythonExecutorI16,
"ExecutorI16",
PythonExecutorWrapperI16,
MyStdStateI16,
MyStdFuzzerI16,
PythonEventManagerI16,
PythonOwnedInProcessExecutorI16,
PythonMapObserverI16
);
define_python_executor!(
PythonExecutorI32,
"ExecutorI32",
PythonExecutorWrapperI32,
MyStdStateI32,
MyStdFuzzerI32,
PythonEventManagerI32,
PythonOwnedInProcessExecutorI32,
PythonMapObserverI32
);
define_python_executor!(
PythonExecutorI64,
"ExecutorI64",
PythonExecutorWrapperI64,
MyStdStateI64,
MyStdFuzzerI64,
PythonEventManagerI64,
PythonOwnedInProcessExecutorI64,
PythonMapObserverI64
);
define_python_executor!(
PythonExecutorU8,
"ExecutorU8",
PythonExecutorWrapperU8,
MyStdStateU8,
MyStdFuzzerU8,
PythonEventManagerU8,
PythonOwnedInProcessExecutorU8,
PythonMapObserverU8
);
define_python_executor!(
PythonExecutorU16,
"ExecutorU16",
PythonExecutorWrapperU16,
MyStdStateU16,
MyStdFuzzerU16,
PythonEventManagerU16,
PythonOwnedInProcessExecutorU16,
PythonMapObserverU16
);
define_python_executor!(
PythonExecutorU32,
"ExecutorU32",
PythonExecutorWrapperU32,
MyStdStateU32,
MyStdFuzzerU32,
PythonEventManagerU32,
PythonOwnedInProcessExecutorU32,
PythonMapObserverU32
);
define_python_executor!(
PythonExecutorU64,
"ExecutorU64",
PythonExecutorWrapperU64,
MyStdStateU64,
MyStdFuzzerU64,
PythonEventManagerU64,
PythonOwnedInProcessExecutorU64,
PythonMapObserverU64
PythonExecutor,
"Executor",
PythonExecutorWrapper,
PythonStdState,
PythonStdFuzzer,
PythonEventManager,
PythonOwnedInProcessExecutor,
PythonObserver
);
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonExecutorI8>()?;
m.add_class::<PythonExecutorI16>()?;
m.add_class::<PythonExecutorI32>()?;
m.add_class::<PythonExecutorI64>()?;
m.add_class::<PythonExecutorU8>()?;
m.add_class::<PythonExecutorU16>()?;
m.add_class::<PythonExecutorU32>()?;
m.add_class::<PythonExecutorU64>()?;
m.add_class::<PythonExecutor>()?;
Ok(())
}
}

View File

@ -7,24 +7,24 @@ use alloc::{
use core::ops::{BitAnd, BitOr};
use core::{fmt::Debug, marker::PhantomData};
use num_traits::PrimInt;
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
bolts::{
tuples::{MatchName, Named},
AsMutSlice, AsRefIterator, AsSlice, HasRefCnt,
},
bolts::{tuples::Named, AsMutSlice, AsRefIterator, AsSlice, HasRefCnt},
corpus::Testcase,
events::{Event, EventFirer},
executors::ExitKind,
feedbacks::{Feedback, FeedbackState},
feedbacks::{Feedback, HasObserverName},
inputs::Input,
monitors::UserStats,
observers::{MapObserver, ObserversTuple},
state::{HasClientPerfMonitor, HasFeedbackStates, HasMetadata},
state::{HasClientPerfMonitor, HasMetadata, HasNamedMetadata},
Error,
};
/// The prefix of the metadata names
pub const MAPFEEDBACK_PREFIX: &str = "mapfeedback_metadata_";
/// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from ``HitcountsMapObserver``.
pub type AflMapFeedback<I, O, S, T> = MapFeedback<I, DifferentIsNovel, O, OrReducer, S, T>;
@ -272,71 +272,44 @@ impl MapNoveltiesMetadata {
}
/// The state of [`MapFeedback`]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct MapFeedbackState<T>
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: DeserializeOwned")]
pub struct MapFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize,
{
/// Contains information about untouched entries
pub history_map: Vec<T>,
/// Name identifier of this instance
pub name: String,
}
impl<T> FeedbackState for MapFeedbackState<T>
where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
{
fn reset(&mut self) -> Result<(), Error> {
self.history_map.iter_mut().for_each(|x| *x = T::default());
Ok(())
}
}
crate::impl_serdeany!(
MapFeedbackMetadata<T: Debug + Default + Copy + 'static + Serialize + DeserializeOwned>,
<u8>,<u16>,<u32>,<u64>,<i8>,<i16>,<i32>,<i64>,<f32>,<f64>,<bool>,<char>
);
impl<T> Named for MapFeedbackState<T>
impl<T> MapFeedbackMetadata<T>
where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
T: Default + Copy + 'static + Serialize + DeserializeOwned,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
}
}
impl<T> MapFeedbackState<T>
where
T: Default + Copy + 'static + Serialize + serde::de::DeserializeOwned,
{
/// Create new `MapFeedbackState`
/// Create new `MapFeedbackMetadata`
#[must_use]
pub fn new(name: &'static str, map_size: usize) -> Self {
pub fn new(map_size: usize) -> Self {
Self {
history_map: vec![T::default(); map_size],
name: name.to_string(),
}
}
/// Create new `MapFeedbackState` for the observer type.
pub fn with_observer<O>(map_observer: &O) -> Self
where
O: MapObserver<Entry = T>,
T: PartialEq + Debug,
{
Self {
history_map: vec![map_observer.initial(); map_observer.len()],
name: map_observer.name().to_string(),
}
}
/// Create new `MapFeedbackState` using a name and a map.
/// Create new `MapFeedbackMetadata` using a name and a map.
/// The map can be shared.
#[must_use]
pub fn with_history_map(name: &'static str, history_map: Vec<T>) -> Self {
Self {
history_map,
name: name.to_string(),
pub fn with_history_map(history_map: Vec<T>) -> Self {
Self { history_map }
}
/// Reset the map
pub fn reset(&mut self) -> Result<(), Error> {
self.history_map.iter_mut().for_each(|x| *x = T::default());
Ok(())
}
}
@ -344,12 +317,12 @@ where
#[derive(Clone, Debug)]
pub struct MapFeedback<I, N, O, R, S, T>
where
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsRefIterator<'it, Item = T>,
N: IsNovel<T>,
S: HasFeedbackStates,
S: HasNamedMetadata,
{
/// Indexes used in the last observation
indexes: Option<Vec<usize>>,
@ -365,14 +338,19 @@ where
impl<I, N, O, R, S, T> Feedback<I, S> for MapFeedback<I, N, O, R, S, T>
where
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsRefIterator<'it, Item = T>,
N: IsNovel<T>,
I: Input,
S: HasFeedbackStates + HasClientPerfMonitor + Debug,
S: HasNamedMetadata + HasClientPerfMonitor + Debug,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_named_metadata(MapFeedbackMetadata::<T>::default(), &self.name);
Ok(())
}
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
@ -393,11 +371,14 @@ where
let initial = observer.initial();
let map_state = state
.feedback_states_mut()
.match_name_mut::<MapFeedbackState<T>>(&self.name)
.named_metadata_mut()
.get_mut::<MapFeedbackMetadata<T>>(&self.name)
.unwrap();
if map_state.history_map.len() < observer.len() {
map_state.history_map.resize(observer.len(), T::default());
}
assert!(size <= map_state.history_map.len(), "The size of the associated map observer cannot exceed the size of the history map of the feedback. If you are running multiple instances of slightly different fuzzers (e.g. one with ASan and another without) synchronized using LLMP please check the `configuration` field of the LLMP manager.");
// assert!(size <= map_state.history_map.len(), "The size of the associated map observer cannot exceed the size of the history map of the feedback. If you are running multiple instances of slightly different fuzzers (e.g. one with ASan and another without) synchronized using LLMP please check the `configuration` field of the LLMP manager.");
assert!(size <= observer.len());
@ -471,12 +452,12 @@ where
impl<I, N, O, R, S, T> Named for MapFeedback<I, N, O, R, S, T>
where
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
N: IsNovel<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsRefIterator<'it, Item = T>,
S: HasFeedbackStates,
S: HasNamedMetadata,
{
#[inline]
fn name(&self) -> &str {
@ -484,22 +465,37 @@ where
}
}
impl<I, N, O, R, S, T> MapFeedback<I, N, O, R, S, T>
impl<I, N, O, R, S, T> HasObserverName for MapFeedback<I, N, O, R, S, T>
where
T: PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
N: IsNovel<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsRefIterator<'it, Item = T>,
S: HasFeedbackStates,
S: HasNamedMetadata,
{
#[inline]
fn observer_name(&self) -> &str {
self.observer_name.as_str()
}
}
impl<I, N, O, R, S, T> MapFeedback<I, N, O, R, S, T>
where
T: PartialEq + Default + Copy + 'static + Serialize + DeserializeOwned + Debug,
R: Reducer<T>,
N: IsNovel<T>,
O: MapObserver<Entry = T>,
for<'it> O: AsRefIterator<'it, Item = T>,
S: HasNamedMetadata,
{
/// Create new `MapFeedback`
#[must_use]
pub fn new(feedback_state: &MapFeedbackState<T>, map_observer: &O) -> Self {
pub fn new(map_observer: &O) -> Self {
Self {
indexes: None,
novelties: None,
name: feedback_state.name().to_string(),
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
observer_name: map_observer.name().to_string(),
phantom: PhantomData,
}
@ -507,16 +503,11 @@ where
/// Create new `MapFeedback` specifying if it must track indexes of used entries and/or novelties
#[must_use]
pub fn new_tracking(
feedback_state: &MapFeedbackState<T>,
map_observer: &O,
track_indexes: bool,
track_novelties: bool,
) -> Self {
pub fn new_tracking(map_observer: &O, track_indexes: bool, track_novelties: bool) -> Self {
Self {
indexes: if track_indexes { Some(vec![]) } else { None },
novelties: if track_novelties { Some(vec![]) } else { None },
name: feedback_state.name().to_string(),
name: MAPFEEDBACK_PREFIX.to_string() + map_observer.name(),
observer_name: map_observer.name().to_string(),
phantom: PhantomData,
}
@ -673,10 +664,303 @@ mod tests {
}
}
/// `MapFeedback` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
use crate::bolts::{tuples::Named, AsMutIterator, AsRefIterator, HasLen};
use crate::observers::{map::OwnedMapObserver, MapObserver, Observer};
use crate::Error;
use pyo3::prelude::*;
use serde::{Deserialize, Serialize};
use std::slice::{Iter, IterMut};
macro_rules! define_python_map_observer {
($struct_name:ident, $py_name:tt, $struct_name_trait:ident, $py_name_trait:tt, $datatype:ty, $wrapper_name: ident) => {
#[pyclass(unsendable, name = $py_name)]
#[derive(Serialize, Deserialize, Debug, Clone)]
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
pub struct $struct_name {
/// Rust wrapped OwnedMapObserver object
pub inner: OwnedMapObserver<$datatype>,
}
#[pymethods]
impl $struct_name {
#[new]
fn new(name: String, map: Vec<$datatype>) -> Self {
Self {
//TODO: Not leak memory
inner: OwnedMapObserver::new(Box::leak(name.into_boxed_str()), map),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
enum $wrapper_name {
Owned($struct_name),
}
// Should not be exposed to user
#[pyclass(unsendable, name = $py_name_trait)]
#[derive(Serialize, Deserialize, Debug, Clone)]
/// MapObserver + Observer Trait binding
pub struct $struct_name_trait {
pub wrapper: $wrapper_name,
}
impl $struct_name_trait {
fn unwrap(&self) -> &impl MapObserver<Entry = $datatype> {
unsafe {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
}
}
}
fn unwrap_mut(&mut self) -> &mut impl MapObserver<Entry = $datatype> {
unsafe {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
}
}
}
fn upcast<S>(&self) -> &impl Observer<BytesInput, S> {
unsafe {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
}
}
}
fn upcast_mut<S>(&mut self) -> &mut impl Observer<BytesInput, S> {
unsafe {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
}
}
}
}
#[pymethods]
impl $struct_name_trait {
#[staticmethod]
fn new_from_owned(owned_map: $struct_name) -> Self {
Self {
wrapper: $wrapper_name::Owned(owned_map),
}
}
}
impl<'it> AsRefIterator<'it> for $struct_name_trait {
type Item = $datatype;
type IntoIter = Iter<'it, $datatype>;
fn as_ref_iter(&'it self) -> Self::IntoIter {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_ref_iter(),
}
}
}
impl<'it> AsMutIterator<'it> for $struct_name_trait {
type Item = $datatype;
type IntoIter = IterMut<'it, $datatype>;
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_mut_iter(),
}
}
}
impl MapObserver for $struct_name_trait {
type Entry = $datatype;
#[inline]
fn get(&self, idx: usize) -> &$datatype {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner.get(idx),
}
}
#[inline]
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.get_mut(idx),
}
}
#[inline]
fn usable_count(&self) -> usize {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.wrapper.usable_count(),
}
}
fn hash(&self) -> u64 {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.hash(),
}
}
#[inline]
fn initial(&self) -> $datatype {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial(),
}
}
#[inline]
fn initial_mut(&mut self) -> &mut $datatype {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial_mut(),
}
}
#[inline]
fn set_initial(&mut self, initial: $datatype) {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => {
py_wrapper.inner.set_initial(initial);
}
}
}
fn to_vec(&self) -> Vec<$datatype> {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.to_vec(),
}
}
}
impl Named for $struct_name_trait {
#[inline]
fn name(&self) -> &str {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.name(),
}
}
}
impl HasLen for $struct_name_trait {
#[inline]
fn len(&self) -> usize {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.len(),
}
}
}
impl<I, S> Observer<I, S> for $struct_name_trait
where
Self: MapObserver,
{
#[inline]
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => {
py_wrapper.inner.pre_exec(_state, _input)
}
}
}
}
};
}
define_python_map_observer!(
PythonOwnedMapObserverI8,
"OwnedMapObserverI8",
PythonMapObserverI8,
"MapObserverI8",
i8,
PythonMapObserverWrapperI8
);
define_python_map_observer!(
PythonOwnedMapObserverI16,
"OwnedMapObserverI16",
PythonMapObserverI16,
"MapObserverI16",
i16,
PythonMapObserverWrapperI16
);
define_python_map_observer!(
PythonOwnedMapObserverI32,
"OwnedMapObserverI32",
PythonMapObserverI32,
"MapObserverI32",
i32,
PythonMapObserverWrapperI32
);
define_python_map_observer!(
PythonOwnedMapObserverI64,
"OwnedMapObserverI64",
PythonMapObserverI64,
"MapObserverI64",
i64,
PythonMapObserverWrapperI64
);
define_python_map_observer!(
PythonOwnedMapObserverU8,
"OwnedMapObserverU8",
PythonMapObserverU8,
"MapObserverU8",
u8,
PythonMapObserverWrapperU8
);
define_python_map_observer!(
PythonOwnedMapObserverU16,
"OwnedMapObserverU16",
PythonMapObserverU16,
"MapObserverU16",
u16,
PythonMapObserverWrapperU16
);
define_python_map_observer!(
PythonOwnedMapObserverU32,
"OwnedMapObserverU32",
PythonMapObserverU32,
"MapObserverU32",
u32,
PythonMapObserverWrapperU32
);
define_python_map_observer!(
PythonOwnedMapObserverU64,
"OwnedMapObserverU64",
PythonMapObserverU64,
"MapObserverU64",
u64,
PythonMapObserverWrapperU64
);
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonOwnedMapObserverI8>()?;
m.add_class::<PythonMapObserverI8>()?;
m.add_class::<PythonOwnedMapObserverI16>()?;
m.add_class::<PythonMapObserverI16>()?;
m.add_class::<PythonOwnedMapObserverI32>()?;
m.add_class::<PythonMapObserverI32>()?;
m.add_class::<PythonOwnedMapObserverI64>()?;
m.add_class::<PythonMapObserverI64>()?;
m.add_class::<PythonOwnedMapObserverU8>()?;
m.add_class::<PythonMapObserverU8>()?;
m.add_class::<PythonOwnedMapObserverU16>()?;
m.add_class::<PythonMapObserverU16>()?;
m.add_class::<PythonOwnedMapObserverU32>()?;
m.add_class::<PythonMapObserverU32>()?;
m.add_class::<PythonOwnedMapObserverU64>()?;
m.add_class::<PythonMapObserverU64>()?;
Ok(())
}
}
#[cfg(feature = "python")]
/// Map Feedback Python bindings
pub mod pybind {
use crate::feedbacks::map::{MapFeedbackState, MaxMapFeedback};
use crate::feedbacks::map::{MapFeedbackMetadata, MaxMapFeedback};
use crate::inputs::BytesInput;
use pyo3::prelude::*;
@ -688,10 +972,10 @@ pub mod pybind {
#[pyclass(unsendable, name = $map_feedback_state_py_name)]
#[derive(Clone, Debug)]
/// Python class for MapFeedbackState
/// Python class for MapFeedbackMetadata
pub struct $map_feedback_state_struct_name {
/// Rust wrapped MapFeedbackState object
pub map_feedback_state: MapFeedbackState<$datatype>,
/// Rust wrapped MapFeedbackMetadata object
pub map_feedback_state: MapFeedbackMetadata<$datatype>,
}
#[pymethods]
@ -699,7 +983,7 @@ pub mod pybind {
#[staticmethod]
fn with_observer(py_observer: &$map_observer_name) -> Self {
Self {
map_feedback_state: MapFeedbackState::with_observer(py_observer),
map_feedback_state: MapFeedbackMetadata::with_observer(py_observer),
}
}
}
@ -740,8 +1024,8 @@ pub mod pybind {
}
define_python_map_feedback!(
PythonMapFeedbackStateI8,
"MapFeedbackStateI8",
PythonMapFeedbackMetadataI8,
"MapFeedbackMetadataI8",
PythonMaxMapFeedbackI8,
"MaxMapFeedbackI8",
i8,
@ -750,8 +1034,8 @@ pub mod pybind {
);
define_python_map_feedback!(
PythonMapFeedbackStateI16,
"MapFeedbackStateI16",
PythonMapFeedbackMetadataI16,
"MapFeedbackMetadataI16",
PythonMaxMapFeedbackI16,
"MaxMapFeedbackI16",
i16,
@ -759,8 +1043,8 @@ pub mod pybind {
MyStdStateI16
);
define_python_map_feedback!(
PythonMapFeedbackStateI32,
"MapFeedbackStateI32",
PythonMapFeedbackMetadataI32,
"MapFeedbackMetadataI32",
PythonMaxMapFeedbackI32,
"MaxMapFeedbackI32",
i32,
@ -768,8 +1052,8 @@ pub mod pybind {
MyStdStateI32
);
define_python_map_feedback!(
PythonMapFeedbackStateI64,
"MapFeedbackStateI64",
PythonMapFeedbackMetadataI64,
"MapFeedbackMetadataI64",
PythonMaxMapFeedbackI64,
"MaxMapFeedbackI64",
i64,
@ -778,8 +1062,8 @@ pub mod pybind {
);
define_python_map_feedback!(
PythonMapFeedbackStateU8,
"MapFeedbackStateU8",
PythonMapFeedbackMetadataU8,
"MapFeedbackMetadataU8",
PythonMaxMapFeedbackU8,
"MaxMapFeedbackU8",
u8,
@ -788,8 +1072,8 @@ pub mod pybind {
);
define_python_map_feedback!(
PythonMapFeedbackStateU16,
"MapFeedbackStateU16",
PythonMapFeedbackMetadataU16,
"MapFeedbackMetadataU16",
PythonMaxMapFeedbackU16,
"MaxMapFeedbackU16",
u16,
@ -797,8 +1081,8 @@ pub mod pybind {
MyStdStateU16
);
define_python_map_feedback!(
PythonMapFeedbackStateU32,
"MapFeedbackStateU32",
PythonMapFeedbackMetadataU32,
"MapFeedbackMetadataU32",
PythonMaxMapFeedbackU32,
"MaxMapFeedbackU32",
u32,
@ -806,8 +1090,8 @@ pub mod pybind {
MyStdStateU32
);
define_python_map_feedback!(
PythonMapFeedbackStateU64,
"MapFeedbackStateU64",
PythonMapFeedbackMetadataU64,
"MapFeedbackMetadataU64",
PythonMaxMapFeedbackU64,
"MaxMapFeedbackU64",
u64,
@ -817,15 +1101,15 @@ pub mod pybind {
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonMapFeedbackStateI8>()?;
m.add_class::<PythonMapFeedbackStateI16>()?;
m.add_class::<PythonMapFeedbackStateI32>()?;
m.add_class::<PythonMapFeedbackStateI64>()?;
m.add_class::<PythonMapFeedbackMetadataI8>()?;
m.add_class::<PythonMapFeedbackMetadataI16>()?;
m.add_class::<PythonMapFeedbackMetadataI32>()?;
m.add_class::<PythonMapFeedbackMetadataI64>()?;
m.add_class::<PythonMapFeedbackStateU8>()?;
m.add_class::<PythonMapFeedbackStateU16>()?;
m.add_class::<PythonMapFeedbackStateU32>()?;
m.add_class::<PythonMapFeedbackStateU64>()?;
m.add_class::<PythonMapFeedbackMetadataU8>()?;
m.add_class::<PythonMapFeedbackMetadataU16>()?;
m.add_class::<PythonMapFeedbackMetadataU32>()?;
m.add_class::<PythonMapFeedbackMetadataU64>()?;
m.add_class::<PythonMaxMapFeedbackI8>()?;
m.add_class::<PythonMaxMapFeedbackI16>()?;

View File

@ -16,7 +16,7 @@ pub mod new_hash_feedback;
#[cfg(feature = "std")]
pub use new_hash_feedback::NewHashFeedback;
#[cfg(feature = "std")]
pub use new_hash_feedback::NewHashFeedbackState;
pub use new_hash_feedback::NewHashFeedbackMetadata;
#[cfg(feature = "nautilus")]
pub mod nautilus;
@ -27,7 +27,7 @@ use alloc::string::{String, ToString};
use serde::{Deserialize, Serialize};
use crate::{
bolts::tuples::{MatchName, Named},
bolts::tuples::Named,
corpus::Testcase,
events::EventFirer,
executors::ExitKind,
@ -51,6 +51,12 @@ where
I: Input,
S: HasClientPerfMonitor,
{
/// Initializes the feedback state.
/// This method is called after that the `State` is created.
fn init_state(&mut self, _state: &mut S) -> Result<(), Error> {
Ok(())
}
/// `is_interesting ` return if an input is worth the addition to the corpus
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
@ -116,36 +122,10 @@ where
}
}
/// [`FeedbackState`] is the data associated with a [`Feedback`] that must persist as part
/// of the fuzzer State
pub trait FeedbackState: Named + Serialize + serde::de::DeserializeOwned + Debug {
/// Reset the internal state
fn reset(&mut self) -> Result<(), Error> {
Ok(())
}
}
/// A haskell-style tuple of feedback states
pub trait FeedbackStatesTuple: MatchName + Serialize + serde::de::DeserializeOwned + Debug {
/// Resets all the feedback states of the tuple
fn reset_all(&mut self) -> Result<(), Error>;
}
impl FeedbackStatesTuple for () {
fn reset_all(&mut self) -> Result<(), Error> {
Ok(())
}
}
impl<Head, Tail> FeedbackStatesTuple for (Head, Tail)
where
Head: FeedbackState,
Tail: FeedbackStatesTuple,
{
fn reset_all(&mut self) -> Result<(), Error> {
self.0.reset()?;
self.1.reset_all()
}
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
pub trait HasObserverName {
/// The name associated with the observer
fn observer_name(&self) -> &str;
}
/// A combined feedback consisting of multiple [`Feedback`]s
@ -207,6 +187,12 @@ where
I: Input,
S: HasClientPerfMonitor + Debug,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
self.first.init_state(state)?;
self.second.init_state(state)?;
Ok(())
}
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
@ -596,6 +582,10 @@ where
I: Input,
S: HasClientPerfMonitor,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
self.first.init_state(state)
}
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
@ -984,3 +974,177 @@ where
}
}
}
/// The [`ConstFeedback`] reports the same value, always.
/// It can be used to enable or disable feedback results through composition.
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)]
pub enum ConstFeedback {
/// Always returns `true`
True,
/// Alsways returns `false`
False,
}
impl<I, S> Feedback<I, S> for ConstFeedback
where
I: Input,
S: HasClientPerfMonitor,
{
#[inline]
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
_manager: &mut EM,
_input: &I,
_observers: &OT,
_exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<I>,
OT: ObserversTuple<I, S>,
{
Ok(match self {
ConstFeedback::True => true,
ConstFeedback::False => false,
})
}
}
impl Named for ConstFeedback {
#[inline]
fn name(&self) -> &str {
"ConstFeedback"
}
}
impl ConstFeedback {
/// Creates a new [`ConstFeedback`] from the given boolean
#[must_use]
pub fn new(val: bool) -> Self {
Self::from(val)
}
}
impl From<bool> for ConstFeedback {
fn from(val: bool) -> Self {
if val {
Self::True
} else {
Self::False
}
}
}
/// `Feedback` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
use crate::inputs::BytesInput;
use crate::{
bolts::tuples::Named, corpus::Testcase, events::EventFirer, executors::ExitKind,
feedbacks::Feedback, observers::ObserversTuple, Error,
};
use pyo3::prelude::*;
macro_rules! define_python_feedback {
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident) => {
use crate::observers::map::pybind::PythonMaxMapFeedbackI8;
use crate::state::pybind::$my_std_state_type_name;
#[derive(Debug)]
enum $wrapper_name {
MaxMapI8(*mut PythonMaxMapFeedbackI8),
}
#[pyclass(unsendable, name = $py_name_trait)]
#[derive(Debug)]
/// Observer Trait binding
pub struct $struct_name_trait {
pub wrapper: $wrapper_name,
}
impl $struct_name_trait {
fn unwrap(&self) -> &impl Feedback<BytesInput, $my_std_state_type_name> {
unsafe {
match self.wrapper {
$wrapper_name::MaxMapI8(py_wrapper) => &(*py_wrapper).upcast(),
}
}
}
fn unwrap_mut(
&mut self,
) -> &mut impl Feedback<BytesInput, $my_std_state_type_name> {
unsafe {
match self.wrapper {
$wrapper_name::MaxMapI8(py_wrapper) => &mut (*py_wrapper).upcast_mut(),
}
}
}
}
#[pymethods]
impl $struct_name_trait {
#[staticmethod]
fn new_map(map_feedback: &mut PythonMaxMapFeedbackI8) -> Self {
Self {
observer: $wrapper_name::MaxMapI8(map_feedback),
}
}
}
impl Named for $struct_name_trait {
fn name(&self) -> &str {
self.unwrap().name()
}
}
impl Feedback<BytesInput, $my_std_state_type_name> for $struct_name_trait {
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
self.unwrap_mut().init_state(state)
}
fn is_interesting<EM, OT>(
&mut self,
state: &mut S,
manager: &mut EM,
input: &I,
observers: &OT,
exit_kind: &ExitKind,
) -> Result<bool, Error>
where
EM: EventFirer<I>,
OT: ObserversTuple<I, S>,
{
self.unwrap_mut()
.is_interesting(state, manager, input, observers, exit_kind)
}
fn append_metadata(
&mut self,
state: &mut S,
testcase: &mut Testcase<I>,
) -> Result<(), Error> {
self.unwrap_mut().append_metadata(state, testcase)
}
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.unwrap_mut().discard_metadata(state, input)
}
}
};
}
define_python_feedback!(
PythonFeedback,
"Feedback",
PythonFeedbackWrapper,
PythonStdState,
);
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonFeedback>()?;
Ok(())
}
}

View File

@ -1,98 +1,64 @@
//! The ``NewHashFeedback`` uses the backtrace hash and a hashset to only keep novel cases
use std::{fmt::Debug, hash::Hash, marker::PhantomData};
use std::{fmt::Debug, marker::PhantomData};
use hashbrown::HashSet;
use num_traits::PrimInt;
use serde::{Deserialize, Serialize};
use crate::{
bolts::tuples::{MatchName, Named},
bolts::tuples::Named,
events::EventFirer,
executors::ExitKind,
feedbacks::{Feedback, FeedbackState},
feedbacks::{Feedback, HasObserverName},
inputs::Input,
observers::{ObserverWithHashField, ObserversTuple},
state::{HasClientPerfMonitor, HasFeedbackStates},
state::{HasClientPerfMonitor, HasNamedMetadata},
Error,
};
/// The prefix of the metadata names
pub const NEWHASHFEEDBACK_PREFIX: &str = "newhashfeedback_metadata_";
/// A state that implements this trait has a hash set
pub trait HashSetState<T> {
/// creates a new instance with a specific hashset
fn with_hash_set(name: &'static str, hash_set: HashSet<T>) -> Self;
fn with_hash_set(hash_set: HashSet<T>) -> Self;
/// updates the `hash_set` with the given value
fn update_hash_set(&mut self, value: T) -> Result<bool, Error>;
}
/// The state of [`NewHashFeedback`]
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "T: serde::de::DeserializeOwned")]
pub struct NewHashFeedbackState<T>
where
T: PrimInt + Default + Copy + 'static + Serialize + Hash + Debug,
{
#[derive(Default, Serialize, Deserialize, Clone, Debug)]
pub struct NewHashFeedbackMetadata {
/// Contains information about untouched entries
pub hash_set: HashSet<T>,
/// Name identifier of this instance
pub name: String,
pub hash_set: HashSet<u64>,
}
impl<T> FeedbackState for NewHashFeedbackState<T>
where
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
{
fn reset(&mut self) -> Result<(), Error> {
#[rustfmt::skip]
crate::impl_serdeany!(NewHashFeedbackMetadata);
impl NewHashFeedbackMetadata {
/// Create a new [`NewHashFeedbackMetadata`]
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Reset the internal state
pub fn reset(&mut self) -> Result<(), Error> {
self.hash_set.clear();
Ok(())
}
}
impl<T> Named for NewHashFeedbackState<T>
where
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
{
#[inline]
fn name(&self) -> &str {
self.name.as_str()
}
}
impl<T> NewHashFeedbackState<T>
where
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
{
/// Create a new [`NewHashFeedbackState`]
impl HashSetState<u64> for NewHashFeedbackMetadata {
/// Create new [`NewHashFeedbackMetadata`] using a name and a hash set.
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
hash_set: HashSet::<T>::new(),
name: name.to_string(),
}
fn with_hash_set(hash_set: HashSet<u64>) -> Self {
Self { hash_set }
}
/// Create a new [`NewHashFeedbackState`] for an observer that implements [`ObserverWithHashField`]
pub fn with_observer(backtrace_observer: &(impl ObserverWithHashField + Named)) -> Self {
Self {
hash_set: HashSet::<T>::new(),
name: backtrace_observer.name().to_string(),
}
}
}
impl<T> HashSetState<T> for NewHashFeedbackState<T>
where
T: PrimInt + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Hash + Debug,
{
/// Create new [`NewHashFeedbackState`] using a name and a hash set.
#[must_use]
fn with_hash_set(name: &'static str, hash_set: HashSet<T>) -> Self {
Self {
hash_set,
name: name.to_string(),
}
}
fn update_hash_set(&mut self, value: T) -> Result<bool, Error> {
fn update_hash_set(&mut self, value: u64) -> Result<bool, Error> {
let r = self.hash_set.insert(value);
// println!("Got r={}, the hashset is {:?}", r, &self.hash_set);
Ok(r)
@ -102,7 +68,7 @@ where
/// A [`NewHashFeedback`] maintains a hashset of already seen stacktraces and considers interesting unseen ones
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NewHashFeedback<O> {
feedback_name: String,
name: String,
observer_name: String,
o_type: PhantomData<O>,
}
@ -110,13 +76,18 @@ pub struct NewHashFeedback<O> {
impl<I, S, O> Feedback<I, S> for NewHashFeedback<O>
where
I: Input,
S: HasClientPerfMonitor + HasFeedbackStates,
S: HasClientPerfMonitor + HasNamedMetadata,
O: ObserverWithHashField + Named + Debug,
{
fn init_state(&mut self, state: &mut S) -> Result<(), Error> {
state.add_named_metadata(NewHashFeedbackMetadata::default(), &self.name);
Ok(())
}
#[allow(clippy::wrong_self_convention)]
fn is_interesting<EM, OT>(
&mut self,
_state: &mut S,
state: &mut S,
_manager: &mut EM,
_input: &I,
observers: &OT,
@ -130,9 +101,9 @@ where
.match_name::<O>(&self.observer_name)
.expect("A NewHashFeedback needs a BacktraceObserver");
let backtrace_state = _state
.feedback_states_mut()
.match_name_mut::<NewHashFeedbackState<u64>>(&self.observer_name)
let backtrace_state = state
.named_metadata_mut()
.get_mut::<NewHashFeedbackMetadata>(&self.name)
.unwrap();
match observer.hash() {
@ -153,7 +124,14 @@ where
impl<O> Named for NewHashFeedback<O> {
#[inline]
fn name(&self) -> &str {
&self.feedback_name
&self.name
}
}
impl<O> HasObserverName for NewHashFeedback<O> {
#[inline]
fn observer_name(&self) -> &str {
&self.observer_name
}
}
@ -161,12 +139,12 @@ impl<O> NewHashFeedback<O>
where
O: ObserverWithHashField + Named + Debug,
{
/// Returns a new [`NewHashFeedback`]. Carefull, it's recommended to use `new_with_observer`
/// Returns a new [`NewHashFeedback`].
/// Setting an observer name that doesn't exist would eventually trigger a panic.
#[must_use]
pub fn new(feedback_name: &str, observer_name: &str) -> Self {
pub fn with_names(name: &str, observer_name: &str) -> Self {
Self {
feedback_name: feedback_name.to_string(),
name: name.to_string(),
observer_name: observer_name.to_string(),
o_type: PhantomData,
}
@ -174,9 +152,9 @@ where
/// Returns a new [`NewHashFeedback`].
#[must_use]
pub fn new_with_observer(feedback_name: &str, observer: &O) -> Self {
pub fn new(observer: &O) -> Self {
Self {
feedback_name: feedback_name.to_string(),
name: NEWHASHFEEDBACK_PREFIX.to_string() + observer.name(),
observer_name: observer.name().to_string(),
o_type: PhantomData,
}

View 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(())
}
}

View File

@ -70,10 +70,10 @@ Welcome to `LibAFL`
)]
#[macro_use]
extern crate alloc;
pub extern crate alloc;
#[macro_use]
extern crate static_assertions;
#[cfg(feature = "std")]
#[cfg(feature = "ctor")]
pub use ctor::ctor;
// Re-export derive(SerdeAny)
@ -407,8 +407,10 @@ mod tests {
rand,
corpus,
InMemoryCorpus::<BytesInput>::new(),
tuple_list!(),
);
&mut (),
&mut (),
)
.unwrap();
let monitor = SimpleMonitor::new(|s| {
println!("{}", s);
@ -440,7 +442,6 @@ mod tests {
let state_serialized = postcard::to_allocvec(&state).unwrap();
let state_deserialized: StdState<
InMemoryCorpus<BytesInput>,
(),
BytesInput,
StdRand,
InMemoryCorpus<BytesInput>,

View File

@ -1230,7 +1230,8 @@ mod tests {
.add(BytesInput::new(vec![0x42; 0x1337]).into())
.unwrap();
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
let mut state =
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
let mut mutations = test_mutations();
for _ in 0..2 {

View File

@ -447,7 +447,8 @@ mod tests {
let testcase = corpus.get(0).expect("Corpus did not contain entries");
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
let mut state =
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
rand.set_seed(5);
@ -474,7 +475,8 @@ mod tests {
let mut input = testcase.borrow_mut().load_input().unwrap().clone();
let input_prior = input.clone();
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
let mut state =
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
let mut havoc = StdScheduledMutator::new(havoc_mutations());

View File

@ -1487,6 +1487,7 @@ where
}
}
}
/// `MapObserver` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
@ -1504,7 +1505,7 @@ pub mod pybind {
/// Python class for OwnedMapObserver (i.e. StdMapObserver with owned map)
pub struct $struct_name {
/// Rust wrapped OwnedMapObserver object
pub owned_map_observer: OwnedMapObserver<$datatype>,
pub inner: OwnedMapObserver<$datatype>,
}
#[pymethods]
@ -1513,10 +1514,7 @@ pub mod pybind {
fn new(name: String, map: Vec<$datatype>) -> Self {
Self {
//TODO: Not leak memory
owned_map_observer: OwnedMapObserver::new(
Box::leak(name.into_boxed_str()),
map,
),
inner: OwnedMapObserver::new(Box::leak(name.into_boxed_str()), map),
}
}
}
@ -1531,15 +1529,49 @@ pub mod pybind {
#[derive(Serialize, Deserialize, Debug, Clone)]
/// MapObserver + Observer Trait binding
pub struct $struct_name_trait {
map_observer: $wrapper_name,
pub wrapper: $wrapper_name,
}
impl $struct_name_trait {
fn unwrap(&self) -> &impl MapObserver<Entry = $datatype> {
unsafe {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
}
}
}
fn unwrap_mut(&mut self) -> &mut impl MapObserver<Entry = $datatype> {
unsafe {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
}
}
}
fn upcast<S>(&self) -> &impl Observer<BytesInput, S> {
unsafe {
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner,
}
}
}
fn upcast_mut<S>(&mut self) -> &mut impl Observer<BytesInput, S> {
unsafe {
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => &mut py_wrapper.inner,
}
}
}
}
#[pymethods]
impl $struct_name_trait {
#[staticmethod]
fn new_from_owned(owned_map_observer: $struct_name) -> Self {
fn new_from_owned(owned_map: $struct_name) -> Self {
Self {
map_observer: $wrapper_name::Owned(owned_map_observer),
wrapper: $wrapper_name::Owned(owned_map),
}
}
}
@ -1549,10 +1581,8 @@ pub mod pybind {
type IntoIter = Iter<'it, $datatype>;
fn as_ref_iter(&'it self) -> Self::IntoIter {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.as_ref_iter()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_ref_iter(),
}
}
}
@ -1562,10 +1592,8 @@ pub mod pybind {
type IntoIter = IterMut<'it, $datatype>;
fn as_mut_iter(&'it mut self) -> Self::IntoIter {
match &mut self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.as_mut_iter()
}
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.as_mut_iter(),
}
}
}
@ -1575,71 +1603,57 @@ pub mod pybind {
#[inline]
fn get(&self, idx: usize) -> &$datatype {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
&map_observer.owned_map_observer.get(idx)
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => &py_wrapper.inner.get(idx),
}
}
#[inline]
fn get_mut(&mut self, idx: usize) -> &mut $datatype {
match &mut self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.get_mut(idx)
}
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.get_mut(idx),
}
}
#[inline]
fn usable_count(&self) -> usize {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.usable_count()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.wrapper.usable_count(),
}
}
fn hash(&self) -> u64 {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.hash()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.hash(),
}
}
#[inline]
fn initial(&self) -> $datatype {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.initial()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial(),
}
}
#[inline]
fn initial_mut(&mut self) -> &mut $datatype {
match &mut self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.initial_mut()
}
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.initial_mut(),
}
}
#[inline]
fn set_initial(&mut self, initial: $datatype) {
match &mut self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.set_initial(initial);
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => {
py_wrapper.inner.set_initial(initial);
}
}
}
fn to_vec(&self) -> Vec<$datatype> {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.to_vec()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.to_vec(),
}
}
}
@ -1647,10 +1661,8 @@ pub mod pybind {
impl Named for $struct_name_trait {
#[inline]
fn name(&self) -> &str {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.name()
}
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.name(),
}
}
}
@ -1658,8 +1670,8 @@ pub mod pybind {
impl HasLen for $struct_name_trait {
#[inline]
fn len(&self) -> usize {
match &self.map_observer {
$wrapper_name::Owned(map_observer) => map_observer.owned_map_observer.len(),
match &self.wrapper {
$wrapper_name::Owned(py_wrapper) => py_wrapper.inner.len(),
}
}
}
@ -1670,9 +1682,9 @@ pub mod pybind {
{
#[inline]
fn pre_exec(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
match &mut self.map_observer {
$wrapper_name::Owned(map_observer) => {
map_observer.owned_map_observer.pre_exec(_state, _input)
match &mut self.wrapper {
$wrapper_name::Owned(py_wrapper) => {
py_wrapper.inner.pre_exec(_state, _input)
}
}
}

View File

@ -290,6 +290,125 @@ where
}
}
/// `Observer` Python bindings
#[cfg(feature = "python")]
pub mod pybind {
use crate::bolts::tuples::Named;
use crate::executors::ExitKind;
use crate::inputs::BytesInput;
use crate::observers::Observer;
use crate::Error;
use pyo3::prelude::*;
macro_rules! define_python_observer {
($struct_name_trait:ident, $py_name_trait:tt, $wrapper_name: ident, $my_std_state_type_name: ident) => {
use crate::observers::map::pybind::PythonMapObserverI8;
use crate::state::pybind::$my_std_state_type_name;
#[derive(Debug)]
enum $wrapper_name {
MapI8(*mut PythonMapObserverI8),
}
#[pyclass(unsendable, name = $py_name_trait)]
#[derive(Debug)]
/// Observer Trait binding
pub struct $struct_name_trait {
pub wrapper: $wrapper_name,
}
impl $struct_name_trait {
fn unwrap(&self) -> &impl Observer<BytesInput, $my_std_state_type_name> {
unsafe {
match self.wrapper {
$wrapper_name::MapI8(py_wrapper) => &(*py_wrapper).upcast(),
}
}
}
fn unwrap_mut(
&mut self,
) -> &mut impl Observer<BytesInput, $my_std_state_type_name> {
unsafe {
match self.wrapper {
$wrapper_name::MapI8(py_wrapper) => &mut (*py_wrapper).upcast_mut(),
}
}
}
}
#[pymethods]
impl $struct_name_trait {
#[staticmethod]
fn new_map(map_observer: &mut PythonMapObserverI8) -> Self {
Self {
observer: $wrapper_name::MapI8(map_observer),
}
}
}
impl Named for $struct_name_trait {
fn name(&self) -> &str {
self.unwrap().name()
}
}
impl Observer<BytesInput, $my_std_state_type_name> for $struct_name_trait {
fn flush(&mut self) -> Result<(), Error> {
self.unwrap_mut().flush()
}
fn pre_exec(
&mut self,
state: &mut $my_std_state_type_name,
input: &BytesInput,
) -> Result<(), Error> {
self.unwrap_mut().pre_exec(state, input)
}
fn post_exec(
&mut self,
state: &mut $my_std_state_type_name,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.unwrap_mut().post_exec(state, input, exit_kind)
}
fn pre_exec_child(
&mut self,
state: &mut $my_std_state_type_name,
input: &BytesInput,
) -> Result<(), Error> {
self.unwrap_mut().pre_exec(state, input)
}
fn post_exec_child(
&mut self,
state: &mut $my_std_state_type_name,
input: &BytesInput,
exit_kind: &ExitKind,
) -> Result<(), Error> {
self.unwrap_mut().post_exec_child(state, input, exit_kind)
}
}
};
}
define_python_observer!(
PythonObserver,
"Observer",
PythonObserverWrapper,
PythonStdState,
);
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonObserver>()?;
Ok(())
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {

View File

@ -188,7 +188,8 @@ mod tests {
let idx1 = corpus.add(t1).unwrap();
let idx2 = corpus.add(t2).unwrap();
let mut state = StdState::new(rand, corpus, InMemoryCorpus::new(), ());
let mut state =
StdState::new(rand, corpus, InMemoryCorpus::new(), &mut (), &mut ()).unwrap();
scheduler.on_add(state.borrow_mut(), idx1).unwrap();
scheduler.on_add(state.borrow_mut(), idx2).unwrap();
let next_idx1 = scheduler.next(&mut state).unwrap();

View File

@ -79,7 +79,7 @@ mod tests {
OnDiskCorpus::<BytesInput>::new(PathBuf::from("target/.test/fancy/objective/path"))
.unwrap();
let mut state = StdState::new(rand, q, objective_q, ());
let mut state = StdState::new(rand, q, objective_q, &mut (), &mut ()).unwrap();
let next_idx = scheduler.next(&mut state).unwrap();
let filename = state

View File

@ -1,18 +1,20 @@
//! The calibration stage. The fuzzer measures the average exec time and the bitmap size.
use crate::{
bolts::current_time,
bolts::tuples::MatchName,
bolts::{current_time, tuples::Named, AsRefIterator},
corpus::{Corpus, SchedulerTestcaseMetaData},
events::{EventFirer, LogSeverity},
executors::{Executor, ExitKind, HasObservers},
feedbacks::MapFeedbackState,
feedbacks::{
map::{IsNovel, MapFeedback, MapFeedbackMetadata, Reducer},
HasObserverName,
},
fuzzer::Evaluator,
inputs::Input,
observers::{MapObserver, ObserversTuple},
schedulers::powersched::SchedulerMetadata,
stages::Stage,
state::{HasClientPerfMonitor, HasCorpus, HasFeedbackStates, HasMetadata},
state::{HasClientPerfMonitor, HasCorpus, HasMetadata, HasNamedMetadata},
Error,
};
use alloc::string::{String, ToString};
@ -27,9 +29,10 @@ where
I: Input,
O: MapObserver,
OT: ObserversTuple<I, S>,
S: HasCorpus<I> + HasMetadata,
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
{
map_observer_name: String,
map_name: String,
stage_max: usize,
phantom: PhantomData<(I, O, OT, S)>,
}
@ -45,7 +48,7 @@ where
O: MapObserver,
for<'de> <O as MapObserver>::Entry: Serialize + Deserialize<'de> + 'static,
OT: ObserversTuple<I, S>,
S: HasCorpus<I> + HasMetadata + HasFeedbackStates + HasClientPerfMonitor,
S: HasCorpus<I> + HasMetadata + HasClientPerfMonitor + HasNamedMetadata,
Z: Evaluator<E, EM, I, S>,
{
#[inline]
@ -147,8 +150,8 @@ where
.to_vec();
let history_map = &mut state
.feedback_states_mut()
.match_name_mut::<MapFeedbackState<O::Entry>>(&self.map_observer_name)
.named_metadata_mut()
.get_mut::<MapFeedbackMetadata<O::Entry>>(&self.map_name)
.unwrap()
.history_map;
@ -222,12 +225,21 @@ where
I: Input,
O: MapObserver,
OT: ObserversTuple<I, S>,
S: HasCorpus<I> + HasMetadata,
S: HasCorpus<I> + HasMetadata + HasNamedMetadata,
{
/// Create a new [`CalibrationStage`].
pub fn new(map_observer_name: &O) -> Self {
#[must_use]
pub fn new<N, R>(map_feedback: &MapFeedback<I, N, O, R, S, O::Entry>) -> Self
where
O::Entry:
PartialEq + Default + Copy + 'static + Serialize + serde::de::DeserializeOwned + Debug,
R: Reducer<O::Entry>,
for<'it> O: AsRefIterator<'it, Item = O::Entry>,
N: IsNovel<O::Entry>,
{
Self {
map_observer_name: map_observer_name.name().to_string(),
map_observer_name: map_feedback.observer_name().to_string(),
map_name: map_feedback.name().to_string(),
stage_max: CAL_STAGE_START,
phantom: PhantomData,
}

View File

@ -11,11 +11,11 @@ use std::{
use crate::{
bolts::{
rands::Rand,
serdeany::{SerdeAny, SerdeAnyMap},
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
},
corpus::Corpus,
events::{Event, EventFirer, LogSeverity},
feedbacks::FeedbackStatesTuple,
feedbacks::Feedback,
fuzzer::{Evaluator, ExecuteInputResult},
generators::Generator,
inputs::Input,
@ -110,15 +110,30 @@ pub trait HasMetadata {
}
}
/// Trait for elements offering a feedback
pub trait HasFeedbackStates {
/// The associated feedback type implementing [`FeedbackStatesTuple`].
type FeedbackStates: FeedbackStatesTuple;
/// The feedback states
fn feedback_states(&self) -> &Self::FeedbackStates;
/// Trait for elements offering named metadata
pub trait HasNamedMetadata {
/// A map, storing all metadata
fn named_metadata(&self) -> &NamedSerdeAnyMap;
/// A map, storing all metadata (mutable)
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap;
/// The feedback states (mutable)
fn feedback_states_mut(&mut self) -> &mut Self::FeedbackStates;
/// Add a metadata to the metadata map
#[inline]
fn add_named_metadata<M>(&mut self, meta: M, name: &str)
where
M: SerdeAny,
{
self.named_metadata_mut().insert(meta, name);
}
/// Check for a metadata
#[inline]
fn has_named_metadata<M>(&self, name: &str) -> bool
where
M: SerdeAny,
{
self.named_metadata().contains::<M>(name)
}
}
/// Trait for the execution counter
@ -141,13 +156,12 @@ pub trait HasStartTime {
/// The state a fuzz run.
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(bound = "FT: serde::de::DeserializeOwned")]
pub struct StdState<C, FT, I, R, SC>
#[serde(bound = "C: serde::Serialize + for<'a> serde::Deserialize<'a>")]
pub struct StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
/// RNG instance
@ -158,12 +172,12 @@ where
start_time: Duration,
/// The corpus
corpus: C,
/// States of the feedback used to evaluate an input
feedback_states: FT,
// Solutions corpus
solutions: SC,
/// Metadata stored for this state by one of the components
metadata: SerdeAnyMap,
/// Metadata stored with names
named_metadata: NamedSerdeAnyMap,
/// MaxSize testcase size for mutators that appreciate it
max_size: usize,
/// The stability of the current fuzzing process
@ -176,22 +190,20 @@ where
phantom: PhantomData<I>,
}
impl<C, FT, I, R, SC> State for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> State for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
}
impl<C, FT, I, R, SC> HasRand for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasRand for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
type Rand = R;
@ -209,12 +221,11 @@ where
}
}
impl<C, FT, I, R, SC> HasCorpus<I> for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasCorpus<I> for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
type Corpus = C;
@ -232,12 +243,11 @@ where
}
}
impl<C, FT, I, R, SC> HasSolutions<I> for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasSolutions<I> for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
type Solutions = SC;
@ -255,12 +265,11 @@ where
}
}
impl<C, FT, I, R, SC> HasMetadata for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasMetadata for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
/// Get all the metadata into an [`hashbrown::HashMap`]
@ -276,35 +285,31 @@ where
}
}
impl<C, FT, I, R, SC> HasFeedbackStates for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasNamedMetadata for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
type FeedbackStates = FT;
/// The feedback states
/// Get all the metadata into an [`hashbrown::HashMap`]
#[inline]
fn feedback_states(&self) -> &FT {
&self.feedback_states
fn named_metadata(&self) -> &NamedSerdeAnyMap {
&self.named_metadata
}
/// The feedback states (mutable)
/// Get all the metadata into an [`hashbrown::HashMap`] (mutable)
#[inline]
fn feedback_states_mut(&mut self) -> &mut FT {
&mut self.feedback_states
fn named_metadata_mut(&mut self) -> &mut NamedSerdeAnyMap {
&mut self.named_metadata
}
}
impl<C, FT, I, R, SC> HasExecutions for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasExecutions for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
/// The executions counter
@ -320,12 +325,11 @@ where
}
}
impl<C, FT, I, R, SC> HasMaxSize for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasMaxSize for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
fn max_size(&self) -> usize {
@ -337,12 +341,11 @@ where
}
}
impl<C, FT, I, R, SC> HasStartTime for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasStartTime for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
/// The starting time
@ -359,12 +362,11 @@ where
}
#[cfg(feature = "std")]
impl<C, FT, I, R, SC> StdState<C, FT, I, R, SC>
impl<C, I, R, SC> StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
/// Loads inputs from a directory.
@ -480,12 +482,11 @@ where
}
}
impl<C, FT, I, R, SC> StdState<C, FT, I, R, SC>
impl<C, I, R, SC> StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
fn generate_initial_internal<G, E, EM, Z>(
@ -561,31 +562,43 @@ where
}
/// Creates a new `State`, taking ownership of all of the individual components during fuzzing.
pub fn new(rand: R, corpus: C, solutions: SC, feedback_states: FT) -> Self {
Self {
pub fn new<F, O>(
rand: R,
corpus: C,
solutions: SC,
feedback: &mut F,
objective: &mut O,
) -> Result<Self, Error>
where
F: Feedback<I, Self>,
O: Feedback<I, Self>,
{
let mut state = Self {
rand,
executions: 0,
stability: None,
start_time: Duration::from_millis(0),
metadata: SerdeAnyMap::default(),
named_metadata: NamedSerdeAnyMap::default(),
corpus,
feedback_states,
solutions,
max_size: DEFAULT_MAX_SIZE,
#[cfg(feature = "introspection")]
introspection_monitor: ClientPerfMonitor::new(),
phantom: PhantomData,
}
};
feedback.init_state(&mut state)?;
objective.init_state(&mut state)?;
Ok(state)
}
}
#[cfg(feature = "introspection")]
impl<C, FT, I, R, SC> HasClientPerfMonitor for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasClientPerfMonitor for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
fn introspection_monitor(&self) -> &ClientPerfMonitor {
@ -610,12 +623,11 @@ where
}
#[cfg(not(feature = "introspection"))]
impl<C, FT, I, R, SC> HasClientPerfMonitor for StdState<C, FT, I, R, SC>
impl<C, I, R, SC> HasClientPerfMonitor for StdState<C, I, R, SC>
where
C: Corpus<I>,
I: Input,
R: Rand,
FT: FeedbackStatesTuple,
SC: Corpus<I>,
{
fn introspection_monitor(&self) -> &ClientPerfMonitor {
@ -645,28 +657,20 @@ pub mod pybind {
use crate::bolts::rands::pybind::PythonRand;
use crate::bolts::tuples::tuple_list;
use crate::corpus::pybind::PythonCorpus;
use crate::feedbacks::map::MapFeedbackState;
use crate::feedbacks::pybind::PythonFeedback;
use crate::inputs::BytesInput;
use crate::state::StdState;
use pyo3::prelude::*;
macro_rules! define_python_state {
($type_name:ident, $struct_name:ident, $py_name:tt, $datatype:ty, $py_map_feedback_state_name:ident, $event_manager_name: ident,
$fuzzer_name: ident, $executor_name: ident, $rand_printable_generator: ident) => {
($type_name:ident, $struct_name:ident, $py_name:tt) => {
use crate::events::pybind::$event_manager_name;
use crate::executors::pybind::$executor_name;
use crate::feedbacks::map::pybind::$py_map_feedback_state_name;
use crate::fuzzer::pybind::$fuzzer_name;
use crate::generators::pybind::$rand_printable_generator;
/// `StdState` with fixed generics
pub type $type_name = StdState<
PythonCorpus,
(MapFeedbackState<$datatype>, ()),
BytesInput,
PythonRand,
PythonCorpus,
>;
pub type $type_name = StdState<PythonCorpus, BytesInput, PythonRand, PythonCorpus>;
#[pyclass(unsendable, name = $py_name)]
#[derive(Debug)]
@ -683,24 +687,20 @@ pub mod pybind {
py_rand: PythonRand,
corpus: PythonCorpus,
solutions: PythonCorpus,
py_map_feedback_state: $py_map_feedback_state_name,
feedback: &mut PythonFeedback,
objective: &mut PythonFeedback,
) -> Self {
Self {
std_state: StdState::new(
py_rand,
corpus,
solutions,
tuple_list!(py_map_feedback_state.map_feedback_state),
),
std_state: StdState::new(py_rand, corpus, solutions, feedback, objective),
}
}
fn generate_initial_inputs(
&mut self,
py_fuzzer: &mut $fuzzer_name,
py_executor: &mut $executor_name,
py_generator: &mut $rand_printable_generator,
py_mgr: &mut $event_manager_name,
py_fuzzer: &mut PythonFuzzer,
py_executor: &mut PythonExecutor,
py_generator: &mut PythonGenerator,
py_mgr: &mut PythonEventManager,
num: usize,
) {
self.std_state
@ -717,109 +717,11 @@ pub mod pybind {
};
}
define_python_state!(
MyStdStateI8,
PythonStdStateI8,
"StdStateI8",
i8,
PythonMapFeedbackStateI8,
PythonEventManagerI8,
PythonStdFuzzerI8,
PythonExecutorI8,
PythonRandPrintablesGeneratorI8
);
define_python_state!(
MyStdStateI16,
PythonStdStateI16,
"StdStateI16",
i16,
PythonMapFeedbackStateI16,
PythonEventManagerI16,
PythonStdFuzzerI16,
PythonExecutorI16,
PythonRandPrintablesGeneratorI16
);
define_python_state!(
MyStdStateI32,
PythonStdStateI32,
"StdStateI32",
i32,
PythonMapFeedbackStateI32,
PythonEventManagerI32,
PythonStdFuzzerI32,
PythonExecutorI32,
PythonRandPrintablesGeneratorI32
);
define_python_state!(
MyStdStateI64,
PythonStdStateI64,
"StdStateI64",
i64,
PythonMapFeedbackStateI64,
PythonEventManagerI64,
PythonStdFuzzerI64,
PythonExecutorI64,
PythonRandPrintablesGeneratorI64
);
define_python_state!(
MyStdStateU8,
PythonStdStateU8,
"StdStateU8",
u8,
PythonMapFeedbackStateU8,
PythonEventManagerU8,
PythonStdFuzzerU8,
PythonExecutorU8,
PythonRandPrintablesGeneratorU8
);
define_python_state!(
MyStdStateU16,
PythonStdStateU16,
"StdStateU16",
u16,
PythonMapFeedbackStateU16,
PythonEventManagerU16,
PythonStdFuzzerU16,
PythonExecutorU16,
PythonRandPrintablesGeneratorU16
);
define_python_state!(
MyStdStateU32,
PythonStdStateU32,
"StdStateU32",
u32,
PythonMapFeedbackStateU32,
PythonEventManagerU32,
PythonStdFuzzerU32,
PythonExecutorU32,
PythonRandPrintablesGeneratorU32
);
define_python_state!(
MyStdStateU64,
PythonStdStateU64,
"StdStateU64",
u64,
PythonMapFeedbackStateU64,
PythonEventManagerU64,
PythonStdFuzzerU64,
PythonExecutorU64,
PythonRandPrintablesGeneratorU64
);
define_python_state!(PythonStdState, PythonStdStateWrapper, "StdState",);
/// Register the classes to the python module
pub fn register(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<PythonStdStateI8>()?;
m.add_class::<PythonStdStateI16>()?;
m.add_class::<PythonStdStateI32>()?;
m.add_class::<PythonStdStateI64>()?;
m.add_class::<PythonStdStateU8>()?;
m.add_class::<PythonStdStateU16>()?;
m.add_class::<PythonStdStateU32>()?;
m.add_class::<PythonStdStateU64>()?;
m.add_class::<PythonStdStateWrapper>()?;
Ok(())
}
}

@ -1 +1 @@
Subproject commit 5cccc33456c48ad83008eb618e7da5d005c72d89
Subproject commit 45cde0269ae22aef4cca2e1fb98c3b24f7bb2984

View File

@ -17,7 +17,7 @@ use libafl::{
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
executors::{forkserver::ForkserverExecutorBuilder, TimeoutForkserverExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandBytesGenerator,
monitors::MultiMonitor,
@ -111,7 +111,7 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
let monitor = MultiMonitor::new(|s| println!("{}", s));
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
// Coverage map shared between target and fuzzer
@ -130,20 +130,17 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
// Create an observation channel to keep track of the execution time
let time_observer = TimeObserver::new("time");
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -155,10 +152,10 @@ impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> {
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(crashes.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
// Create a dictionary if not existing

View File

@ -19,7 +19,7 @@ use libafl::{
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
executors::{inprocess::InProcessExecutor, ExitKind, ShadowExecutor, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandBytesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -138,7 +138,7 @@ where
let monitor = MultiMonitor::new(|s| println!("{}", s));
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
// Create an observation channel using the coverage map
@ -151,20 +151,17 @@ where
let cmplog = unsafe { &mut CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -176,10 +173,10 @@ where
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(crashes.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
// Create a dictionary if not existing

View File

@ -18,7 +18,7 @@ use libafl::{
events::{EventConfig, EventRestarter, LlmpRestartingEventManager},
executors::{ExitKind, ShadowExecutor, TimeoutExecutor},
feedback_or, feedback_or_fast,
feedbacks::{CrashFeedback, MapFeedbackState, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback, TimeoutFeedback},
fuzzer::{Fuzzer, StdFuzzer},
generators::RandBytesGenerator,
inputs::{BytesInput, HasTargetBytes},
@ -141,7 +141,7 @@ where
let monitor = MultiMonitor::new(|s| println!("{}", s));
let mut run_client = |state: Option<StdState<_, _, _, _, _>>,
let mut run_client = |state: Option<_>,
mut mgr: LlmpRestartingEventManager<_, _, _, _>,
_core_id| {
// Create an observation channel using the coverage map
@ -157,20 +157,17 @@ where
let cmplog = unsafe { &mut cmplog::CMPLOG_MAP };
let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true);
// The state of the edges feedback.
let feedback_state = MapFeedbackState::with_observer(&edges_observer);
// Feedback to rate the interestingness of an input
// This one is composed by two Feedbacks in OR
let feedback = feedback_or!(
let mut feedback = feedback_or!(
// New maximization map feedback linked to the edges observer and the feedback state
MaxMapFeedback::new_tracking(&feedback_state, &edges_observer, true, false),
MaxMapFeedback::new_tracking(&edges_observer, true, false),
// Time feedback, this one does not need a feedback state
TimeFeedback::new_with_observer(&time_observer)
);
// A feedback to choose if an input is a solution or not
let objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
let mut objective = feedback_or_fast!(CrashFeedback::new(), TimeoutFeedback::new());
// If not restarting, create a State from scratch
let mut state = state.unwrap_or_else(|| {
@ -182,10 +179,10 @@ where
// Corpus in which we store solutions (crashes in this example),
// on disk so the user can get them after stopping the fuzzer
OnDiskCorpus::new(crashes.clone()).unwrap(),
// States of the feedbacks.
// They are the data related to the feedbacks that you want to persist in the State.
tuple_list!(feedback_state),
&mut feedback,
&mut objective,
)
.unwrap()
});
// Create a dictionary if not existing