diff --git a/fuzzers/fuzzbench/src/lib.rs b/fuzzers/fuzzbench/src/lib.rs index 09a688ba4b..d692885f64 100644 --- a/fuzzers/fuzzbench/src/lib.rs +++ b/fuzzers/fuzzbench/src/lib.rs @@ -38,7 +38,7 @@ use libafl::{ }, observers::{HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, PowerQueueScheduler, + powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, }, stages::{ calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, @@ -71,19 +71,22 @@ pub fn libafl_main() { Arg::new("out") .short('o') .long("output") - .help("The directory to place finds in ('corpus')"), + .help("The directory to place finds in ('corpus')") + .takes_value(true), ) .arg( Arg::new("in") .short('i') .long("input") - .help("The directory to read initial inputs from ('seeds')"), + .help("The directory to read initial inputs from ('seeds')") + .takes_value(true), ) .arg( Arg::new("tokens") .short('x') .long("tokens") - .help("A file to read tokens from, to be used during fuzzing"), + .help("A file to read tokens from, to be used during fuzzing") + .takes_value(true), ) .arg( Arg::new("logfile") @@ -99,7 +102,7 @@ pub fn libafl_main() { .help("Timeout for each individual execution, in milliseconds") .default_value("1200"), ) - .arg(Arg::new("remaining")) + .arg(Arg::new("remaining").multiple_values(true)) .try_get_matches() { Ok(res) => res, @@ -120,8 +123,8 @@ pub fn libafl_main() { env::current_dir().unwrap().to_string_lossy().to_string() ); - if let Some(filenames) = res.get_many::("remaining") { - let filenames: Vec<&str> = filenames.map(|v| v.as_str()).collect(); + if let Some(filenames) = res.values_of("remaining") { + let filenames: Vec<&str> = filenames.collect(); if !filenames.is_empty() { run_testcases(&filenames); return; @@ -157,11 +160,12 @@ pub fn libafl_main() { let tokens = res.get_one::("tokens").map(PathBuf::from); - let logfile = PathBuf::from(res.get_one::("logfile").unwrap()); + let logfile = PathBuf::from(res.get_one::("logfile").unwrap().to_string()); let timeout = Duration::from_millis( res.get_one::("timeout") .unwrap() + .to_string() .parse() .expect("Could not parse timeout in milliseconds"), ); @@ -313,8 +317,9 @@ fn fuzz( let power = StdPowerMutationalStage::new(mutator, &edges_observer); // A minimization+queue policy to get testcasess from the corpus - let scheduler = - IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST)); + let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::with_schedule( + PowerSchedule::EXPLORE, + )); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); diff --git a/fuzzers/fuzzbench_text/src/lib.rs b/fuzzers/fuzzbench_text/src/lib.rs index 8d647975a4..1d8b03d502 100644 --- a/fuzzers/fuzzbench_text/src/lib.rs +++ b/fuzzers/fuzzbench_text/src/lib.rs @@ -44,7 +44,7 @@ use libafl::{ }, observers::{HitcountsMapObserver, StdMapObserver, TimeObserver}, schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, PowerQueueScheduler, + powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, }, stages::{ calibrate::CalibrationStage, power::StdPowerMutationalStage, GeneralizationStage, @@ -377,8 +377,9 @@ fn fuzz_binary( let power = StdPowerMutationalStage::new(mutator, &edges_observer); // A minimization+queue policy to get testcasess from the corpus - let scheduler = - IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST)); + let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::with_schedule( + PowerSchedule::EXPLORE, + )); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); @@ -532,7 +533,7 @@ fn fuzz_text( let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true); // New maximization map feedback linked to the edges observer and the feedback state - let mut map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, true); + let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, true); let calibration = CalibrationStage::new(&map_feedback); @@ -602,8 +603,9 @@ fn fuzz_text( let grimoire = StdMutationalStage::new(grimoire_mutator); // A minimization+queue policy to get testcasess from the corpus - let scheduler = - IndexesLenTimeMinimizerScheduler::new(PowerQueueScheduler::new(PowerSchedule::FAST)); + let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::with_schedule( + PowerSchedule::EXPLORE, + )); // A fuzzer with feedbacks and a corpus scheduler let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); diff --git a/fuzzers/fuzzbench_weighted/.gitignore b/fuzzers/fuzzbench_weighted/.gitignore deleted file mode 100644 index d3561edaf7..0000000000 --- a/fuzzers/fuzzbench_weighted/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -libpng-* -fuzzer diff --git a/fuzzers/fuzzbench_weighted/Cargo.toml b/fuzzers/fuzzbench_weighted/Cargo.toml deleted file mode 100644 index 20e629c695..0000000000 --- a/fuzzers/fuzzbench_weighted/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "fuzzbench_weighted" -version = "0.8.2" -authors = ["Andrea Fioraldi ", "Dominik Maier "] -edition = "2021" - -[features] -default = ["std"] -std = [] - -[profile.release] -lto = true -codegen-units = 1 -opt-level = 3 -debug = true - -[build-dependencies] -cc = { version = "1.0", features = ["parallel"] } -which = { version = "4.0.2" } - -[dependencies] -libafl = { path = "../../libafl/" } -libafl_targets = { path = "../../libafl_targets/", features = ["sancov_pcguard_hitcounts", "sancov_cmplog", "libfuzzer"] } -# TODO Include it only when building cc -libafl_cc = { path = "../../libafl_cc/" } -clap = { version = "3.2", features = ["default"] } -nix = "0.25" -mimalloc = { version = "*", default-features = false } - -[lib] -name = "fuzzbench" -crate-type = ["staticlib"] diff --git a/fuzzers/fuzzbench_weighted/Makefile.toml b/fuzzers/fuzzbench_weighted/Makefile.toml deleted file mode 100644 index 14c6b92387..0000000000 --- a/fuzzers/fuzzbench_weighted/Makefile.toml +++ /dev/null @@ -1,100 +0,0 @@ -[env] -CARGO_TARGET_DIR = { value = "target", condition = { env_not_set = ["CARGO_TARGET_DIR"] } } -FUZZER_NAME="fuzzer" -PROJECT_DIR = { script = ["pwd"] } - -[tasks.unsupported] -script_runner="@shell" -script=''' -echo "Cargo-make not integrated yet on this" -''' - -# Compilers -[tasks.cxx] -linux_alias = "cxx_unix" -mac_alias = "cxx_unix" -windows_alias = "unsupported" - -[tasks.cxx_unix] -command = "cargo" -args = ["build" , "--release"] - -[tasks.cc] -linux_alias = "cc_unix" -mac_alias = "cc_unix" -windows_alias = "unsupported" - -[tasks.cc_unix] -command = "cargo" -args = ["build" , "--release"] - -# fuzz.o File -[tasks.fuzz_o] -linux_alias = "fuzz_o_unix" -mac_alias = "fuzz_o_unix" -windows_alias = "unsupported" - -[tasks.fuzz_o_unix] -command = "${CARGO_TARGET_DIR}/release/libafl_cc" -args = ["--libafl-no-link", "-O3", "-c", "fuzz.c", "-o", "fuzz.o"] -dependencies = ["cc", "cxx"] - -# Fuzzer -[tasks.fuzzer] -linux_alias = "fuzzer_unix" -mac_alias = "fuzzer_unix" -windows_alias = "unsupported" - -[tasks.fuzzer_unix] -command = "${CARGO_TARGET_DIR}/release/libafl_cxx" -args = ["--libafl", "fuzz.o", "-o", "${FUZZER_NAME}", "-lm", "-lz"] -dependencies = ["cc", "cxx", "fuzz_o"] - -# Run -[tasks.run] -linux_alias = "run_unix" -mac_alias = "run_unix" -windows_alias = "unsupported" - -[tasks.run_unix] -script_runner="@shell" -script=''' -rm -rf libafl_unix_shmem_server || true -mkdir in || true -echo a > in/a -./${FUZZER_NAME} -o out -i in -''' -dependencies = ["fuzzer"] - - -# Test -[tasks.test] -linux_alias = "test_unix" -mac_alias = "test_unix" -windows_alias = "unsupported" - -[tasks.test_unix] -script_runner="@shell" -script=''' -rm -rf libafl_unix_shmem_server || true -mkdir in || true -echo a > in/a -# Allow sigterm as exit code -timeout 11s ./${FUZZER_NAME} -o out -i in || [ $? -eq 124 ] -rm -rf out || true -rm -rf in || true -''' -dependencies = ["fuzzer"] - -# Clean -[tasks.clean] -linux_alias = "clean_unix" -mac_alias = "clean_unix" -windows_alias = "unsupported" - -[tasks.clean_unix] -script_runner="@shell" -script=''' -rm ./${FUZZER_NAME} || true -rm fuzz.o || true -''' \ No newline at end of file diff --git a/fuzzers/fuzzbench_weighted/README.md b/fuzzers/fuzzbench_weighted/README.md deleted file mode 100644 index df34f5e090..0000000000 --- a/fuzzers/fuzzbench_weighted/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Fuzzbench Harness - -This folder contains an example fuzzer tailored for fuzzbench. -It uses the best possible setting, with the exception of a SimpleRestartingEventManager instead of an LlmpEventManager - since fuzzbench is single threaded. -Real fuzz campaigns should consider using multithreaded LlmpEventManager, see the other examples. - -## Build - -To build this example, run `cargo build --release`. -This will build the fuzzer compilers (`libafl_cc` and `libafl_cpp`) with `src/lib.rs` as fuzzer. -The fuzzer uses the libfuzzer compatibility layer and the SanitizerCoverage runtime functions for coverage feedback. - -These can then be used to build libfuzzer harnesses in the software project of your choice. -Finally, just run the resulting binary with `out_dir`, `in_dir`. - -In any real-world scenario, you should use `taskset` to pin each client to an empty CPU core, the lib does not pick an empty core automatically (yet). - diff --git a/fuzzers/fuzzbench_weighted/fuzz.c b/fuzzers/fuzzbench_weighted/fuzz.c deleted file mode 100644 index 56b10527b2..0000000000 --- a/fuzzers/fuzzbench_weighted/fuzz.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { - if (Size >= 8 && *(uint32_t *)Data == 0xaabbccdd) { abort(); } -} - -/* -int main() { - - char buf [10] = {0}; - LLVMFuzzerTestOneInput(buf, 10); - -}*/ diff --git a/fuzzers/fuzzbench_weighted/src/bin/libafl_cc.rs b/fuzzers/fuzzbench_weighted/src/bin/libafl_cc.rs deleted file mode 100644 index 9d4fc05945..0000000000 --- a/fuzzers/fuzzbench_weighted/src/bin/libafl_cc.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::env; - -use libafl_cc::{ClangWrapper, CompilerWrapper, LLVMPasses}; - -pub fn main() { - let mut args: Vec = env::args().collect(); - if args.len() > 1 { - let mut dir = env::current_exe().unwrap(); - let wrapper_name = dir.file_name().unwrap().to_str().unwrap(); - - let is_cpp = match wrapper_name[wrapper_name.len()-2..].to_lowercase().as_str() { - "cc" => false, - "++" | "pp" | "xx" => true, - _ => panic!("Could not figure out if c or c++ warpper was called. Expected {:?} to end with c or cxx", dir), - }; - - dir.pop(); - - // Must be always present, even without --libafl - args.push("-fsanitize-coverage=trace-pc-guard,trace-cmp".into()); - - let mut cc = ClangWrapper::new(); - - #[cfg(any(target_os = "linux", target_vendor = "apple"))] - cc.add_pass(LLVMPasses::AutoTokens); - - if let Some(code) = cc - .cpp(is_cpp) - // silence the compiler wrapper output, needed for some configure scripts. - .silence(true) - // add arguments only if --libafl or --libafl-no-link are present - .need_libafl_arg(true) - .parse_args(&args) - .expect("Failed to parse the command line") - .link_staticlib(&dir, "fuzzbench") - .add_pass(LLVMPasses::CmpLogRtn) - .run() - .expect("Failed to run the wrapped compiler") - { - std::process::exit(code); - } - } else { - panic!("LibAFL CC: No Arguments given"); - } -} diff --git a/fuzzers/fuzzbench_weighted/src/bin/libafl_cxx.rs b/fuzzers/fuzzbench_weighted/src/bin/libafl_cxx.rs deleted file mode 100644 index ce786239b0..0000000000 --- a/fuzzers/fuzzbench_weighted/src/bin/libafl_cxx.rs +++ /dev/null @@ -1,5 +0,0 @@ -pub mod libafl_cc; - -fn main() { - libafl_cc::main() -} diff --git a/fuzzers/fuzzbench_weighted/src/lib.rs b/fuzzers/fuzzbench_weighted/src/lib.rs deleted file mode 100644 index d692885f64..0000000000 --- a/fuzzers/fuzzbench_weighted/src/lib.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! A singlethreaded libfuzzer-like fuzzer that can auto-restart. -use mimalloc::MiMalloc; -#[global_allocator] -static GLOBAL: MiMalloc = MiMalloc; - -use core::{cell::RefCell, time::Duration}; -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, FromRawFd}; -use std::{ - env, - fs::{self, File, OpenOptions}, - io::{self, Read, Write}, - path::PathBuf, - process, -}; - -use clap::{Arg, Command}; -use libafl::{ - bolts::{ - current_nanos, current_time, - os::dup2, - rands::StdRand, - shmem::{ShMemProvider, StdShMemProvider}, - tuples::{tuple_list, Merge}, - AsSlice, - }, - corpus::{Corpus, OnDiskCorpus}, - events::SimpleRestartingEventManager, - executors::{inprocess::InProcessExecutor, ExitKind, TimeoutExecutor}, - feedback_or, - feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, - fuzzer::{Fuzzer, StdFuzzer}, - inputs::{BytesInput, HasTargetBytes}, - monitors::SimpleMonitor, - mutators::{ - scheduled::havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, - StdMOptMutator, StdScheduledMutator, Tokens, - }, - observers::{HitcountsMapObserver, StdMapObserver, TimeObserver}, - schedulers::{ - powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, - }, - stages::{ - calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, - TracingStage, - }, - state::{HasCorpus, HasMetadata, StdState}, - Error, -}; -#[cfg(any(target_os = "linux", target_vendor = "apple"))] -use libafl_targets::autotokens; -use libafl_targets::{ - libfuzzer_initialize, libfuzzer_test_one_input, CmpLogObserver, CMPLOG_MAP, EDGES_MAP, - MAX_EDGES_NUM, -}; -#[cfg(unix)] -use nix::{self, unistd::dup}; - -/// The fuzzer main (as `no_mangle` C function) -#[no_mangle] -pub fn libafl_main() { - // Registry the metadata types used in this fuzzer - // Needed only on no_std - //RegistryBuilder::register::(); - - let res = match Command::new(env!("CARGO_PKG_NAME")) - .version(env!("CARGO_PKG_VERSION")) - .author("AFLplusplus team") - .about("LibAFL-based fuzzer for Fuzzbench") - .arg( - Arg::new("out") - .short('o') - .long("output") - .help("The directory to place finds in ('corpus')") - .takes_value(true), - ) - .arg( - Arg::new("in") - .short('i') - .long("input") - .help("The directory to read initial inputs from ('seeds')") - .takes_value(true), - ) - .arg( - Arg::new("tokens") - .short('x') - .long("tokens") - .help("A file to read tokens from, to be used during fuzzing") - .takes_value(true), - ) - .arg( - Arg::new("logfile") - .short('l') - .long("logfile") - .help("Duplicates all output to this file") - .default_value("libafl.log"), - ) - .arg( - Arg::new("timeout") - .short('t') - .long("timeout") - .help("Timeout for each individual execution, in milliseconds") - .default_value("1200"), - ) - .arg(Arg::new("remaining").multiple_values(true)) - .try_get_matches() - { - Ok(res) => res, - Err(err) => { - println!( - "Syntax: {}, [-x dictionary] -o corpus_dir -i seed_dir\n{:?}", - env::current_exe() - .unwrap_or_else(|_| "fuzzer".into()) - .to_string_lossy(), - err, - ); - return; - } - }; - - println!( - "Workdir: {:?}", - env::current_dir().unwrap().to_string_lossy().to_string() - ); - - if let Some(filenames) = res.values_of("remaining") { - let filenames: Vec<&str> = filenames.collect(); - if !filenames.is_empty() { - run_testcases(&filenames); - return; - } - } - - // For fuzzbench, crashes and finds are inside the same `corpus` directory, in the "queue" and "crashes" subdir. - let mut out_dir = PathBuf::from( - res.get_one::("out") - .expect("The --output parameter is missing") - .to_string(), - ); - if fs::create_dir(&out_dir).is_err() { - println!("Out dir at {:?} already exists.", &out_dir); - if !out_dir.is_dir() { - println!("Out dir at {:?} is not a valid directory!", &out_dir); - return; - } - } - let mut crashes = out_dir.clone(); - crashes.push("crashes"); - out_dir.push("queue"); - - let in_dir = PathBuf::from( - res.get_one::("in") - .expect("The --input parameter is missing") - .to_string(), - ); - if !in_dir.is_dir() { - println!("In dir at {:?} is not a valid directory!", &in_dir); - return; - } - - let tokens = res.get_one::("tokens").map(PathBuf::from); - - let logfile = PathBuf::from(res.get_one::("logfile").unwrap().to_string()); - - let timeout = Duration::from_millis( - res.get_one::("timeout") - .unwrap() - .to_string() - .parse() - .expect("Could not parse timeout in milliseconds"), - ); - - fuzz(out_dir, crashes, in_dir, tokens, logfile, timeout) - .expect("An error occurred while fuzzing"); -} - -fn run_testcases(filenames: &[&str]) { - // The actual target run starts here. - // Call LLVMFUzzerInitialize() if present. - let args: Vec = env::args().collect(); - if libfuzzer_initialize(&args) == -1 { - println!("Warning: LLVMFuzzerInitialize failed with -1") - } - - println!( - "You are not fuzzing, just executing {} testcases", - filenames.len() - ); - for fname in filenames { - println!("Executing {}", fname); - - let mut file = File::open(fname).expect("No file found"); - let mut buffer = vec![]; - file.read_to_end(&mut buffer).expect("Buffer overflow"); - - libfuzzer_test_one_input(&buffer); - } -} - -/// The actual fuzzer -fn fuzz( - corpus_dir: PathBuf, - objective_dir: PathBuf, - seed_dir: PathBuf, - tokenfile: Option, - logfile: PathBuf, - timeout: Duration, -) -> Result<(), Error> { - let log = RefCell::new( - OpenOptions::new() - .append(true) - .create(true) - .open(&logfile)?, - ); - - #[cfg(unix)] - let mut stdout_cpy = unsafe { - let new_fd = dup(io::stdout().as_raw_fd())?; - File::from_raw_fd(new_fd) - }; - #[cfg(unix)] - let file_null = File::open("/dev/null")?; - - // 'While the monitor are state, they are usually used in the broker - which is likely never restarted - let monitor = SimpleMonitor::new(|s| { - #[cfg(unix)] - writeln!(&mut stdout_cpy, "{}", s).unwrap(); - #[cfg(windows)] - println!("{}", s); - writeln!(log.borrow_mut(), "{:?} {}", current_time(), s).unwrap(); - }); - - // We need a shared map to store our state before a crash. - // This way, we are able to continue fuzzing afterwards. - let mut shmem_provider = StdShMemProvider::new()?; - - let (state, mut mgr) = match SimpleRestartingEventManager::launch(monitor, &mut shmem_provider) - { - // The restarting state will spawn the same process again as child, then restarted it each time it crashes. - Ok(res) => res, - Err(err) => match err { - Error::ShuttingDown => { - return Ok(()); - } - _ => { - panic!("Failed to setup the restarter: {}", err); - } - }, - }; - - // Create an observation channel using the coverage map - // We don't use the hitcounts (see the Cargo.toml, we use pcguard_edges) - let edges = unsafe { &mut EDGES_MAP[0..MAX_EDGES_NUM] }; - let edges_observer = HitcountsMapObserver::new(StdMapObserver::new("edges", edges)); - - // Create an observation channel to keep track of the execution time - let time_observer = TimeObserver::new("time"); - - let cmplog = unsafe { &mut CMPLOG_MAP }; - let cmplog_observer = CmpLogObserver::new("cmplog", cmplog, true); - - let map_feedback = MaxMapFeedback::new_tracking(&edges_observer, true, false); - - let calibration = CalibrationStage::new(&map_feedback); - - // Feedback to rate the interestingness of an input - // This one is composed by two Feedbacks in OR - let mut feedback = feedback_or!( - // New maximization map feedback linked to the edges observer and the feedback state - map_feedback, - // Time feedback, this one does not need a feedback state - TimeFeedback::new_with_observer(&time_observer) - ); - - // A feedback to choose if an input is a solution or not - let mut objective = CrashFeedback::new(); - - // If not restarting, create a State from scratch - let mut state = state.unwrap_or_else(|| { - StdState::new( - // RNG - StdRand::with_seed(current_nanos()), - // Corpus that will be evolved, we keep it in memory for performance - OnDiskCorpus::new(corpus_dir).unwrap(), - // Corpus in which we store solutions (crashes in this example), - // on disk so the user can get them after stopping the fuzzer - OnDiskCorpus::new(objective_dir).unwrap(), - // States of the feedbacks. - // The feedbacks can report the data that should persist in the State. - &mut feedback, - // Same for objective feedbacks - &mut objective, - ) - .unwrap() - }); - - println!("Let's fuzz :)"); - - // The actual target run starts here. - // Call LLVMFUzzerInitialize() if present. - let args: Vec = env::args().collect(); - if libfuzzer_initialize(&args) == -1 { - println!("Warning: LLVMFuzzerInitialize failed with -1") - } - - // Setup a randomic Input2State stage - let i2s = StdMutationalStage::new(StdScheduledMutator::new(tuple_list!(I2SRandReplace::new()))); - - // Setup a MOPT mutator - let mutator = StdMOptMutator::new( - &mut state, - havoc_mutations().merge(tokens_mutations()), - 7, - 5, - )?; - - let power = StdPowerMutationalStage::new(mutator, &edges_observer); - - // A minimization+queue policy to get testcasess from the corpus - let scheduler = IndexesLenTimeMinimizerScheduler::new(StdWeightedScheduler::with_schedule( - PowerSchedule::EXPLORE, - )); - - // A fuzzer with feedbacks and a corpus scheduler - let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective); - - // The wrapped harness function, calling out to the LLVM-style harness - let mut harness = |input: &BytesInput| { - let target = input.target_bytes(); - let buf = target.as_slice(); - libfuzzer_test_one_input(buf); - ExitKind::Ok - }; - - let mut tracing_harness = harness; - - // Create the executor for an in-process function with one observer for edge coverage and one for the execution time - let mut executor = TimeoutExecutor::new( - InProcessExecutor::new( - &mut harness, - tuple_list!(edges_observer, time_observer), - &mut fuzzer, - &mut state, - &mut mgr, - )?, - timeout, - ); - - // Setup a tracing stage in which we log comparisons - let tracing = TracingStage::new(TimeoutExecutor::new( - InProcessExecutor::new( - &mut tracing_harness, - tuple_list!(cmplog_observer), - &mut fuzzer, - &mut state, - &mut mgr, - )?, - // Give it more time! - timeout * 10, - )); - - // The order of the stages matter! - let mut stages = tuple_list!(calibration, tracing, i2s, power); - - // Read tokens - if state.metadata().get::().is_none() { - let mut toks = Tokens::default(); - if let Some(tokenfile) = tokenfile { - toks.add_from_file(tokenfile)?; - } - #[cfg(any(target_os = "linux", target_vendor = "apple"))] - { - toks += autotokens()?; - } - - if !toks.is_empty() { - state.add_metadata(toks); - } - } - - // In case the corpus is empty (on first run), reset - if state.corpus().count() < 1 { - state - .load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &[seed_dir.clone()]) - .unwrap_or_else(|_| { - println!("Failed to load initial corpus at {:?}", &seed_dir); - process::exit(0); - }); - println!("We imported {} inputs from disk.", state.corpus().count()); - } - - // Remove target ouput (logs still survive) - #[cfg(unix)] - { - let null_fd = file_null.as_raw_fd(); - dup2(null_fd, io::stdout().as_raw_fd())?; - dup2(null_fd, io::stderr().as_raw_fd())?; - } - // reopen file to make sure we're at the end - log.replace( - OpenOptions::new() - .append(true) - .create(true) - .open(&logfile)?, - ); - - fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?; - - // Never reached - Ok(()) -}