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"] } pyo3 = { version = "0.15", features = ["extension-module"] }
libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] } libafl_qemu = { path = "../../libafl_qemu", version = "0.7", features = ["python"] }
libafl_sugar = { path = "../../libafl_sugar", version = "0.7", features = ["python"] } libafl_sugar = { path = "../../libafl_sugar", version = "0.7", features = ["python"] }
libafl = { path = "../../libafl", version = "0.7", features = ["python"] } #libafl = { path = "../../libafl", version = "0.7", features = ["python"] }
libafl = { path = "../../libafl", version = "0.7" }
[build-dependencies] [build-dependencies]
pyo3-build-config = { version = "0.15" } pyo3-build-config = { version = "0.15" }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

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(feature = "std")]
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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