Rust 2024 edition (#3022)

* Rust 2024 edition

* gen = generalized

* Fixes

* more fix

* More fix

* even more fix

* fix libfuzzer

* ignore clippy lint

* even more

* fix docs?

* more?

* More pub more better

* win

* docs

* more

* More

* doc stuff?

* counter_maps->counters_maps

* libafl qemu fixes for rust 2024

* fix?

* fmt

* unsafe lint

* final fixes

* fmt

* working?

* not working

* unused import

* win?

* update libafl qemu hash

* fmt

* fix

* unused imports

* fix

* fix

* more foix

* less edition

* fix

---------

Co-authored-by: Romain Malmain <romain.malmain@pm.me>
This commit is contained in:
Dominik Maier 2025-02-27 00:12:29 +01:00 committed by GitHub
parent 3d31adcca1
commit c7207dceb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
336 changed files with 4399 additions and 3156 deletions

View File

@ -223,6 +223,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: taiki-e/install-action@cargo-hack - uses: taiki-e/install-action@cargo-hack
- run: rustup upgrade
# Note: We currently only specify minimum rust versions for the default workspace members # Note: We currently only specify minimum rust versions for the default workspace members
- run: cargo hack check --rust-version -p libafl -p libafl_bolts -p libafl_derive -p libafl_cc -p libafl_targets - run: cargo hack check --rust-version -p libafl -p libafl_bolts -p libafl_derive -p libafl_cc -p libafl_targets

1
.gitignore vendored
View File

@ -74,6 +74,5 @@ libafl_nyx/packer
harness harness
program program
fuzzer_libpng* fuzzer_libpng*
forkserver_simple
*.patch *.patch

View File

@ -5,7 +5,7 @@ version = "0.15.1"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
repository = "https://github.com/AFLplusplus/LibAFL/" repository = "https://github.com/AFLplusplus/LibAFL/"
keywords = ["fuzzing", "testing", "security", "python"] keywords = ["fuzzing", "testing", "security", "python"]
edition = "2021" edition = "2024"
categories = ["development-tools::testing", "emulators", "embedded", "os"] categories = ["development-tools::testing", "emulators", "embedded", "os"]
[dependencies] [dependencies]

View File

@ -31,7 +31,7 @@ Here, we use it in Rust. `external_current_millis` is then called from LibAFL.
Note that it needs to be `no_mangle` in order to get picked up by LibAFL at linktime: Note that it needs to be `no_mangle` in order to get picked up by LibAFL at linktime:
```rust,ignore ```rust,ignore
#[no_mangle] #[unsafe(no_mangle)]
pub extern "C" fn external_current_millis() -> u64 { pub extern "C" fn external_current_millis() -> u64 {
unsafe { my_real_seconds()*1000 } unsafe { my_real_seconds()*1000 }
} }

View File

@ -32,7 +32,9 @@ As you can see from the forkserver example,
//Coverage map shared between observer and executor //Coverage map shared between observer and executor
let mut shmem = StdShMemProvider::new().unwrap().new_shmem(MAP_SIZE).unwrap(); let mut shmem = StdShMemProvider::new().unwrap().new_shmem(MAP_SIZE).unwrap();
//let the forkserver know the shmid //let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let mut shmem_buf = shmem.as_slice_mut(); let mut shmem_buf = shmem.as_slice_mut();
``` ```

View File

@ -21,7 +21,7 @@ debug = true
[build-dependencies] [build-dependencies]
anyhow = "1.0.89" anyhow = "1.0.89"
bindgen = "0.70.1" bindgen = "0.71.1"
cc = "=1.2.7" # fix me later cc = "=1.2.7" # fix me later
[dependencies] [dependencies]

View File

@ -40,7 +40,9 @@ pub fn main() {
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
//let the forkserver know the shmid //let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_map: &mut [u8; MAP_SIZE] = shmem let shmem_map: &mut [u8; MAP_SIZE] = shmem
.as_slice_mut() .as_slice_mut()
.try_into() .try_into()

View File

@ -97,7 +97,9 @@ pub fn main() {
// The coverage map shared between observer and executor // The coverage map shared between observer and executor
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// the next line is not needed // the next line is not needed
// unsafe { EDGES_MAP_PTR = shmem_buf.as_mut_ptr() }; // unsafe { EDGES_MAP_PTR = shmem_buf.as_mut_ptr() };

View File

@ -2,7 +2,7 @@
name = "forkserver_simple" name = "forkserver_simple"
version = "0.14.1" version = "0.14.1"
authors = ["tokatoka <tokazerkje@outlook.com>"] authors = ["tokatoka <tokazerkje@outlook.com>"]
edition = "2021" edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,7 +1,7 @@
use std::{ use std::{
env, env,
path::Path, path::Path,
process::{exit, Command}, process::{Command, exit},
}; };
const AFL_URL: &str = "https://github.com/AFLplusplus/AFLplusplus"; const AFL_URL: &str = "https://github.com/AFLplusplus/AFLplusplus";
@ -12,7 +12,9 @@ fn main() {
exit(0); exit(0);
} }
env::remove_var("DEBUG"); unsafe {
env::remove_var("DEBUG");
}
let cwd = env::current_dir().unwrap().to_string_lossy().to_string(); let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
let afl = format!("{}/AFLplusplus", &cwd); let afl = format!("{}/AFLplusplus", &cwd);

View File

@ -3,27 +3,26 @@ use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use libafl::{ use libafl::{
HasMetadata,
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
events::SimpleEventManager, events::SimpleEventManager,
executors::{forkserver::ForkserverExecutor, HasObservers}, executors::{HasObservers, forkserver::ForkserverExecutor},
feedback_and_fast, feedback_or, feedback_and_fast, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
inputs::BytesInput, inputs::BytesInput,
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens}, mutators::{StdScheduledMutator, Tokens, havoc_mutations, tokens_mutations},
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver}, observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler}, schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
stages::mutational::StdMutationalStage, stages::mutational::StdMutationalStage,
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
HasMetadata,
}; };
use libafl_bolts::{ use libafl_bolts::{
current_nanos, AsSliceMut, Truncate, current_nanos,
rands::StdRand, rands::StdRand,
shmem::{ShMem, ShMemProvider, UnixShMemProvider}, shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::{tuple_list, Handled, Merge}, tuples::{Handled, Merge, tuple_list},
AsSliceMut, Truncate,
}; };
use nix::sys::signal::Signal; use nix::sys::signal::Signal;
@ -97,7 +96,9 @@ pub fn main() {
// The coverage map shared between observer and executor // The coverage map shared between observer and executor
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// Create an observation channel using the signals map // Create an observation channel using the signals map

View File

@ -242,7 +242,9 @@ fn fuzz(
// The coverage map shared between observer and executor // The coverage map shared between observer and executor
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// To let know the AFL++ binary that we have a big map // To let know the AFL++ binary that we have a big map
std::env::set_var("AFL_MAP_SIZE", format!("{}", MAP_SIZE)); std::env::set_var("AFL_MAP_SIZE", format!("{}", MAP_SIZE));
@ -348,7 +350,9 @@ fn fuzz(
// The cmplog map shared between observer and executor // The cmplog map shared between observer and executor
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap(); let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); unsafe {
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
}
let cmpmap = unsafe { OwnedRefMut::<AFLppCmpLogMap>::from_shmem(&mut cmplog_shmem) }; let cmpmap = unsafe { OwnedRefMut::<AFLppCmpLogMap>::from_shmem(&mut cmplog_shmem) };
let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true); let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true);

View File

@ -244,7 +244,9 @@ fn fuzz(
// The coverage map shared between observer and executor // The coverage map shared between observer and executor
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// To let know the AFL++ binary that we have a big map // To let know the AFL++ binary that we have a big map
std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}")); std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}"));
@ -351,7 +353,9 @@ fn fuzz(
// The cmplog map shared between observer and executor // The cmplog map shared between observer and executor
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap(); let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
// let the forkserver know the shmid // let the forkserver know the shmid
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); unsafe {
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
}
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true); let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true);

View File

@ -200,7 +200,7 @@ pub fn find_afl_binary(filename: &str, same_dir_as: Option<PathBuf>) -> Result<P
false false
}; };
#[expect(clippy::useless_conversion)] // u16 on MacOS, u32 on Linux #[allow(clippy::useless_conversion)] // u16 on MacOS, u32 on Linux
let permission = if is_library { let permission = if is_library {
u32::from(S_IRUSR) // user can read u32::from(S_IRUSR) // user can read
} else { } else {

View File

@ -122,7 +122,9 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
let mut shmem = shmem_provider let mut shmem = shmem_provider
.new_shmem(opt.map_size.unwrap_or(AFL_DEFAULT_MAP_SIZE)) .new_shmem(opt.map_size.unwrap_or(AFL_DEFAULT_MAP_SIZE))
.unwrap(); .unwrap();
shmem.write_to_env(SHMEM_ENV_VAR).unwrap(); unsafe {
shmem.write_to_env(SHMEM_ENV_VAR).unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// If we are in Nyx Mode, we need to use a different map observer. // If we are in Nyx Mode, we need to use a different map observer.
@ -300,14 +302,17 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
// Set LD_PRELOAD (Linux) && DYLD_INSERT_LIBRARIES (OSX) for target. // Set LD_PRELOAD (Linux) && DYLD_INSERT_LIBRARIES (OSX) for target.
if let Some(preload_env) = &opt.afl_preload { if let Some(preload_env) = &opt.afl_preload {
std::env::set_var("LD_PRELOAD", preload_env); // TODO: Audit that the environment access only happens in single-threaded code.
std::env::set_var("DYLD_INSERT_LIBRARIES", preload_env); unsafe { std::env::set_var("LD_PRELOAD", preload_env) };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("DYLD_INSERT_LIBRARIES", preload_env) };
} }
// Insert appropriate shared libraries if frida_mode // Insert appropriate shared libraries if frida_mode
if opt.frida_mode { if opt.frida_mode {
if opt.frida_asan { if opt.frida_asan {
std::env::set_var("ASAN_OPTIONS", "detect_leaks=false"); // TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("ASAN_OPTIONS", "detect_leaks=false") };
} }
let frida_bin = find_afl_binary("afl-frida-trace.so", Some(opt.executable.clone()))? let frida_bin = find_afl_binary("afl-frida-trace.so", Some(opt.executable.clone()))?
.display() .display()
@ -317,8 +322,10 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
} else { } else {
frida_bin frida_bin
}; };
std::env::set_var("LD_PRELOAD", &preload); // TODO: Audit that the environment access only happens in single-threaded code.
std::env::set_var("DYLD_INSERT_LIBRARIES", &preload); unsafe { std::env::set_var("LD_PRELOAD", &preload) };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { std::env::set_var("DYLD_INSERT_LIBRARIES", &preload) };
} }
#[cfg(feature = "nyx")] #[cfg(feature = "nyx")]
let mut executor = { let mut executor = {
@ -456,7 +463,7 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
// We only run cmplog on the main node // We only run cmplog on the main node
let cmplog_executable_path = match &opt.cmplog { let cmplog_executable_path = match &opt.cmplog {
None => "-", None => "-",
Some(ref p) => match p.as_str() { Some(p) => match p.as_str() {
"0" => opt.executable.to_str().unwrap(), "0" => opt.executable.to_str().unwrap(),
_ => p, _ => p,
}, },
@ -468,7 +475,9 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap(); let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
// Let the Forkserver know the CmpLog shared memory map ID. // Let the Forkserver know the CmpLog shared memory map ID.
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap(); unsafe {
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
}
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) }; let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
// Create the CmpLog observer. // Create the CmpLog observer.

View File

@ -5,7 +5,7 @@ authors = [
"Andrea Fioraldi <andreafioraldi@gmail.com>", "Andrea Fioraldi <andreafioraldi@gmail.com>",
"Dominik Maier <domenukk@gmail.com>", "Dominik Maier <domenukk@gmail.com>",
] ]
edition = "2021" edition = "2024"
[features] [features]
default = ["std"] default = ["std"]

View File

@ -8,10 +8,15 @@ pub fn main() {
let mut dir = env::current_exe().unwrap(); let mut dir = env::current_exe().unwrap();
let wrapper_name = dir.file_name().unwrap().to_str().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() { let is_cpp = match wrapper_name[wrapper_name.len() - 2..]
.to_lowercase()
.as_str()
{
"cc" => false, "cc" => false,
"++" | "pp" | "xx" => true, "++" | "pp" | "xx" => true,
_ => panic!("Could not figure out if c or c++ wrapper was called. Expected {dir:?} to end with c or cxx"), _ => panic!(
"Could not figure out if c or c++ wrapper was called. Expected {dir:?} to end with c or cxx"
),
}; };
dir.pop(); dir.pop();

View File

@ -16,47 +16,46 @@ use std::{
use clap::{Arg, Command}; use clap::{Arg, Command};
use libafl::{ use libafl::{
Error, HasMetadata,
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus}, corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
events::SimpleRestartingEventManager, events::SimpleRestartingEventManager,
executors::{inprocess::InProcessExecutor, ExitKind}, executors::{ExitKind, inprocess::InProcessExecutor},
feedback_or, feedback_or,
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback}, feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
fuzzer::{Fuzzer, StdFuzzer}, fuzzer::{Fuzzer, StdFuzzer},
inputs::{BytesInput, HasTargetBytes}, inputs::{BytesInput, HasTargetBytes},
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{ mutators::{
havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator, StdMOptMutator, StdScheduledMutator, Tokens, havoc_mutations,
StdScheduledMutator, Tokens, token_mutations::I2SRandReplace, tokens_mutations,
}, },
observers::{CanTrack, HitcountsMapObserver, TimeObserver}, observers::{CanTrack, HitcountsMapObserver, TimeObserver},
schedulers::{ schedulers::{
powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule,
}, },
stages::{ stages::{
calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage, StdMutationalStage, TracingStage, calibrate::CalibrationStage,
TracingStage, power::StdPowerMutationalStage,
}, },
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
Error, HasMetadata,
}; };
use libafl_bolts::{ use libafl_bolts::{
current_time, AsSlice, current_time,
os::dup2, os::dup2,
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMemProvider}, shmem::{ShMemProvider, StdShMemProvider},
tuples::{tuple_list, Merge}, tuples::{Merge, tuple_list},
AsSlice,
}; };
#[cfg(any(target_os = "linux", target_vendor = "apple"))] #[cfg(any(target_os = "linux", target_vendor = "apple"))]
use libafl_targets::autotokens; use libafl_targets::autotokens;
use libafl_targets::{ use libafl_targets::{
libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer, CmpLogObserver, CmpLogObserver, libfuzzer_initialize, libfuzzer_test_one_input, std_edges_map_observer,
}; };
#[cfg(unix)] #[cfg(unix)]
use nix::unistd::dup; use nix::unistd::dup;
/// The fuzzer main (as `no_mangle` C function) /// The fuzzer main (as `no_mangle` C function)
#[no_mangle] #[unsafe(no_mangle)]
pub extern "C" fn libafl_main() { pub extern "C" fn libafl_main() {
// Registry the metadata types used in this fuzzer // Registry the metadata types used in this fuzzer
// Needed only on no_std // Needed only on no_std

View File

@ -95,8 +95,12 @@ pub fn main() {
// The coverage map shared between observer and executor // The coverage map shared between observer and executor
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap(); unsafe {
// let the forkserver know the shmid
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf = shmem.as_slice_mut(); let shmem_buf = shmem.as_slice_mut();
// Create an observation channel using the signals map // Create an observation channel using the signals map

View File

@ -11,8 +11,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/"
readme = "../README.md" readme = "../README.md"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
keywords = ["fuzzing", "testing", "security"] keywords = ["fuzzing", "testing", "security"]
edition = "2021" edition = "2024"
rust-version = "1.82" rust-version = "1.85"
categories = [ categories = [
"development-tools::testing", "development-tools::testing",
"emulators", "emulators",

View File

@ -4,9 +4,9 @@
use std::{thread::sleep, time::Duration}; use std::{thread::sleep, time::Duration};
use libafl::monitors::{ use libafl::monitors::{
stats::{manager::ClientStatsManager, ClientStats},
tui::TuiMonitor,
Monitor, Monitor,
stats::{ClientStats, manager::ClientStatsManager},
tui::TuiMonitor,
}; };
use libafl_bolts::ClientId; use libafl_bolts::ClientId;

View File

@ -7,8 +7,8 @@ use core::any::type_name;
pub mod nautilus; pub mod nautilus;
use libafl_bolts::{ use libafl_bolts::{
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
Error, Error,
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
}; };
/// Trait for elements offering metadata /// Trait for elements offering metadata
pub trait HasMetadata { pub trait HasMetadata {

View File

@ -2,7 +2,7 @@ use alloc::{string::String, vec::Vec};
use std::{ use std::{
fs::File, fs::File,
io::Write, io::Write,
sync::{atomic::AtomicBool, RwLock}, sync::{RwLock, atomic::AtomicBool},
}; };
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};

View File

@ -2,7 +2,7 @@ use alloc::vec::Vec;
use core::{mem, num::NonZero}; use core::{mem, num::NonZero};
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl_bolts::{rands::Rand, Error}; use libafl_bolts::{Error, rands::Rand};
use crate::common::nautilus::grammartec::{ use crate::common::nautilus::grammartec::{
chunkstore::ChunkStore, chunkstore::ChunkStore,

View File

@ -3,8 +3,8 @@ use std::fmt;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{ use libafl_bolts::{
rands::{loaded_dice::LoadedDiceSampler, Rand},
Error, Error,
rands::{Rand, loaded_dice::LoadedDiceSampler},
}; };
use crate::common::nautilus::grammartec::{ use crate::common::nautilus::grammartec::{

View File

@ -4,9 +4,9 @@ use std::{cmp, io, io::Write, marker::Sized};
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl_bolts::rands::Rand; use libafl_bolts::rands::Rand;
use pyo3::{ use pyo3::{
PyTypeInfo,
prelude::{PyObject, PyResult, Python}, prelude::{PyObject, PyResult, Python},
types::{PyAnyMethods, PyBytes, PyBytesMethods, PyString, PyStringMethods, PyTuple}, types::{PyAnyMethods, PyBytes, PyBytesMethods, PyString, PyStringMethods, PyTuple},
PyTypeInfo,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -380,11 +380,7 @@ impl Tree {
done_nterms.insert(nterm); done_nterms.insert(nterm);
} }
} }
if ret.is_empty() { if ret.is_empty() { None } else { Some(ret) }
None
} else {
Some(ret)
}
} }
#[expect(dead_code)] #[expect(dead_code)]

View File

@ -7,12 +7,12 @@ use std::path::Path;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error,
corpus::{ corpus::{
inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId, Corpus, CorpusId, HasTestcase, Testcase, inmemory_ondisk::InMemoryOnDiskCorpus,
HasTestcase, Testcase, ondisk::OnDiskMetadataFormat,
}, },
inputs::Input, inputs::Input,
Error,
}; };
/// A corpus that keeps a maximum number of [`Testcase`]s in memory /// A corpus that keeps a maximum number of [`Testcase`]s in memory

View File

@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize};
use super::HasTestcase; use super::HasTestcase;
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase},
Error, Error,
corpus::{Corpus, CorpusId, Testcase},
}; };
/// Keep track of the stored `Testcase` and the siblings ids (insertion order) /// Keep track of the stored `Testcase` and the siblings ids (insertion order)
@ -60,10 +60,9 @@ impl<I> TestcaseStorageMap<I> {
/// Replace a testcase given a `CorpusId` /// Replace a testcase given a `CorpusId`
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> { pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
if let Some(entry) = self.map.get_mut(&id) { match self.map.get_mut(&id) {
Some(entry.testcase.replace(testcase)) Some(entry) => Some(entry.testcase.replace(testcase)),
} else { _ => None,
None
} }
} }
@ -76,23 +75,30 @@ impl<I> TestcaseStorageMap<I> {
/// Remove a testcase given a [`CorpusId`] /// Remove a testcase given a [`CorpusId`]
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> { pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
if let Some(item) = self.map.remove(&id) { match self.map.remove(&id) {
self.remove_key(id); Some(item) => {
if let Some(prev) = item.prev { self.remove_key(id);
self.map.get_mut(&prev).unwrap().next = item.next; match item.prev {
} else { Some(prev) => {
// first elem self.map.get_mut(&prev).unwrap().next = item.next;
self.first_id = item.next; }
_ => {
// first elem
self.first_id = item.next;
}
}
match item.next {
Some(next) => {
self.map.get_mut(&next).unwrap().prev = item.prev;
}
_ => {
// last elem
self.last_id = item.prev;
}
}
Some(item.testcase)
} }
if let Some(next) = item.next { _ => None,
self.map.get_mut(&next).unwrap().prev = item.prev;
} else {
// last elem
self.last_id = item.prev;
}
Some(item.testcase)
} else {
None
} }
} }
@ -121,10 +127,9 @@ impl<I> TestcaseStorageMap<I> {
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
#[must_use] #[must_use]
pub fn next(&self, id: CorpusId) -> Option<CorpusId> { pub fn next(&self, id: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&id) { match self.map.get(&id) {
item.next Some(item) => item.next,
} else { _ => None,
None
} }
} }
@ -152,10 +157,9 @@ impl<I> TestcaseStorageMap<I> {
#[cfg(not(feature = "corpus_btreemap"))] #[cfg(not(feature = "corpus_btreemap"))]
#[must_use] #[must_use]
pub fn prev(&self, id: CorpusId) -> Option<CorpusId> { pub fn prev(&self, id: CorpusId) -> Option<CorpusId> {
if let Some(item) = self.map.get(&id) { match self.map.get(&id) {
item.prev Some(item) => item.prev,
} else { _ => None,
None
} }
} }

View File

@ -20,13 +20,13 @@ use libafl_bolts::compress::GzipCompressor;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::{ use super::{
ondisk::{OnDiskMetadata, OnDiskMetadataFormat},
HasTestcase, HasTestcase,
ondisk::{OnDiskMetadata, OnDiskMetadataFormat},
}; };
use crate::{ use crate::{
Error, HasMetadata,
corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase}, corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase},
inputs::Input, inputs::Input,
Error, HasMetadata,
}; };
/// Creates the given `path` and returns an error if it fails. /// Creates the given `path` and returns an error if it fails.

View File

@ -6,14 +6,14 @@ use core::{hash::Hash, marker::PhantomData};
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use libafl_bolts::{ use libafl_bolts::{
current_time, AsIter, Named, current_time,
tuples::{Handle, Handled}, tuples::{Handle, Handled},
AsIter, Named,
}; };
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use z3::{ast::Bool, Config, Context, Optimize}; use z3::{Config, Context, Optimize, ast::Bool};
use crate::{ use crate::{
Error, HasMetadata, HasScheduler,
corpus::Corpus, corpus::Corpus,
events::{Event, EventFirer, LogSeverity}, events::{Event, EventFirer, LogSeverity},
executors::{Executor, HasObservers}, executors::{Executor, HasObservers},
@ -22,7 +22,6 @@ use crate::{
observers::{MapObserver, ObserversTuple}, observers::{MapObserver, ObserversTuple},
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore}, schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
state::{HasCorpus, HasExecutions}, state::{HasCorpus, HasExecutions},
Error, HasMetadata, HasScheduler,
}; };
/// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`. /// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`.

View File

@ -4,8 +4,8 @@ use core::{cell::RefCell, marker::PhantomData};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
corpus::{Corpus, CorpusId, Testcase},
Error, Error,
corpus::{Corpus, CorpusId, Testcase},
}; };
/// A corpus which does not store any [`Testcase`]s. /// A corpus which does not store any [`Testcase`]s.

View File

@ -16,9 +16,9 @@ use libafl_bolts::serdeany::SerdeAnyMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error,
corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase}, corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase},
inputs::Input, inputs::Input,
Error,
}; };
/// Options for the the format of the on-disk metadata /// Options for the the format of the on-disk metadata

View File

@ -11,11 +11,11 @@ use core::{
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::path::PathBuf; use std::path::PathBuf;
use libafl_bolts::{serdeany::SerdeAnyMap, HasLen}; use libafl_bolts::{HasLen, serdeany::SerdeAnyMap};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::Corpus; use super::Corpus;
use crate::{corpus::CorpusId, Error, HasMetadata}; use crate::{Error, HasMetadata, corpus::CorpusId};
/// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`]. /// Shorthand to receive a [`Ref`] or [`RefMut`] to a stored [`Testcase`], by [`CorpusId`].
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives. /// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.

View File

@ -1,17 +1,17 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use core::{fmt::Debug, marker::PhantomData}; use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::{
ClientId, Error,
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED}; use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
use libafl_bolts::{
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
ClientId, Error,
};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use crate::events::COMPRESS_THRESHOLD; use crate::events::COMPRESS_THRESHOLD;
use crate::events::{BrokerEventResult, Event, _LLMP_TAG_TO_MAIN}; use crate::events::{_LLMP_TAG_TO_MAIN, BrokerEventResult, Event};
/// An LLMP-backed event manager for scalable multi-processed fuzzing /// An LLMP-backed event manager for scalable multi-processed fuzzing
pub struct CentralizedLlmpHook<I> { pub struct CentralizedLlmpHook<I> {

View File

@ -9,9 +9,9 @@ use std::{
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::llmp::LLMP_FLAG_COMPRESSED; use libafl_bolts::llmp::LLMP_FLAG_COMPRESSED;
use libafl_bolts::{ use libafl_bolts::{
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag, LLMP_FLAG_FROM_MM},
ownedref::OwnedRef,
ClientId, Error, ClientId, Error,
llmp::{Flags, LLMP_FLAG_FROM_MM, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
ownedref::OwnedRef,
}; };
use serde::Serialize; use serde::Serialize;
use tokio::{ use tokio::{
@ -23,9 +23,9 @@ use tokio::{
use crate::{ use crate::{
events::{ events::{
Event,
centralized::_LLMP_TAG_TO_MAIN, centralized::_LLMP_TAG_TO_MAIN,
multi_machine::{MultiMachineMsg, TcpMultiMachineState}, multi_machine::{MultiMachineMsg, TcpMultiMachineState},
Event,
}, },
inputs::Input, inputs::Input,
}; };

View File

@ -2,20 +2,20 @@
use alloc::vec::Vec; use alloc::vec::Vec;
use core::marker::PhantomData; use core::marker::PhantomData;
use libafl_bolts::{
ClientId,
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED}; use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
use libafl_bolts::{
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
ClientId,
};
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use crate::events::llmp::COMPRESS_THRESHOLD; use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{ use crate::{
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
monitors::{stats::ClientStatsManager, Monitor},
Error, Error,
events::{BrokerEventResult, Event, llmp::LLMP_TAG_EVENT_TO_BOTH},
monitors::{Monitor, stats::ClientStatsManager},
}; };
/// centralized hook /// centralized hook

View File

@ -11,34 +11,33 @@ use alloc::{string::String, vec::Vec};
use core::{fmt::Debug, marker::PhantomData, time::Duration}; use core::{fmt::Debug, marker::PhantomData, time::Duration};
use std::process; use std::process;
use libafl_bolts::{
ClientId,
llmp::{LlmpClient, LlmpClientDescription, Tag},
shmem::{ShMem, ShMemProvider},
tuples::{Handle, MatchNameRef},
};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::{ use libafl_bolts::{
compress::GzipCompressor, compress::GzipCompressor,
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED}, llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
}; };
use libafl_bolts::{
llmp::{LlmpClient, LlmpClientDescription, Tag},
shmem::{ShMem, ShMemProvider},
tuples::{Handle, MatchNameRef},
ClientId,
};
use serde::Serialize; use serde::Serialize;
use super::{AwaitRestartSafe, RecordSerializationTime}; use super::{AwaitRestartSafe, RecordSerializationTime};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use crate::events::llmp::COMPRESS_THRESHOLD; use crate::events::llmp::COMPRESS_THRESHOLD;
use crate::{ use crate::{
Error,
common::HasMetadata, common::HasMetadata,
events::{ events::{
serialize_observers_adaptive, std_maybe_report_progress, std_report_progress,
AdaptiveSerializer, CanSerializeObserver, Event, EventConfig, EventFirer, EventManagerId, AdaptiveSerializer, CanSerializeObserver, Event, EventConfig, EventFirer, EventManagerId,
EventReceiver, EventRestarter, HasEventManagerId, LogSeverity, ProgressReporter, EventReceiver, EventRestarter, HasEventManagerId, LogSeverity, ProgressReporter,
SendExiting, SendExiting, serialize_observers_adaptive, std_maybe_report_progress, std_report_progress,
}, },
inputs::Input, inputs::Input,
observers::TimeObserver, observers::TimeObserver,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable}, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
Error,
}; };
pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453); pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
@ -389,8 +388,13 @@ where
/// Write the config for a client `EventManager` to env vars, a new /// Write the config for a client `EventManager` to env vars, a new
/// client can reattach using [`CentralizedEventManagerBuilder::build_existing_client_from_env()`]. /// client can reattach using [`CentralizedEventManagerBuilder::build_existing_client_from_env()`].
pub fn to_env(&self, env_name: &str) { ///
self.client.to_env(env_name).unwrap(); /// # Safety
/// Writes to env variables and may only be done single-threaded.
pub unsafe fn to_env(&self, env_name: &str) {
unsafe {
self.client.to_env(env_name).unwrap();
}
} }
/// Know if this instance is main or secondary /// Know if this instance is main or secondary

View File

@ -4,7 +4,7 @@
//! other clients //! other clients
use libafl_bolts::ClientId; use libafl_bolts::ClientId;
use crate::{events::Event, Error}; use crate::{Error, events::Event};
/// The `broker_hooks` that are run before and after the event manager calls `try_receive` /// The `broker_hooks` that are run before and after the event manager calls `try_receive`
pub trait EventManagerHook<I, S> { pub trait EventManagerHook<I, S> {

View File

@ -22,21 +22,21 @@ use std::{net::SocketAddr, string::String};
use libafl_bolts::{ use libafl_bolts::{
core_affinity::{CoreId, Cores}, core_affinity::{CoreId, Cores},
shmem::ShMemProvider, shmem::ShMemProvider,
tuples::{tuple_list, Handle}, tuples::{Handle, tuple_list},
}; };
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{Deserialize, Serialize, de::DeserializeOwned};
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
#[cfg(all(unix, feature = "fork"))] #[cfg(all(unix, feature = "fork"))]
use { use {
crate::{ crate::{
events::{centralized::CentralizedEventManager, CentralizedLlmpHook, StdLlmpEventHook}, events::{CentralizedLlmpHook, StdLlmpEventHook, centralized::CentralizedEventManager},
inputs::Input, inputs::Input,
}, },
alloc::string::ToString, alloc::string::ToString,
libafl_bolts::{ libafl_bolts::{
core_affinity::get_core_ids, core_affinity::get_core_ids,
llmp::{Broker, Brokers, LlmpBroker}, llmp::{Broker, Brokers, LlmpBroker},
os::{fork, ForkResult}, os::{ForkResult, fork},
}, },
std::boxed::Box, std::boxed::Box,
}; };
@ -51,13 +51,13 @@ use {libafl_bolts::os::startable_self, std::process::Stdio};
#[cfg(all(unix, feature = "fork", feature = "multi_machine"))] #[cfg(all(unix, feature = "fork", feature = "multi_machine"))]
use crate::events::multi_machine::{NodeDescriptor, TcpMultiMachineHooks}; use crate::events::multi_machine::{NodeDescriptor, TcpMultiMachineHooks};
use crate::{ use crate::{
Error,
events::{ events::{
llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr},
EventConfig, EventManagerHooksTuple, EventConfig, EventManagerHooksTuple,
llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr},
}, },
monitors::Monitor, monitors::Monitor,
observers::TimeObserver, observers::TimeObserver,
Error,
}; };
/// The (internal) `env` that indicates we're running as client. /// The (internal) `env` that indicates we're running as client.
@ -300,10 +300,13 @@ where
if !debug_output { if !debug_output {
if let Some(file) = &self.opened_stdout_file { if let Some(file) = &self.opened_stdout_file {
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?; dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
if let Some(stderr) = &self.opened_stderr_file { match &self.opened_stderr_file {
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; Some(stderr) => {
} else { dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; }
_ => {
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
}
} }
} }
} }
@ -365,7 +368,9 @@ where
} else { } else {
for handle in &handles { for handle in &handles {
let mut status = 0; let mut status = 0;
log::info!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."); log::info!(
"Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."
);
unsafe { unsafe {
libc::waitpid(*handle, &mut status, 0); libc::waitpid(*handle, &mut status, 0);
if status != 0 { if status != 0 {
@ -470,10 +475,14 @@ where
let client_description = let client_description =
ClientDescription::new(index, overcommit_i, core_id); ClientDescription::new(index, overcommit_i, core_id);
std::env::set_var( // # Safety
_AFL_LAUNCHER_CLIENT, // This is set only once, in here, for the child.
client_description.to_safe_string(), unsafe {
); std::env::set_var(
_AFL_LAUNCHER_CLIENT,
client_description.to_safe_string(),
);
}
let mut child = startable_self()?; let mut child = startable_self()?;
let child = (if debug_output { let child = (if debug_output {
&mut child &mut child
@ -522,7 +531,9 @@ where
handle.kill()?; handle.kill()?;
} }
} else { } else {
log::info!("Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."); log::info!(
"Not spawning broker (spawn_broker is false). Waiting for fuzzer children to exit..."
);
for handle in &mut handles { for handle in &mut handles {
let ecode = handle.wait()?; let ecode = handle.wait()?;
if !ecode.success() { if !ecode.success() {
@ -759,10 +770,13 @@ where
if !debug_output { if !debug_output {
if let Some(file) = &self.opened_stdout_file { if let Some(file) = &self.opened_stdout_file {
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?; dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
if let Some(stderr) = &self.opened_stderr_file { match &self.opened_stderr_file {
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?; Some(stderr) => {
} else { dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?; }
_ => {
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
}
} }
} }
} }

View File

@ -2,24 +2,24 @@
use core::{fmt::Debug, marker::PhantomData, time::Duration}; use core::{fmt::Debug, marker::PhantomData, time::Duration};
use libafl_bolts::{
ClientId,
llmp::{LlmpClient, LlmpClientDescription, Tag},
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::{ use libafl_bolts::{
compress::GzipCompressor, compress::GzipCompressor,
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED}, llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
}; };
use libafl_bolts::{ use serde::{Serialize, de::DeserializeOwned};
llmp::{LlmpClient, LlmpClientDescription, Tag},
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
ClientId,
};
use serde::{de::DeserializeOwned, Serialize};
use crate::{ use crate::{
Error,
events::{Event, EventFirer}, events::{Event, EventFirer},
fuzzer::EvaluatorObservers, fuzzer::EvaluatorObservers,
inputs::{Input, InputConverter, NopInput, NopInputConverter}, inputs::{Input, InputConverter, NopInput, NopInputConverter},
state::{HasCurrentTestcase, HasSolutions, NopState}, state::{HasCurrentTestcase, HasSolutions, NopState},
Error,
}; };
/// The llmp restarting manager /// The llmp restarting manager
@ -242,9 +242,14 @@ where
} }
/// Write the config for a client `EventManager` to env vars, a new client can reattach using [`LlmpEventConverterBuilder::build_existing_client_from_env()`]. /// Write the config for a client `EventManager` to env vars, a new client can reattach using [`LlmpEventConverterBuilder::build_existing_client_from_env()`].
///
/// # Safety
/// Writes to env variables and may only be done single-threaded.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn to_env(&self, env_name: &str) { pub unsafe fn to_env(&self, env_name: &str) {
self.llmp.to_env(env_name).unwrap(); unsafe {
self.llmp.to_env(env_name).unwrap();
}
} }
// Handle arriving events in the client // Handle arriving events in the client
@ -265,7 +270,9 @@ where
Event::NewTestcase { Event::NewTestcase {
input, forward_id, .. input, forward_id, ..
} => { } => {
log::debug!("Received new Testcase to convert from {client_id:?} (forward {forward_id:?}, forward {forward_id:?})"); log::debug!(
"Received new Testcase to convert from {client_id:?} (forward {forward_id:?}, forward {forward_id:?})"
);
let Some(converter) = self.converter_back.as_mut() else { let Some(converter) = self.converter_back.as_mut() else {
return Ok(()); return Ok(());

View File

@ -9,7 +9,7 @@ use alloc::vec::Vec;
use core::{ use core::{
marker::PhantomData, marker::PhantomData,
num::NonZeroUsize, num::NonZeroUsize,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
time::Duration, time::Duration,
}; };
use std::net::SocketAddr; use std::net::SocketAddr;
@ -21,7 +21,12 @@ use libafl_bolts::os::startable_self;
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
use libafl_bolts::os::unix_signals::setup_signal_handler; use libafl_bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(feature = "fork", unix))] #[cfg(all(feature = "fork", unix))]
use libafl_bolts::os::{fork, ForkResult}; use libafl_bolts::os::{ForkResult, fork};
#[cfg(feature = "std")]
use libafl_bolts::{
IP_LOCALHOST,
llmp::{TcpRequest, TcpResponse, recv_tcp_msg, send_tcp_msg},
};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::{ use libafl_bolts::{
compress::GzipCompressor, compress::GzipCompressor,
@ -31,19 +36,14 @@ use libafl_bolts::{
core_affinity::CoreId, core_affinity::CoreId,
current_time, current_time,
llmp::{ llmp::{
Broker, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection, LLMP_FLAG_FROM_MM, Broker, LLMP_FLAG_FROM_MM, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection,
}, },
os::CTRL_C_EXIT, os::CTRL_C_EXIT,
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider}, shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
staterestore::StateRestorer, staterestore::StateRestorer,
tuples::{tuple_list, Handle, MatchNameRef}, tuples::{Handle, MatchNameRef, tuple_list},
}; };
#[cfg(feature = "std")] use serde::{Serialize, de::DeserializeOwned};
use libafl_bolts::{
llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse},
IP_LOCALHOST,
};
use serde::{de::DeserializeOwned, Serialize};
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
@ -51,14 +51,15 @@ use crate::events::COMPRESS_THRESHOLD;
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{ use crate::{
Error,
common::HasMetadata, common::HasMetadata,
events::{ events::{
_LLMP_TAG_EVENT_TO_BROKER, AdaptiveSerializer, AwaitRestartSafe, CanSerializeObserver,
Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventReceiver,
EventRestarter, HasEventManagerId, LLMP_TAG_EVENT_TO_BOTH, LlmpShouldSaveState,
ProgressReporter, RecordSerializationTime, SendExiting, StdLlmpEventHook,
launcher::ClientDescription, serialize_observers_adaptive, std_maybe_report_progress, launcher::ClientDescription, serialize_observers_adaptive, std_maybe_report_progress,
std_report_progress, AdaptiveSerializer, AwaitRestartSafe, CanSerializeObserver, Event, std_report_progress,
EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventReceiver,
EventRestarter, HasEventManagerId, LlmpShouldSaveState, ProgressReporter,
RecordSerializationTime, SendExiting, StdLlmpEventHook, LLMP_TAG_EVENT_TO_BOTH,
_LLMP_TAG_EVENT_TO_BROKER,
}, },
inputs::Input, inputs::Input,
monitors::Monitor, monitors::Monitor,
@ -67,7 +68,6 @@ use crate::{
HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime,
HasSolutions, MaybeHasClientPerfMonitor, Stoppable, HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
}, },
Error,
}; };
const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4; const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4;
@ -285,7 +285,7 @@ where
SP: ShMemProvider<ShMem = SHM>, SP: ShMemProvider<ShMem = SHM>,
{ {
fn send_exiting(&mut self) -> Result<(), Error> { fn send_exiting(&mut self) -> Result<(), Error> {
if let Some(ref mut sr) = &mut self.staterestorer { if let Some(sr) = &mut self.staterestorer {
sr.send_exiting(); sr.send_exiting();
} }
// Also inform the broker that we are about to exit. // Also inform the broker that we are about to exit.
@ -366,7 +366,10 @@ where
.. ..
} => { } => {
#[cfg(feature = "std")] #[cfg(feature = "std")]
log::debug!("[{}] Received new Testcase {evt_name} from {client_id:?} ({client_config:?}, forward {forward_id:?})", std::process::id()); log::debug!(
"[{}] Received new Testcase {evt_name} from {client_id:?} ({client_config:?}, forward {forward_id:?})",
std::process::id()
);
if client_config.match_with(&self.configuration) && observers_buf.is_some() { if client_config.match_with(&self.configuration) && observers_buf.is_some() {
return Ok(Some((event, true))); return Ok(Some((event, true)));
@ -563,9 +566,14 @@ where
{ {
/// Write the config for a client `EventManager` to env vars, a new /// Write the config for a client `EventManager` to env vars, a new
/// client can reattach using [`LlmpEventManagerBuilder::build_existing_client_from_env()`]. /// client can reattach using [`LlmpEventManagerBuilder::build_existing_client_from_env()`].
///
/// # Safety
/// This will write to process env. Should only be called from a single thread at a time.
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn to_env(&self, env_name: &str) { pub unsafe fn to_env(&self, env_name: &str) {
self.llmp.to_env(env_name).unwrap(); unsafe {
self.llmp.to_env(env_name).unwrap();
}
} }
/// Get the staterestorer /// Get the staterestorer
@ -842,7 +850,9 @@ where
)?; )?;
broker_things(broker, self.remote_broker_addr)?; broker_things(broker, self.remote_broker_addr)?;
unreachable!("The broker may never return normally, only on errors or when shutting down."); unreachable!(
"The broker may never return normally, only on errors or when shutting down."
);
} }
ManagerKind::Client { client_description } => { ManagerKind::Client { client_description } => {
// We are a client // We are a client
@ -867,7 +877,11 @@ where
} }
// We are the fuzzer respawner in a llmp client // We are the fuzzer respawner in a llmp client
mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); // # Safety
// There should only ever be one launcher thread.
unsafe {
mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL);
}
// First, create a channel from the current fuzzer to the next to store state between restarts. // First, create a channel from the current fuzzer to the next to store state between restarts.
#[cfg(unix)] #[cfg(unix)]
@ -877,8 +891,13 @@ where
#[cfg(not(unix))] #[cfg(not(unix))]
let staterestorer: StateRestorer<SP::ShMem, SP> = let staterestorer: StateRestorer<SP::ShMem, SP> =
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?); StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
// Store the information to a map. // Store the information to a map.
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; // # Safety
// Very likely single threaded here.
unsafe {
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
@ -943,9 +962,14 @@ where
log::error!("Failed to detach from broker: {err}"); log::error!("Failed to detach from broker: {err}");
} }
#[cfg(unix)] #[cfg(unix)]
assert_ne!(9, child_status, "Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"); assert_ne!(
9, child_status,
"Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"
);
// Storing state in the last round did not work // Storing state in the last round did not work
panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); panic!(
"Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"
);
} }
ctr = ctr.wrapping_add(1); ctr = ctr.wrapping_add(1);
@ -1026,21 +1050,22 @@ where
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{Ordering, compiler_fence};
use libafl_bolts::{ use libafl_bolts::{
ClientId,
llmp::{LlmpClient, LlmpSharedMap}, llmp::{LlmpClient, LlmpSharedMap},
rands::StdRand, rands::StdRand,
shmem::{ShMemProvider, StdShMem, StdShMemProvider}, shmem::{ShMemProvider, StdShMem, StdShMemProvider},
staterestore::StateRestorer, staterestore::StateRestorer,
tuples::{tuple_list, Handled}, tuples::{Handled, tuple_list},
ClientId,
}; };
use serial_test::serial; use serial_test::serial;
use crate::{ use crate::{
StdFuzzer,
corpus::{Corpus, InMemoryCorpus, Testcase}, corpus::{Corpus, InMemoryCorpus, Testcase},
events::llmp::restarting::{LlmpEventManagerBuilder, _ENV_FUZZER_SENDER}, events::llmp::restarting::{_ENV_FUZZER_SENDER, LlmpEventManagerBuilder},
executors::{ExitKind, InProcessExecutor}, executors::{ExitKind, InProcessExecutor},
feedbacks::ConstFeedback, feedbacks::ConstFeedback,
fuzzer::Fuzzer, fuzzer::Fuzzer,
@ -1050,7 +1075,6 @@ mod tests {
schedulers::RandScheduler, schedulers::RandScheduler,
stages::StdMutationalStage, stages::StdMutationalStage,
state::StdState, state::StdState,
StdFuzzer,
}; };
#[test] #[test]
@ -1131,7 +1155,11 @@ mod tests {
assert!(staterestorer.has_content()); assert!(staterestorer.has_content());
// Store the information to a map. // Store the information to a map.
staterestorer.write_to_env(_ENV_FUZZER_SENDER).unwrap(); // # Safety
// Single-threaded test code
unsafe {
staterestorer.write_to_env(_ENV_FUZZER_SENDER).unwrap();
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);

View File

@ -34,9 +34,9 @@ pub use broker_hooks::*;
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use launcher::*; pub use launcher::*;
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
use libafl_bolts::os::unix_signals::{siginfo_t, ucontext_t, Signal, SignalHandler};
#[cfg(all(unix, feature = "std"))]
use libafl_bolts::os::CTRL_C_EXIT; use libafl_bolts::os::CTRL_C_EXIT;
#[cfg(all(unix, feature = "std"))]
use libafl_bolts::os::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use libafl_bolts::tuples::MatchNameRef; use libafl_bolts::tuples::MatchNameRef;
use libafl_bolts::{current_time, tuples::Handle}; use libafl_bolts::{current_time, tuples::Handle};
@ -45,11 +45,11 @@ use serde::{Deserialize, Serialize};
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
Error, HasMetadata,
executors::ExitKind, executors::ExitKind,
inputs::Input, inputs::Input,
monitors::stats::UserStats, monitors::stats::UserStats,
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor}, state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
Error, HasMetadata,
}; };
/// Multi-machine mode /// Multi-machine mode
@ -871,7 +871,7 @@ pub trait AdaptiveSerializer {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use libafl_bolts::{current_time, tuples::tuple_list, Named}; use libafl_bolts::{Named, current_time, tuples::tuple_list};
use tuple_list::tuple_list_type; use tuple_list::tuple_list_type;
use crate::{ use crate::{

View File

@ -5,17 +5,17 @@ use std::{
io::ErrorKind, io::ErrorKind,
process, process,
sync::{ sync::{
atomic::{AtomicU64, Ordering},
Arc, OnceLock, Arc, OnceLock,
atomic::{AtomicU64, Ordering},
}, },
time::Duration, time::Duration,
vec::Vec, vec::Vec,
}; };
use enumflags2::{bitflags, BitFlags}; use enumflags2::{BitFlags, bitflags};
#[cfg(feature = "llmp_compression")] #[cfg(feature = "llmp_compression")]
use libafl_bolts::compress::GzipCompressor; use libafl_bolts::compress::GzipCompressor;
use libafl_bolts::{current_time, ownedref::OwnedRef, Error}; use libafl_bolts::{Error, current_time, ownedref::OwnedRef};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::{ use tokio::{
io::{AsyncReadExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncWriteExt},
@ -216,34 +216,35 @@ where
where where
I: Input + Send + Sync + 'static, I: Input + Send + Sync + 'static,
{ {
let node_descriptor = self.node_descriptor.take().ok_or_else(|| {
Error::illegal_state(
"The node descriptor can never be `None` at this point in the code",
)
})?;
// Create the state of the hook. This will be shared with the background server, so we wrap
// it with concurrent-safe objects
let state = Arc::new(RwLock::new(TcpMultiMachineState {
node_descriptor,
parent: None,
children: HashMap::default(),
old_msgs: Vec::new(),
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::new(),
}));
let rt =
Arc::new(Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?);
unsafe { unsafe {
TcpMultiMachineState::init::<I>(&state.clone(), &rt.clone())?; let node_descriptor = self.node_descriptor.take().ok_or_else(|| {
} Error::illegal_state(
"The node descriptor can never be `None` at this point in the code",
)
})?;
Ok(TcpMultiMachineHooks { // Create the state of the hook. This will be shared with the background server, so we wrap
sender: TcpMultiMachineLlmpSenderHook::new(state.clone(), rt.clone()), // it with concurrent-safe objects
receiver: TcpMultiMachineLlmpReceiverHook::new(state, rt), let state = Arc::new(RwLock::new(TcpMultiMachineState {
}) node_descriptor,
parent: None,
children: HashMap::default(),
old_msgs: Vec::new(),
#[cfg(feature = "llmp_compression")]
compressor: GzipCompressor::new(),
}));
let rt = Arc::new(
Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?,
);
TcpMultiMachineState::init::<I>(&state.clone(), &rt.clone())?;
Ok(TcpMultiMachineHooks {
sender: TcpMultiMachineLlmpSenderHook::new(state.clone(), rt.clone()),
receiver: TcpMultiMachineLlmpReceiverHook::new(state, rt),
})
}
} }
} }

View File

@ -2,44 +2,44 @@
use alloc::vec::Vec; use alloc::vec::Vec;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{Ordering, compiler_fence};
use core::{fmt::Debug, marker::PhantomData, time::Duration}; use core::{fmt::Debug, marker::PhantomData, time::Duration};
use libafl_bolts::ClientId;
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))] #[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
use libafl_bolts::os::startable_self; use libafl_bolts::os::startable_self;
#[cfg(all(unix, feature = "std", not(miri)))] #[cfg(all(unix, feature = "std", not(miri)))]
use libafl_bolts::os::unix_signals::setup_signal_handler; use libafl_bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(feature = "std", feature = "fork", unix))] #[cfg(all(feature = "std", feature = "fork", unix))]
use libafl_bolts::os::{fork, ForkResult}; use libafl_bolts::os::{ForkResult, fork};
use libafl_bolts::ClientId;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use libafl_bolts::{ use libafl_bolts::{
os::CTRL_C_EXIT, os::CTRL_C_EXIT,
shmem::{ShMem, ShMemProvider}, shmem::{ShMem, ShMemProvider},
staterestore::StateRestorer, staterestore::StateRestorer,
}; };
use serde::Serialize;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use serde::Serialize;
use super::{std_on_restart, AwaitRestartSafe, ProgressReporter, RecordSerializationTime}; use super::{AwaitRestartSafe, ProgressReporter, RecordSerializationTime, std_on_restart};
#[cfg(all(unix, feature = "std", not(miri)))] #[cfg(all(unix, feature = "std", not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{ use crate::{
Error, HasMetadata,
events::{ events::{
std_maybe_report_progress, std_report_progress, BrokerEventResult, CanSerializeObserver, BrokerEventResult, CanSerializeObserver, Event, EventFirer, EventManagerId, EventReceiver,
Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, EventRestarter, HasEventManagerId, SendExiting, std_maybe_report_progress,
SendExiting, std_report_progress,
}, },
monitors::{stats::ClientStatsManager, Monitor}, monitors::{Monitor, stats::ClientStatsManager},
state::{ state::{
HasCurrentStageId, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable, HasCurrentStageId, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable,
}, },
Error, HasMetadata,
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::{ use crate::{
monitors::{stats::ClientStats, SimplePrintingMonitor}, monitors::{SimplePrintingMonitor, stats::ClientStats},
state::HasSolutions, state::HasSolutions,
}; };
@ -132,7 +132,7 @@ where
_ => { _ => {
return Err(Error::unknown(format!( return Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {event:?}." "Received illegal message that message should not have arrived: {event:?}."
))) )));
} }
} }
} }
@ -454,7 +454,12 @@ where
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?); StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
//let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? }; //let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? };
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
// # Safety
// Launcher is usually running in a single thread.
unsafe {
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
@ -509,10 +514,14 @@ where
if !staterestorer.has_content() { if !staterestorer.has_content() {
#[cfg(unix)] #[cfg(unix)]
if child_status == 9 { if child_status == 9 {
panic!("Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"); panic!(
"Target received SIGKILL!. This could indicate the target crashed due to OOM, user sent SIGKILL, or the target was in an unrecoverable situation and could not save state to restart"
);
} }
// Storing state in the last round did not work // Storing state in the last round did not work
panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); panic!(
"Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"
);
} }
ctr = ctr.wrapping_add(1); ctr = ctr.wrapping_add(1);

View File

@ -4,7 +4,7 @@ use alloc::vec::Vec;
use core::{ use core::{
marker::PhantomData, marker::PhantomData,
num::NonZeroUsize, num::NonZeroUsize,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
time::Duration, time::Duration,
}; };
use std::{ use std::{
@ -21,38 +21,38 @@ use libafl_bolts::os::startable_self;
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
use libafl_bolts::os::unix_signals::setup_signal_handler; use libafl_bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(feature = "fork", unix))] #[cfg(all(feature = "fork", unix))]
use libafl_bolts::os::{fork, ForkResult}; use libafl_bolts::os::{ForkResult, fork};
use libafl_bolts::{ use libafl_bolts::{
ClientId,
core_affinity::CoreId, core_affinity::CoreId,
os::CTRL_C_EXIT, os::CTRL_C_EXIT,
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider}, shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
staterestore::StateRestorer, staterestore::StateRestorer,
tuples::tuple_list, tuples::tuple_list,
ClientId,
}; };
use serde::{de::DeserializeOwned, Serialize}; use serde::{Serialize, de::DeserializeOwned};
use tokio::{ use tokio::{
io::{AsyncReadExt, AsyncWriteExt}, io::{AsyncReadExt, AsyncWriteExt},
sync::{broadcast, broadcast::error::RecvError, mpsc}, sync::{broadcast, broadcast::error::RecvError, mpsc},
task::{spawn, JoinHandle}, task::{JoinHandle, spawn},
}; };
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
use super::{std_maybe_report_progress, std_report_progress, AwaitRestartSafe, SendExiting}; use super::{AwaitRestartSafe, SendExiting, std_maybe_report_progress, std_report_progress};
#[cfg(all(unix, not(miri)))] #[cfg(all(unix, not(miri)))]
use crate::events::EVENTMGR_SIGHANDLER_STATE; use crate::events::EVENTMGR_SIGHANDLER_STATE;
use crate::{ use crate::{
Error, HasMetadata,
events::{ events::{
std_on_restart, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId,
EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, std_on_restart,
}, },
inputs::Input, inputs::Input,
monitors::{stats::ClientStatsManager, Monitor}, monitors::{Monitor, stats::ClientStatsManager},
state::{ state::{
HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime,
HasSolutions, MaybeHasClientPerfMonitor, Stoppable, HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
}, },
Error, HasMetadata,
}; };
/// Tries to create (synchronously) a [`TcpListener`] that is `nonblocking` (for later use in tokio). /// Tries to create (synchronously) a [`TcpListener`] that is `nonblocking` (for later use in tokio).
@ -244,8 +244,9 @@ where
} }
if buf[..4] == this_client_id_bytes { if buf[..4] == this_client_id_bytes {
log::debug!("TCP Manager - Not forwarding message from this very client ({this_client_id:?})." log::debug!(
); "TCP Manager - Not forwarding message from this very client ({this_client_id:?})."
);
continue; continue;
} }
@ -573,8 +574,13 @@ where
S: HasExecutions + HasMetadata + HasImported + Stoppable, S: HasExecutions + HasMetadata + HasImported + Stoppable,
{ {
/// Write the client id for a client `EventManager` to env vars /// Write the client id for a client `EventManager` to env vars
pub fn to_env(&self, env_name: &str) { ///
env::set_var(env_name, format!("{}", self.client_id.0)); /// # Safety
/// This writes to env variables, and may only be done single-threaded
pub unsafe fn to_env(&self, env_name: &str) {
unsafe {
env::set_var(env_name, format!("{}", self.client_id.0));
}
} }
} }
@ -684,7 +690,9 @@ where
forward_id, forward_id,
.. ..
} => { } => {
log::info!("Received new Testcase from {other_client_id:?} ({client_config:?}, forward {forward_id:?})"); log::info!(
"Received new Testcase from {other_client_id:?} ({client_config:?}, forward {forward_id:?})"
);
if client_config.match_with(&self.configuration) if client_config.match_with(&self.configuration)
&& observers_buf.is_some() && observers_buf.is_some()
{ {
@ -704,7 +712,7 @@ where
return Err(Error::unknown(format!( return Err(Error::unknown(format!(
"Received illegal message that message should not have arrived: {:?}.", "Received illegal message that message should not have arrived: {:?}.",
event.name() event.name()
))) )));
} }
} }
} }
@ -1118,7 +1126,9 @@ where
)?; )?;
broker_things(event_broker, self.remote_broker_addr)?; broker_things(event_broker, self.remote_broker_addr)?;
unreachable!("The broker may never return normally, only on errors or when shutting down."); unreachable!(
"The broker may never return normally, only on errors or when shutting down."
);
} }
TcpManagerKind::Client { cpu_core } => { TcpManagerKind::Client { cpu_core } => {
// We are a client // We are a client
@ -1137,7 +1147,11 @@ where
} }
// We are the fuzzer respawner in a tcp client // We are the fuzzer respawner in a tcp client
mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL); // # Safety
// There should only ever be one thread doing launcher things.
unsafe {
mgr.to_env(_ENV_FUZZER_BROKER_CLIENT_INITIAL);
}
// First, create a channel from the current fuzzer to the next to store state between restarts. // First, create a channel from the current fuzzer to the next to store state between restarts.
#[cfg(unix)] #[cfg(unix)]
@ -1147,8 +1161,14 @@ where
#[cfg(not(unix))] #[cfg(not(unix))]
let staterestorer: StateRestorer<SP::ShMem, SP> = let staterestorer: StateRestorer<SP::ShMem, SP> =
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?); StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
// Store the information to a map. // Store the information to a map.
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?; // # Safety
// It's reasonable to assume launcher only gets called on a single thread.
// If not, nothing too bad will happen.
unsafe {
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
}
let mut ctr: u64 = 0; let mut ctr: u64 = 0;
// Client->parent loop // Client->parent loop
@ -1206,11 +1226,15 @@ where
if child_status == 137 { if child_status == 137 {
// Out of Memory, see https://tldp.org/LDP/abs/html/exitcodes.html // Out of Memory, see https://tldp.org/LDP/abs/html/exitcodes.html
// and https://github.com/AFLplusplus/LibAFL/issues/32 for discussion. // and https://github.com/AFLplusplus/LibAFL/issues/32 for discussion.
panic!("Fuzzer-respawner: The fuzzed target crashed with an out of memory error! Fix your harness, or switch to another executor (for example, a forkserver)."); panic!(
"Fuzzer-respawner: The fuzzed target crashed with an out of memory error! Fix your harness, or switch to another executor (for example, a forkserver)."
);
} }
// Storing state in the last round did not work // Storing state in the last round did not work
panic!("Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"); panic!(
"Fuzzer-respawner: Storing state in crashed fuzzer instance did not work, no point to spawn the next client! This can happen if the child calls `exit()`, in that case make sure it uses `abort()`, if it got killed unrecoverable (OOM), or if there is a bug in the fuzzer itself. (Child exited with: {child_status})"
);
} }
ctr = ctr.wrapping_add(1); ctr = ctr.wrapping_add(1);

View File

@ -7,8 +7,8 @@ use libafl_bolts::tuples::RefIndexable;
use super::HasTimeout; use super::HasTimeout;
use crate::{ use crate::{
executors::{Executor, ExitKind, HasObservers},
Error, Error,
executors::{Executor, ExitKind, HasObservers},
}; };
/// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one /// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one

View File

@ -22,9 +22,9 @@ use std::{
#[cfg(all(feature = "intel_pt", target_os = "linux"))] #[cfg(all(feature = "intel_pt", target_os = "linux"))]
use libafl_bolts::core_affinity::CoreId; use libafl_bolts::core_affinity::CoreId;
use libafl_bolts::{ use libafl_bolts::{
fs::{get_unique_std_input_file, InputFile},
tuples::{Handle, MatchName, RefIndexable},
AsSlice, AsSlice,
fs::{InputFile, get_unique_std_input_file},
tuples::{Handle, MatchName, RefIndexable},
}; };
#[cfg(all(feature = "intel_pt", target_os = "linux"))] #[cfg(all(feature = "intel_pt", target_os = "linux"))]
use libc::STDIN_FILENO; use libc::STDIN_FILENO;
@ -36,8 +36,9 @@ use nix::{
signal::Signal, signal::Signal,
wait::WaitStatus, wait::WaitStatus,
wait::{ wait::{
waitpid, WaitPidFlag, WaitPidFlag,
WaitStatus::{Exited, PtraceEvent, Signaled, Stopped}, WaitStatus::{Exited, PtraceEvent, Signaled, Stopped},
waitpid,
}, },
}, },
unistd::Pid, unistd::Pid,
@ -49,12 +50,12 @@ use super::HasTimeout;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use crate::executors::hooks::ExecutorHooksTuple; use crate::executors::hooks::ExecutorHooksTuple;
use crate::{ use crate::{
Error,
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
inputs::HasTargetBytes, inputs::HasTargetBytes,
observers::{ObserversTuple, StdErrObserver, StdOutObserver}, observers::{ObserversTuple, StdErrObserver, StdOutObserver},
state::HasExecutions, state::HasExecutions,
std::borrow::ToOwned, std::borrow::ToOwned,
Error,
}; };
/// How to deliver input to an external program /// How to deliver input to an external program
@ -151,13 +152,18 @@ where
InputLocation::StdIn => { InputLocation::StdIn => {
let mut handle = self.command.stdin(Stdio::piped()).spawn()?; let mut handle = self.command.stdin(Stdio::piped()).spawn()?;
let mut stdin = handle.stdin.take().unwrap(); let mut stdin = handle.stdin.take().unwrap();
if let Err(err) = stdin.write_all(input.target_bytes().as_slice()) { match stdin.write_all(input.target_bytes().as_slice()) {
if err.kind() != std::io::ErrorKind::BrokenPipe { Err(err) => {
return Err(err.into()); if err.kind() != std::io::ErrorKind::BrokenPipe {
return Err(err.into());
}
} }
} else if let Err(err) = stdin.flush() { _ => {
if err.kind() != std::io::ErrorKind::BrokenPipe { if let Err(err) = stdin.flush() {
return Err(err.into()); if err.kind() != std::io::ErrorKind::BrokenPipe {
return Err(err.into());
}
}
} }
} }
drop(stdin); drop(stdin);
@ -208,9 +214,9 @@ where
use nix::{ use nix::{
sys::{ sys::{
personality, ptrace, personality, ptrace,
signal::{raise, Signal}, signal::{Signal, raise},
}, },
unistd::{alarm, dup2, execve, fork, pipe, write, ForkResult}, unistd::{ForkResult, alarm, dup2, execve, fork, pipe, write},
}; };
match unsafe { fork() } { match unsafe { fork() } {
@ -482,9 +488,9 @@ where
// Stopped(pid, Signal::SIGKILL) if pid == child => ExitKind::Oom, // Stopped(pid, Signal::SIGKILL) if pid == child => ExitKind::Oom,
s => { s => {
// TODO other cases? // TODO other cases?
return Err(Error::unsupported( return Err(Error::unsupported(format!(
format!("Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})") "Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})"
)); )));
} }
}; };
@ -746,11 +752,11 @@ impl CommandExecutorBuilder {
/// }; /// };
/// ///
/// use libafl::{ /// use libafl::{
/// Error,
/// corpus::Corpus, /// corpus::Corpus,
/// executors::{command::CommandConfigurator, Executor}, /// executors::{Executor, command::CommandConfigurator},
/// inputs::{BytesInput, HasTargetBytes, Input}, /// inputs::{BytesInput, HasTargetBytes, Input},
/// state::HasExecutions, /// state::HasExecutions,
/// Error,
/// }; /// };
/// use libafl_bolts::AsSlice; /// use libafl_bolts::AsSlice;
/// #[derive(Debug)] /// #[derive(Debug)]
@ -861,8 +867,8 @@ mod tests {
use crate::{ use crate::{
events::SimpleEventManager, events::SimpleEventManager,
executors::{ executors::{
command::{CommandExecutor, InputLocation},
Executor, Executor,
command::{CommandExecutor, InputLocation},
}, },
fuzzer::NopFuzzer, fuzzer::NopFuzzer,
inputs::{BytesInput, NopInput}, inputs::{BytesInput, NopInput},

View File

@ -18,9 +18,9 @@ use serde::{Deserialize, Serialize};
use super::HasTimeout; use super::HasTimeout;
use crate::{ use crate::{
Error,
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
observers::{DifferentialObserversTuple, ObserversTuple}, observers::{DifferentialObserversTuple, ObserversTuple},
Error,
}; };
/// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one /// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
@ -200,23 +200,23 @@ where
{ {
#[expect(deprecated)] #[expect(deprecated)]
fn match_name<T>(&self, name: &str) -> Option<&T> { fn match_name<T>(&self, name: &str) -> Option<&T> {
if let Some(t) = self.primary.as_ref().match_name::<T>(name) { match self.primary.as_ref().match_name::<T>(name) {
Some(t) Some(t) => Some(t),
} else if let Some(t) = self.secondary.as_ref().match_name::<T>(name) { _ => match self.secondary.as_ref().match_name::<T>(name) {
Some(t) Some(t) => Some(t),
} else { _ => self.differential.match_name::<T>(name),
self.differential.match_name::<T>(name) },
} }
} }
#[expect(deprecated)] #[expect(deprecated)]
fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> { fn match_name_mut<T>(&mut self, name: &str) -> Option<&mut T> {
if let Some(t) = self.primary.as_mut().match_name_mut::<T>(name) { match self.primary.as_mut().match_name_mut::<T>(name) {
Some(t) Some(t) => Some(t),
} else if let Some(t) = self.secondary.as_mut().match_name_mut::<T>(name) { _ => match self.secondary.as_mut().match_name_mut::<T>(name) {
Some(t) Some(t) => Some(t),
} else { _ => self.differential.match_name_mut::<T>(name),
self.differential.match_name_mut::<T>(name) },
} }
} }
} }

View File

@ -19,18 +19,18 @@ use std::{
}; };
use libafl_bolts::{ use libafl_bolts::{
fs::{get_unique_std_input_file, InputFile}, AsSlice, AsSliceMut, Truncate,
fs::{InputFile, get_unique_std_input_file},
os::{dup2, pipes::Pipe}, os::{dup2, pipes::Pipe},
ownedref::OwnedSlice, ownedref::OwnedSlice,
shmem::{ShMem, ShMemProvider, UnixShMem, UnixShMemProvider}, shmem::{ShMem, ShMemProvider, UnixShMem, UnixShMemProvider},
tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable}, tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable},
AsSlice, AsSliceMut, Truncate,
}; };
use libc::RLIM_INFINITY; use libc::RLIM_INFINITY;
use nix::{ use nix::{
sys::{ sys::{
select::{pselect, FdSet}, select::{FdSet, pselect},
signal::{kill, SigSet, Signal}, signal::{SigSet, Signal, kill},
time::TimeSpec, time::TimeSpec,
wait::waitpid, wait::waitpid,
}, },
@ -40,15 +40,15 @@ use nix::{
use super::HasTimeout; use super::HasTimeout;
#[cfg(feature = "regex")] #[cfg(feature = "regex")]
use crate::observers::{ use crate::observers::{
get_asan_runtime_flags, get_asan_runtime_flags_with_log_path, AsanBacktraceObserver, AsanBacktraceObserver, get_asan_runtime_flags, get_asan_runtime_flags_with_log_path,
}; };
use crate::{ use crate::{
Error,
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter}, inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter},
mutators::Tokens, mutators::Tokens,
observers::{MapObserver, Observer, ObserversTuple}, observers::{MapObserver, Observer, ObserversTuple},
state::HasExecutions, state::HasExecutions,
Error,
}; };
const FORKSRV_FD: i32 = 198; const FORKSRV_FD: i32 = 198;
@ -365,7 +365,9 @@ impl Forkserver {
kill_signal: Signal, kill_signal: Signal,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let Some(coverage_map_size) = coverage_map_size else { let Some(coverage_map_size) = coverage_map_size else {
return Err(Error::unknown("Coverage map size unknown. Use coverage_map_size() to tell the forkserver about the map size.")); return Err(Error::unknown(
"Coverage map size unknown. Use coverage_map_size() to tell the forkserver about the map size.",
));
}; };
if env::var("AFL_MAP_SIZE").is_err() { if env::var("AFL_MAP_SIZE").is_err() {
@ -442,7 +444,7 @@ impl Forkserver {
Err(err) => { Err(err) => {
return Err(Error::illegal_state(format!( return Err(Error::illegal_state(format!(
"Could not spawn the forkserver: {err:#?}" "Could not spawn the forkserver: {err:#?}"
))) )));
} }
}; };
@ -648,8 +650,8 @@ where
impl ForkserverExecutor<(), (), (), UnixShMem, ()> { impl ForkserverExecutor<(), (), (), UnixShMem, ()> {
/// Builder for `ForkserverExecutor` /// Builder for `ForkserverExecutor`
#[must_use] #[must_use]
pub fn builder( pub fn builder()
) -> ForkserverExecutorBuilder<'static, NopTargetBytesConverter<BytesInput>, UnixShMemProvider> -> ForkserverExecutorBuilder<'static, NopTargetBytesConverter<BytesInput>, UnixShMemProvider>
{ {
ForkserverExecutorBuilder::new() ForkserverExecutorBuilder::new()
} }
@ -977,7 +979,11 @@ where
Some(provider) => { Some(provider) => {
// setup shared memory // setup shared memory
let mut shmem = provider.new_shmem(self.max_input_size + SHMEM_FUZZ_HDR_SIZE)?; let mut shmem = provider.new_shmem(self.max_input_size + SHMEM_FUZZ_HDR_SIZE)?;
shmem.write_to_env("__AFL_SHM_FUZZ_ID")?; // # Safety
// This is likely single threade here, we're likely fine if it's not.
unsafe {
shmem.write_to_env("__AFL_SHM_FUZZ_ID")?;
}
let size_in_bytes = (self.max_input_size + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes(); let size_in_bytes = (self.max_input_size + SHMEM_FUZZ_HDR_SIZE).to_ne_bytes();
shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]); shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]);
@ -1003,7 +1009,7 @@ where
None => { None => {
return Err(Error::illegal_argument( return Err(Error::illegal_argument(
"ForkserverExecutorBuilder::build: target file not found".to_string(), "ForkserverExecutorBuilder::build: target file not found".to_string(),
)) ));
} }
}; };
@ -1042,7 +1048,9 @@ where
let version: u32 = status as u32 - 0x41464c00_u32; let version: u32 = status as u32 - 0x41464c00_u32;
match version { match version {
0 => { 0 => {
return Err(Error::illegal_state("Fork server version is not assigned, this should not happen. Recompile target.")); return Err(Error::illegal_state(
"Fork server version is not assigned, this should not happen. Recompile target.",
));
} }
FS_NEW_VERSION_MIN..=FS_NEW_VERSION_MAX => { FS_NEW_VERSION_MIN..=FS_NEW_VERSION_MAX => {
// good, do nothing // good, do nothing
@ -1101,9 +1109,9 @@ where
let tokens_size_max = 0xffffff; let tokens_size_max = 0xffffff;
if !(2..=tokens_size_max).contains(&autotokens_size) { if !(2..=tokens_size_max).contains(&autotokens_size) {
return Err(Error::illegal_state( return Err(Error::illegal_state(format!(
format!("Autotokens size is incorrect, expected 2 to {tokens_size_max} (inclusive), but got {autotokens_size}. Make sure your afl-cc verison is up to date."), "Autotokens size is incorrect, expected 2 to {tokens_size_max} (inclusive), but got {autotokens_size}. Make sure your afl-cc verison is up to date."
)); )));
} }
log::info!("Autotokens size {autotokens_size:x}"); log::info!("Autotokens size {autotokens_size:x}");
let buf = forkserver let buf = forkserver
@ -1223,7 +1231,7 @@ where
return Err(Error::illegal_state(format!( return Err(Error::illegal_state(format!(
"The target map size is {actual_map_size} but the allocated map size is {max_size}. \ "The target map size is {actual_map_size} but the allocated map size is {max_size}. \
Increase the initial size of the forkserver map to at least that size using the forkserver builder's `coverage_map_size`." Increase the initial size of the forkserver map to at least that size using the forkserver builder's `coverage_map_size`."
))); )));
} }
} else { } else {
return Err(Error::illegal_state(format!( return Err(Error::illegal_state(format!(
@ -1280,11 +1288,14 @@ where
// subsequent arguments as regular arguments // subsequent arguments as regular arguments
use_arg_0_as_program = false; use_arg_0_as_program = false;
} else if item.as_ref() == "@@" { } else if item.as_ref() == "@@" {
if let Some(name) = &moved.input_filename.clone() { match &moved.input_filename.clone() {
// If the input file name has been modified, use this one Some(name) => {
moved = moved.arg_input_file(name); // If the input file name has been modified, use this one
} else { moved = moved.arg_input_file(name);
moved = moved.arg_input_file_std(); }
_ => {
moved = moved.arg_input_file_std();
}
} }
} else { } else {
moved = moved.arg(item); moved = moved.arg(item);
@ -1469,8 +1480,8 @@ impl<'a> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, Unix
/// in case no input file is specified. /// in case no input file is specified.
/// If `debug_child` is set, the child will print to `stdout`/`stderr`. /// If `debug_child` is set, the child will print to `stdout`/`stderr`.
#[must_use] #[must_use]
pub fn new( pub fn new()
) -> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, UnixShMemProvider> { -> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, UnixShMemProvider> {
ForkserverExecutorBuilder { ForkserverExecutorBuilder {
program: None, program: None,
arguments: vec![], arguments: vec![],
@ -1623,18 +1634,18 @@ mod tests {
use std::ffi::OsString; use std::ffi::OsString;
use libafl_bolts::{ use libafl_bolts::{
AsSliceMut,
shmem::{ShMem, ShMemProvider, UnixShMemProvider}, shmem::{ShMem, ShMemProvider, UnixShMemProvider},
tuples::tuple_list, tuples::tuple_list,
AsSliceMut,
}; };
use serial_test::serial; use serial_test::serial;
use crate::{ use crate::{
Error,
corpus::NopCorpus, corpus::NopCorpus,
executors::forkserver::{ForkserverExecutor, FAILED_TO_START_FORKSERVER_MSG}, executors::forkserver::{FAILED_TO_START_FORKSERVER_MSG, ForkserverExecutor},
inputs::BytesInput, inputs::BytesInput,
observers::{ConstMapObserver, HitcountsMapObserver}, observers::{ConstMapObserver, HitcountsMapObserver},
Error,
}; };
#[test] #[test]
@ -1648,7 +1659,11 @@ mod tests {
let mut shmem_provider = UnixShMemProvider::new().unwrap(); let mut shmem_provider = UnixShMemProvider::new().unwrap();
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap(); let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
shmem.write_to_env("__AFL_SHM_ID").unwrap(); // # Safety
// There's a slight chance this is racey but very unlikely in the normal use case
unsafe {
shmem.write_to_env("__AFL_SHM_ID").unwrap();
}
let shmem_buf: &mut [u8; MAP_SIZE] = shmem.as_slice_mut().try_into().unwrap(); let shmem_buf: &mut [u8; MAP_SIZE] = shmem.as_slice_mut().try_into().unwrap();
let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new( let edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(

View File

@ -2,7 +2,7 @@
#[cfg(all(target_os = "linux", feature = "std"))] #[cfg(all(target_os = "linux", feature = "std"))]
use core::mem::zeroed; use core::mem::zeroed;
#[cfg(any(unix, all(windows, feature = "std")))] #[cfg(any(unix, all(windows, feature = "std")))]
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{Ordering, compiler_fence};
use core::{ use core::{
ffi::c_void, ffi::c_void,
marker::PhantomData, marker::PhantomData,
@ -13,7 +13,7 @@ use core::{
#[cfg(all(target_os = "linux", feature = "std"))] #[cfg(all(target_os = "linux", feature = "std"))]
use libafl_bolts::current_time; use libafl_bolts::current_time;
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
use libafl_bolts::minibsod::{generate_minibsod_to_vec, BsodInfo}; use libafl_bolts::minibsod::{BsodInfo, generate_minibsod_to_vec};
#[cfg(all(unix, feature = "std", not(miri)))] #[cfg(all(unix, feature = "std", not(miri)))]
use libafl_bolts::os::unix_signals::setup_signal_handler; use libafl_bolts::os::unix_signals::setup_signal_handler;
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
@ -24,16 +24,16 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::executors::hooks::timer::TimerStruct; use crate::executors::hooks::timer::TimerStruct;
use crate::{ use crate::{
Error, HasObjective,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers}, executors::{Executor, HasObservers, hooks::ExecutorHook, inprocess::HasInProcessHooks},
feedbacks::Feedback, feedbacks::Feedback,
state::{HasExecutions, HasSolutions}, state::{HasExecutions, HasSolutions},
Error, HasObjective,
}; };
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
use crate::{ use crate::{
executors::{ executors::{
hooks::unix::unix_signal_handler, inprocess::run_observers_and_save_state, ExitKind, ExitKind, hooks::unix::unix_signal_handler, inprocess::run_observers_and_save_state,
}, },
state::HasCorpus, state::HasCorpus,
}; };
@ -445,43 +445,45 @@ impl InProcessExecutorHandlerData {
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
I: Input + Clone, I: Input + Clone,
{ {
if self.is_valid() { unsafe {
let executor = self.executor_mut::<E>(); if self.is_valid() {
// disarms timeout in case of timeout let executor = self.executor_mut::<E>();
let state = self.state_mut::<S>(); // disarms timeout in case of timeout
let event_mgr = self.event_mgr_mut::<EM>(); let state = self.state_mut::<S>();
let fuzzer = self.fuzzer_mut::<Z>(); let event_mgr = self.event_mgr_mut::<EM>();
let input = self.take_current_input::<I>(); let fuzzer = self.fuzzer_mut::<Z>();
let input = self.take_current_input::<I>();
log::error!("Target crashed!"); log::error!("Target crashed!");
if let Some(bsod_info) = bsod_info { if let Some(bsod_info) = bsod_info {
let bsod = generate_minibsod_to_vec( let bsod = generate_minibsod_to_vec(
bsod_info.signal, bsod_info.signal,
&bsod_info.siginfo, &bsod_info.siginfo,
bsod_info.ucontext.as_ref(), bsod_info.ucontext.as_ref(),
); );
if let Ok(bsod) = bsod { if let Ok(bsod) = bsod {
if let Ok(r) = std::str::from_utf8(&bsod) { if let Ok(r) = std::str::from_utf8(&bsod) {
log::error!("{}", r); log::error!("{}", r);
}
} }
} }
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
return true;
} }
run_observers_and_save_state::<E, EM, I, OF, S, Z>( false
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
return true;
} }
false
} }
} }

View File

@ -5,23 +5,22 @@ use core::{
marker::PhantomData, marker::PhantomData,
mem::transmute, mem::transmute,
ptr::null, ptr::null,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
}; };
#[cfg(not(miri))] #[cfg(not(miri))]
use libafl_bolts::os::unix_signals::setup_signal_handler; use libafl_bolts::os::unix_signals::setup_signal_handler;
use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; use libafl_bolts::os::unix_signals::{Signal, SignalHandler, ucontext_t};
use libc::siginfo_t; use libc::siginfo_t;
use crate::{ use crate::{
Error,
executors::{ executors::{
common_signals, HasObservers, common_signals,
hooks::ExecutorHook, hooks::ExecutorHook,
inprocess_fork::{child_signal_handlers, ForkHandlerFuncPtr}, inprocess_fork::{ForkHandlerFuncPtr, child_signal_handlers},
HasObservers,
}, },
observers::ObserversTuple, observers::ObserversTuple,
Error,
}; };
/// The inmem fork executor's hooks. /// The inmem fork executor's hooks.

View File

@ -10,7 +10,7 @@ pub(crate) const ITIMER_REAL: core::ffi::c_int = 0;
use core::{ use core::{
ffi::c_void, ffi::c_void,
ptr::write_volatile, ptr::write_volatile,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
}; };
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -19,9 +19,9 @@ use libafl_bolts::current_time;
use windows::Win32::{ use windows::Win32::{
Foundation::FILETIME, Foundation::FILETIME,
System::Threading::{ System::Threading::{
CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection, CRITICAL_SECTION, CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection,
LeaveCriticalSection, SetThreadpoolTimer, CRITICAL_SECTION, PTP_CALLBACK_INSTANCE, LeaveCriticalSection, PTP_CALLBACK_INSTANCE, PTP_TIMER, SetThreadpoolTimer,
PTP_TIMER, TP_CALLBACK_ENVIRON_V3, TP_CALLBACK_ENVIRON_V3,
}, },
}; };
@ -59,7 +59,7 @@ pub(crate) struct Itimerval {
} }
#[cfg(all(unix, not(target_os = "linux")))] #[cfg(all(unix, not(target_os = "linux")))]
extern "C" { unsafe extern "C" {
pub(crate) fn setitimer( pub(crate) fn setitimer(
which: libc::c_int, which: libc::c_int,
new_value: *mut Itimerval, new_value: *mut Itimerval,

View File

@ -5,16 +5,15 @@ pub mod unix_signal_handler {
use core::mem::transmute; use core::mem::transmute;
use std::{io::Write, panic}; use std::{io::Write, panic};
use libafl_bolts::os::unix_signals::{ucontext_t, Signal, SignalHandler}; use libafl_bolts::os::unix_signals::{Signal, SignalHandler, ucontext_t};
use libc::siginfo_t; use libc::siginfo_t;
use crate::{ use crate::{
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
common_signals, Executor, ExitKind, HasObservers, common_signals,
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE}, hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData},
inprocess::{run_observers_and_save_state, HasInProcessHooks}, inprocess::{HasInProcessHooks, run_observers_and_save_state},
Executor, ExitKind, HasObservers,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
@ -147,39 +146,41 @@ pub mod unix_signal_handler {
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
I: Input + Clone, I: Input + Clone,
{ {
// this stuff is for batch timeout unsafe {
if !data.executor_ptr.is_null() // this stuff is for batch timeout
&& data if !data.executor_ptr.is_null()
.executor_mut::<E>() && data
.inprocess_hooks_mut() .executor_mut::<E>()
.handle_timeout(data) .inprocess_hooks_mut()
{ .handle_timeout(data)
return; {
return;
}
if !data.is_valid() {
log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing.");
return;
}
let executor = data.executor_mut::<E>();
let state = data.state_mut::<S>();
let event_mgr = data.event_mgr_mut::<EM>();
let fuzzer = data.fuzzer_mut::<Z>();
let input = data.take_current_input::<I>();
log::error!("Timeout in fuzz run.");
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Timeout,
);
log::info!("Exiting");
libc::_exit(55);
} }
if !data.is_valid() {
log::warn!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing.");
return;
}
let executor = data.executor_mut::<E>();
let state = data.state_mut::<S>();
let event_mgr = data.event_mgr_mut::<EM>();
let fuzzer = data.fuzzer_mut::<Z>();
let input = data.take_current_input::<I>();
log::error!("Timeout in fuzz run.");
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Timeout,
);
log::info!("Exiting");
libc::_exit(55);
} }
/// Crash-Handler for in-process fuzzing. /// Crash-Handler for in-process fuzzing.
@ -203,68 +204,29 @@ pub mod unix_signal_handler {
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
I: Input + Clone, I: Input + Clone,
{ {
#[cfg(all(target_os = "android", target_arch = "aarch64"))] unsafe {
let _context = _context.map(|p| { #[cfg(all(target_os = "android", target_arch = "aarch64"))]
&mut *(((core::ptr::from_mut(p) as *mut libc::c_void as usize) + 128) let _context = _context.map(|p| {
as *mut libc::c_void as *mut ucontext_t) &mut *(((core::ptr::from_mut(p) as *mut libc::c_void as usize) + 128)
}); as *mut libc::c_void as *mut ucontext_t)
});
log::error!("Crashed with {signal}"); log::error!("Crashed with {signal}");
if data.is_valid() { if data.is_valid() {
let executor = data.executor_mut::<E>(); let executor = data.executor_mut::<E>();
// disarms timeout in case of timeout // disarms timeout in case of timeout
let state = data.state_mut::<S>(); let state = data.state_mut::<S>();
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = data.event_mgr_mut::<EM>();
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = data.fuzzer_mut::<Z>();
let input = data.take_current_input::<I>(); let input = data.take_current_input::<I>();
log::error!("Child crashed!"); log::error!("Child crashed!");
{
let mut bsod = Vec::new();
{
let mut writer = std::io::BufWriter::new(&mut bsod);
let _ = writeln!(writer, "input: {:?}", input.generate_name(None));
let bsod = libafl_bolts::minibsod::generate_minibsod(
&mut writer,
signal,
_info,
_context.as_deref(),
);
if bsod.is_err() {
log::error!("generate_minibsod failed");
}
let _ = writer.flush();
}
if let Ok(r) = std::str::from_utf8(&bsod) {
log::error!("{}", r);
}
}
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
} else {
{
log::error!("Double crash\n");
#[cfg(target_os = "android")]
let si_addr = (_info._pad[0] as i64) | ((_info._pad[1] as i64) << 32);
#[cfg(not(target_os = "android"))]
let si_addr = { _info.si_addr() as usize };
log::error!(
"We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
);
{ {
let mut bsod = Vec::new(); let mut bsod = Vec::new();
{ {
let mut writer = std::io::BufWriter::new(&mut bsod); let mut writer = std::io::BufWriter::new(&mut bsod);
let _ = writeln!(writer, "input: {:?}", input.generate_name(None));
let bsod = libafl_bolts::minibsod::generate_minibsod( let bsod = libafl_bolts::minibsod::generate_minibsod(
&mut writer, &mut writer,
signal, signal,
@ -280,19 +242,60 @@ pub mod unix_signal_handler {
log::error!("{}", r); log::error!("{}", r);
} }
} }
}
{ run_observers_and_save_state::<E, EM, I, OF, S, Z>(
log::error!("Type QUIT to restart the child"); executor,
let mut line = String::new(); state,
while line.trim() != "QUIT" { input,
let _ = std::io::stdin().read_line(&mut line); fuzzer,
event_mgr,
ExitKind::Crash,
);
} else {
{
log::error!("Double crash\n");
#[cfg(target_os = "android")]
let si_addr = (_info._pad[0] as i64) | ((_info._pad[1] as i64) << 32);
#[cfg(not(target_os = "android"))]
let si_addr = { _info.si_addr() as usize };
log::error!(
"We crashed at addr 0x{si_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
);
{
let mut bsod = Vec::new();
{
let mut writer = std::io::BufWriter::new(&mut bsod);
let bsod = libafl_bolts::minibsod::generate_minibsod(
&mut writer,
signal,
_info,
_context.as_deref(),
);
if bsod.is_err() {
log::error!("generate_minibsod failed");
}
let _ = writer.flush();
}
if let Ok(r) = std::str::from_utf8(&bsod) {
log::error!("{}", r);
}
}
} }
{
log::error!("Type QUIT to restart the child");
let mut line = String::new();
while line.trim() != "QUIT" {
let _ = std::io::stdin().read_line(&mut line);
}
}
// TODO tell the parent to not restart
} }
// TODO tell the parent to not restart libc::_exit(128 + (signal as i32));
} }
libc::_exit(128 + (signal as i32));
} }
} }

View File

@ -1,18 +1,18 @@
/// Same as `inproc_crash_handler`, but this is called when address sanitizer exits, not from the exception handler /// In-Process crash handling for `Windows`
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
pub mod windows_asan_handler { pub mod windows_asan_handler {
use alloc::string::String; use alloc::string::String;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{Ordering, compiler_fence};
use windows::Win32::System::Threading::{ use windows::Win32::System::Threading::{
EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION, CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection,
}; };
use crate::{ use crate::{
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor, Executor, ExitKind, HasObservers, hooks::inprocess::GLOBAL_STATE,
ExitKind, HasObservers, inprocess::run_observers_and_save_state,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
@ -33,75 +33,79 @@ pub mod windows_asan_handler {
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
{ {
let data = &raw mut GLOBAL_STATE; unsafe {
let in_handler = (*data).set_in_handler(true); let data = &raw mut GLOBAL_STATE;
let in_handler = (*data).set_in_handler(true);
if in_handler { if in_handler {
log::error!("We crashed inside a asan death handler, but this should never happen!");
ExitProcess(56);
}
// Have we set a timer_before?
if (*data).ptp_timer.is_some() {
/*
We want to prevent the timeout handler being run while the main thread is executing the crash handler
Timeout handler runs if it has access to the critical section or data.in_target == 0
Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid.
*/
compiler_fence(Ordering::SeqCst);
EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst);
(*data).in_target = 0;
compiler_fence(Ordering::SeqCst);
LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst);
}
log::error!("ASAN detected crash!");
if (*data).current_input_ptr.is_null() {
{
log::error!("Double crash\n");
log::error!( log::error!(
"ASAN detected crash but we're not in the target... Bug in the fuzzer? Exiting.", "We crashed inside a asan death handler, but this should never happen!"
);
ExitProcess(56);
}
// Have we set a timer_before?
if (*data).ptp_timer.is_some() {
/*
We want to prevent the timeout handler being run while the main thread is executing the crash handler
Timeout handler runs if it has access to the critical section or data.in_target == 0
Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid.
*/
compiler_fence(Ordering::SeqCst);
EnterCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst);
(*data).in_target = 0;
compiler_fence(Ordering::SeqCst);
LeaveCriticalSection((*data).critical as *mut CRITICAL_SECTION);
compiler_fence(Ordering::SeqCst);
}
log::error!("ASAN detected crash!");
if (*data).current_input_ptr.is_null() {
{
log::error!("Double crash\n");
log::error!(
"ASAN detected crash but we're not in the target... Bug in the fuzzer? Exiting.",
);
}
#[cfg(feature = "std")]
{
log::error!("Type QUIT to restart the child");
let mut line = String::new();
while line.trim() != "QUIT" {
let _ = std::io::stdin().read_line(&mut line);
}
}
// TODO tell the parent to not restart
} else {
let executor = (*data).executor_mut::<E>();
// reset timer
if (*data).ptp_timer.is_some() {
(*data).ptp_timer = None;
}
let state = (*data).state_mut::<S>();
let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = (*data).event_mgr_mut::<EM>();
log::error!("Child crashed!");
// Make sure we don't crash in the crash handler forever.
let input = (*data).take_current_input::<I>();
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
); );
} }
#[cfg(feature = "std")] // Don't need to exit, Asan will exit for us
{ // ExitProcess(1);
log::error!("Type QUIT to restart the child");
let mut line = String::new();
while line.trim() != "QUIT" {
let _ = std::io::stdin().read_line(&mut line);
}
}
// TODO tell the parent to not restart
} else {
let executor = (*data).executor_mut::<E>();
// reset timer
if (*data).ptp_timer.is_some() {
(*data).ptp_timer = None;
}
let state = (*data).state_mut::<S>();
let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = (*data).event_mgr_mut::<EM>();
log::error!("Child crashed!");
// Make sure we don't crash in the crash handler forever.
let input = (*data).take_current_input::<I>();
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor,
state,
input,
fuzzer,
event_mgr,
ExitKind::Crash,
);
} }
// Don't need to exit, Asan will exit for us
// ExitProcess(1);
} }
} }
@ -115,7 +119,7 @@ pub mod windows_exception_handler {
ffi::c_void, ffi::c_void,
mem::transmute, mem::transmute,
ptr, ptr,
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
}; };
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::io::Write; use std::io::Write;
@ -123,19 +127,19 @@ pub mod windows_exception_handler {
use std::panic; use std::panic;
use libafl_bolts::os::windows_exceptions::{ use libafl_bolts::os::windows_exceptions::{
ExceptionCode, ExceptionHandler, CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, ExceptionCode,
EXCEPTION_POINTERS, ExceptionHandler,
}; };
use windows::Win32::System::Threading::{ use windows::Win32::System::Threading::{
EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION, CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection,
}; };
use crate::{ use crate::{
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE},
inprocess::{run_observers_and_save_state, HasInProcessHooks},
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData},
inprocess::{HasInProcessHooks, run_observers_and_save_state},
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
@ -270,36 +274,41 @@ pub mod windows_exception_handler {
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
{ {
let data: &mut InProcessExecutorHandlerData = let data: &mut InProcessExecutorHandlerData =
&mut *(global_state as *mut InProcessExecutorHandlerData); unsafe { &mut *(global_state as *mut InProcessExecutorHandlerData) };
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
EnterCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); unsafe {
EnterCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
if !data.executor_ptr.is_null() if !data.executor_ptr.is_null()
&& data && unsafe {
.executor_mut::<E>() data.executor_mut::<E>()
.inprocess_hooks_mut() .inprocess_hooks_mut()
.handle_timeout() .handle_timeout()
}
{ {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); unsafe {
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
return; return;
} }
if data.in_target == 1 { if data.in_target == 1 {
let executor = data.executor_mut::<E>(); let executor = unsafe { data.executor_mut::<E>() };
let state = data.state_mut::<S>(); let state = unsafe { data.state_mut::<S>() };
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = unsafe { data.fuzzer_mut::<Z>() };
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = unsafe { data.event_mgr_mut::<EM>() };
if data.current_input_ptr.is_null() { if data.current_input_ptr.is_null() {
log::error!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting"); log::error!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
} else { } else {
log::error!("Timeout in fuzz run."); log::error!("Timeout in fuzz run.");
let input = (data.current_input_ptr as *const I).as_ref().unwrap(); let input = unsafe { (data.current_input_ptr as *const I).as_ref().unwrap() };
data.current_input_ptr = ptr::null_mut(); data.current_input_ptr = ptr::null_mut();
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, I, OF, S, Z>(
@ -313,11 +322,15 @@ pub mod windows_exception_handler {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
ExitProcess(1); unsafe {
ExitProcess(1);
}
} }
} }
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap()); unsafe {
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
// log::info!("TIMER INVOKED!"); // log::info!("TIMER INVOKED!");
} }
@ -346,37 +359,43 @@ pub mod windows_exception_handler {
Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid. Writing 0 to the data.in_target makes the timeout handler makes the timeout handler invalid.
*/ */
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
EnterCriticalSection(data.critical as *mut CRITICAL_SECTION); unsafe {
EnterCriticalSection(data.critical as *mut CRITICAL_SECTION);
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
data.in_target = 0; data.in_target = 0;
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION); unsafe {
LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION);
}
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
} }
// Is this really crash? // Is this really crash?
let mut is_crash = true; let mut is_crash = true;
#[cfg(feature = "std")] #[cfg(feature = "std")]
if let Some(exception_pointers) = exception_pointers.as_mut() { if let Some(exception_pointers) = unsafe { exception_pointers.as_mut() } {
let code: ExceptionCode = ExceptionCode::from( let code: ExceptionCode = ExceptionCode::from(unsafe {
exception_pointers exception_pointers
.ExceptionRecord .ExceptionRecord
.as_mut() .as_mut()
.unwrap() .unwrap()
.ExceptionCode .ExceptionCode
.0, .0
); });
let exception_list = data.exceptions(); let exception_list = data.exceptions();
if exception_list.contains(&code) { if exception_list.contains(&code) {
log::error!( log::error!(
"Crashed with {code} at {:?} in thread {:?}", "Crashed with {code} at {:?} in thread {:?}",
exception_pointers unsafe {
.ExceptionRecord exception_pointers
.as_mut() .ExceptionRecord
.unwrap() .as_mut()
.ExceptionAddress, .unwrap()
winapi::um::processthreadsapi::GetCurrentThreadId() .ExceptionAddress
},
unsafe { winapi::um::processthreadsapi::GetCurrentThreadId() }
); );
} else { } else {
// log::trace!("Exception code received, but {code} is not in CRASH_EXCEPTIONS"); // log::trace!("Exception code received, but {code} is not in CRASH_EXCEPTIONS");
@ -389,16 +408,18 @@ pub mod windows_exception_handler {
if data.current_input_ptr.is_null() { if data.current_input_ptr.is_null() {
{ {
log::error!("Double crash\n"); log::error!("Double crash\n");
let crash_addr = exception_pointers let crash_addr = unsafe {
.as_mut() exception_pointers
.unwrap() .as_mut()
.ExceptionRecord .unwrap()
.as_mut() .ExceptionRecord
.unwrap() .as_mut()
.ExceptionAddress as usize; .unwrap()
.ExceptionAddress as usize
};
log::error!( log::error!(
"We crashed at addr 0x{crash_addr:x}, but are not in the target... Bug in the fuzzer? Exiting." "We crashed at addr 0x{crash_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
); );
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -412,15 +433,15 @@ pub mod windows_exception_handler {
// TODO tell the parent to not restart // TODO tell the parent to not restart
} else { } else {
let executor = data.executor_mut::<E>(); let executor = unsafe { data.executor_mut::<E>() };
// reset timer // reset timer
if data.ptp_timer.is_some() { if data.ptp_timer.is_some() {
data.ptp_timer = None; data.ptp_timer = None;
} }
let state = data.state_mut::<S>(); let state = unsafe { data.state_mut::<S>() };
let fuzzer = data.fuzzer_mut::<Z>(); let fuzzer = unsafe { data.fuzzer_mut::<Z>() };
let event_mgr = data.event_mgr_mut::<EM>(); let event_mgr = unsafe { data.event_mgr_mut::<EM>() };
if is_crash { if is_crash {
log::error!("Child crashed!"); log::error!("Child crashed!");
@ -432,7 +453,7 @@ pub mod windows_exception_handler {
if is_crash { if is_crash {
log::warn!("Running observers and exiting!"); log::warn!("Running observers and exiting!");
// // I want to disable the hooks before doing anything, especially before taking a stack dump // // I want to disable the hooks before doing anything, especially before taking a stack dump
let input = data.take_current_input::<I>(); // log::set_max_level(log::LevelFilter::Trace); let input = unsafe { data.take_current_input::<I>() };
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, I, OF, S, Z>(
executor, executor,
state, state,
@ -459,7 +480,9 @@ pub mod windows_exception_handler {
if is_crash { if is_crash {
log::info!("Exiting!"); log::info!("Exiting!");
ExitProcess(1); unsafe {
ExitProcess(1);
}
} }
// log::info!("Not Exiting!"); // log::info!("Not Exiting!");
} }

View File

@ -3,11 +3,11 @@ use core::{
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
marker::PhantomData, marker::PhantomData,
ptr::{self, null, write_volatile}, ptr::{self, null, write_volatile},
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
time::Duration, time::Duration,
}; };
use libafl_bolts::tuples::{tuple_list, Merge, RefIndexable}; use libafl_bolts::tuples::{Merge, RefIndexable, tuple_list};
#[cfg(windows)] #[cfg(windows)]
use windows::Win32::System::Threading::SetThreadStackGuarantee; use windows::Win32::System::Threading::SetThreadStackGuarantee;
@ -16,21 +16,21 @@ use crate::executors::hooks::inprocess::HasTimeout;
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
use crate::executors::hooks::inprocess::HasTimeout; use crate::executors::hooks::inprocess::HasTimeout;
use crate::{ use crate::{
Error,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, HasObservers,
hooks::{ hooks::{
inprocess::{InProcessHooks, GLOBAL_STATE},
ExecutorHooksTuple, ExecutorHooksTuple,
inprocess::{GLOBAL_STATE, InProcessHooks},
}, },
inprocess::HasInProcessHooks, inprocess::HasInProcessHooks,
Executor, HasObservers,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
state::{HasCurrentTestcase, HasExecutions, HasSolutions}, state::{HasCurrentTestcase, HasExecutions, HasSolutions},
Error,
}; };
/// The internal state of `GenericInProcessExecutor`. /// The internal state of `GenericInProcessExecutor`.

View File

@ -12,22 +12,22 @@ use core::{
time::Duration, time::Duration,
}; };
use libafl_bolts::tuples::{tuple_list, RefIndexable}; use libafl_bolts::tuples::{RefIndexable, tuple_list};
use crate::{ use crate::{
Error, HasMetadata,
corpus::{Corpus, Testcase}, corpus::{Corpus, Testcase},
events::{Event, EventFirer, EventRestarter}, events::{Event, EventFirer, EventRestarter},
executors::{ executors::{
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
inprocess::inner::GenericInProcessExecutorInner,
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
hooks::{ExecutorHooksTuple, inprocess::InProcessHooks},
inprocess::inner::GenericInProcessExecutorInner,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions}, state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
Error, HasMetadata,
}; };
/// The inner structure of `InProcessExecutor`. /// The inner structure of `InProcessExecutor`.
@ -271,7 +271,6 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF>,
{ {
@ -440,6 +439,7 @@ mod tests {
use libafl_bolts::{rands::XkcdRand, tuples::tuple_list}; use libafl_bolts::{rands::XkcdRand, tuples::tuple_list};
use crate::{ use crate::{
StdFuzzer,
corpus::InMemoryCorpus, corpus::InMemoryCorpus,
events::NopEventManager, events::NopEventManager,
executors::{Executor, ExitKind, InProcessExecutor}, executors::{Executor, ExitKind, InProcessExecutor},
@ -447,7 +447,6 @@ mod tests {
inputs::NopInput, inputs::NopInput,
schedulers::RandScheduler, schedulers::RandScheduler,
state::{NopState, StdState}, state::{NopState, StdState},
StdFuzzer,
}; };
#[test] #[test]

View File

@ -8,21 +8,21 @@ use core::{
time::Duration, time::Duration,
}; };
use libafl_bolts::tuples::{tuple_list, RefIndexable}; use libafl_bolts::tuples::{RefIndexable, tuple_list};
use crate::{ use crate::{
Error,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
inprocess::{GenericInProcessExecutorInner, HasInProcessHooks},
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
hooks::{ExecutorHooksTuple, inprocess::InProcessHooks},
inprocess::{GenericInProcessExecutorInner, HasInProcessHooks},
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::HasObjective,
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
state::{HasCurrentTestcase, HasExecutions, HasSolutions}, state::{HasCurrentTestcase, HasExecutions, HasSolutions},
Error,
}; };
/// The process executor simply calls a target function, as mutable reference to a closure /// The process executor simply calls a target function, as mutable reference to a closure

View File

@ -3,32 +3,32 @@ use core::{
fmt::{self, Debug, Formatter}, fmt::{self, Debug, Formatter},
marker::PhantomData, marker::PhantomData,
ptr::{self, null_mut, write_volatile}, ptr::{self, null_mut, write_volatile},
sync::atomic::{compiler_fence, Ordering}, sync::atomic::{Ordering, compiler_fence},
time::Duration, time::Duration,
}; };
use libafl_bolts::{ use libafl_bolts::{
os::unix_signals::Signal, os::unix_signals::Signal,
shmem::ShMemProvider, shmem::ShMemProvider,
tuples::{tuple_list, Merge, RefIndexable}, tuples::{Merge, RefIndexable, tuple_list},
}; };
use nix::{ use nix::{
sys::wait::{waitpid, WaitStatus}, sys::wait::{WaitStatus, waitpid},
unistd::Pid, unistd::Pid,
}; };
#[cfg(all(unix, not(target_os = "linux")))] #[cfg(all(unix, not(target_os = "linux")))]
use crate::executors::hooks::timer::{setitimer, Itimerval, Timeval, ITIMER_REAL}; use crate::executors::hooks::timer::{ITIMER_REAL, Itimerval, Timeval, setitimer};
use crate::{ use crate::{
Error,
executors::{ executors::{
hooks::{
inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA},
ExecutorHooksTuple,
},
ExitKind, HasObservers, ExitKind, HasObservers,
hooks::{
ExecutorHooksTuple,
inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InChildProcessHooks},
},
}, },
observers::ObserversTuple, observers::ObserversTuple,
Error,
}; };
/// Inner state of GenericInProcessExecutor-like structures. /// Inner state of GenericInProcessExecutor-like structures.
@ -117,32 +117,34 @@ where
mgr: &mut EM, mgr: &mut EM,
input: &I, input: &I,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.shmem_provider.post_fork(true)?; unsafe {
self.shmem_provider.post_fork(true)?;
self.enter_target(fuzzer, state, mgr, input); self.enter_target(fuzzer, state, mgr, input);
self.hooks.pre_exec_all(state, input); self.hooks.pre_exec_all(state, input);
self.observers self.observers
.pre_exec_child_all(state, input) .pre_exec_child_all(state, input)
.expect("Failed to run post_exec on observers"); .expect("Failed to run post_exec on observers");
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
{ {
let mut timerid: libc::timer_t = null_mut(); let mut timerid: libc::timer_t = null_mut();
// creates a new per-process interval timer // creates a new per-process interval timer
// we can't do this from the parent, timerid is unique to each process. // we can't do this from the parent, timerid is unique to each process.
libc::timer_create(libc::CLOCK_MONOTONIC, null_mut(), &raw mut timerid); libc::timer_create(libc::CLOCK_MONOTONIC, null_mut(), &raw mut timerid);
// log::info!("Set timer! {:#?} {timerid:#?}", self.itimerspec); // log::info!("Set timer! {:#?} {timerid:#?}", self.itimerspec);
let _: i32 = libc::timer_settime(timerid, 0, &raw mut self.itimerspec, null_mut()); let _: i32 = libc::timer_settime(timerid, 0, &raw mut self.itimerspec, null_mut());
}
#[cfg(not(target_os = "linux"))]
{
setitimer(ITIMER_REAL, &mut self.itimerval, null_mut());
}
// log::trace!("{v:#?} {}", nix::errno::errno());
Ok(())
} }
#[cfg(not(target_os = "linux"))]
{
setitimer(ITIMER_REAL, &mut self.itimerval, null_mut());
}
// log::trace!("{v:#?} {}", nix::errno::errno());
Ok(())
} }
pub(super) unsafe fn post_run_target_child( pub(super) unsafe fn post_run_target_child(
@ -152,14 +154,16 @@ where
mgr: &mut EM, mgr: &mut EM,
input: &I, input: &I,
) { ) {
self.observers unsafe {
.post_exec_child_all(state, input, &ExitKind::Ok) self.observers
.expect("Failed to run post_exec on observers"); .post_exec_child_all(state, input, &ExitKind::Ok)
.expect("Failed to run post_exec on observers");
self.hooks.post_exec_all(state, input); self.hooks.post_exec_all(state, input);
self.leave_target(fuzzer, state, mgr, input); self.leave_target(fuzzer, state, mgr, input);
libc::_exit(0); libc::_exit(0);
}
} }
pub(super) fn parent(&mut self, child: Pid) -> Result<ExitKind, Error> { pub(super) fn parent(&mut self, child: Pid) -> Result<ExitKind, Error> {

View File

@ -5,22 +5,22 @@ use core::{
}; };
use libafl_bolts::{ use libafl_bolts::{
os::unix_signals::{ucontext_t, Signal}, os::unix_signals::{Signal, ucontext_t},
shmem::ShMemProvider, shmem::ShMemProvider,
tuples::{tuple_list, RefIndexable}, tuples::{RefIndexable, tuple_list},
}; };
use libc::siginfo_t; use libc::siginfo_t;
use nix::unistd::{fork, ForkResult}; use nix::unistd::{ForkResult, fork};
use super::hooks::ExecutorHooksTuple; use super::hooks::ExecutorHooksTuple;
use crate::{ use crate::{
Error,
executors::{ executors::{
hooks::inprocess_fork::InProcessForkExecutorGlobalData, Executor, ExitKind, HasObservers, hooks::inprocess_fork::InProcessForkExecutorGlobalData,
inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers, inprocess_fork::inner::GenericInProcessForkExecutorInner,
}, },
observers::ObserversTuple, observers::ObserversTuple,
state::HasExecutions, state::HasExecutions,
Error,
}; };
/// The signature of the crash handler function /// The signature of the crash handler function
@ -206,13 +206,13 @@ pub mod child_signal_handlers {
use alloc::boxed::Box; use alloc::boxed::Box;
use std::panic; use std::panic;
use libafl_bolts::os::unix_signals::{ucontext_t, Signal}; use libafl_bolts::os::unix_signals::{Signal, ucontext_t};
use libc::siginfo_t; use libc::siginfo_t;
use crate::{ use crate::{
executors::{ executors::{
hooks::inprocess_fork::{InProcessForkExecutorGlobalData, FORK_EXECUTOR_GLOBAL_DATA},
ExitKind, HasObservers, ExitKind, HasObservers,
hooks::inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InProcessForkExecutorGlobalData},
}, },
observers::ObserversTuple, observers::ObserversTuple,
}; };
@ -259,17 +259,19 @@ pub mod child_signal_handlers {
E: HasObservers, E: HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
{ {
if data.is_valid() { unsafe {
let executor = data.executor_mut::<E>(); if data.is_valid() {
let mut observers = executor.observers_mut(); let executor = data.executor_mut::<E>();
let state = data.state_mut::<S>(); let mut observers = executor.observers_mut();
let input = data.take_current_input::<I>(); let state = data.state_mut::<S>();
observers let input = data.take_current_input::<I>();
.post_exec_child_all(state, input, &ExitKind::Crash) observers
.expect("Failed to run post_exec on observers"); .post_exec_child_all(state, input, &ExitKind::Crash)
} .expect("Failed to run post_exec on observers");
}
libc::_exit(128 + (_signal as i32)); libc::_exit(128 + (_signal as i32));
}
} }
#[cfg(unix)] #[cfg(unix)]
@ -283,16 +285,18 @@ pub mod child_signal_handlers {
E: HasObservers, E: HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
{ {
if data.is_valid() { unsafe {
let executor = data.executor_mut::<E>(); if data.is_valid() {
let mut observers = executor.observers_mut(); let executor = data.executor_mut::<E>();
let state = data.state_mut::<S>(); let mut observers = executor.observers_mut();
let input = data.take_current_input::<I>(); let state = data.state_mut::<S>();
observers let input = data.take_current_input::<I>();
.post_exec_child_all(state, input, &ExitKind::Timeout) observers
.expect("Failed to run post_exec on observers"); .post_exec_child_all(state, input, &ExitKind::Timeout)
.expect("Failed to run post_exec on observers");
}
libc::_exit(128 + (_signal as i32));
} }
libc::_exit(128 + (_signal as i32));
} }
} }
@ -303,7 +307,7 @@ mod tests {
use serial_test::serial; use serial_test::serial;
use crate::{ use crate::{
executors::{inprocess_fork::GenericInProcessForkExecutorInner, Executor, ExitKind}, executors::{Executor, ExitKind, inprocess_fork::GenericInProcessForkExecutorInner},
inputs::NopInput, inputs::NopInput,
}; };

View File

@ -9,18 +9,18 @@ use core::{
use libafl_bolts::{ use libafl_bolts::{
shmem::ShMemProvider, shmem::ShMemProvider,
tuples::{tuple_list, RefIndexable}, tuples::{RefIndexable, tuple_list},
}; };
use nix::unistd::{fork, ForkResult}; use nix::unistd::{ForkResult, fork};
use crate::{ use crate::{
Error,
executors::{ executors::{
hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor, Executor, ExitKind, HasObservers, hooks::ExecutorHooksTuple,
ExitKind, HasObservers, inprocess_fork::GenericInProcessForkExecutorInner,
}, },
observers::ObserversTuple, observers::ObserversTuple,
state::HasExecutions, state::HasExecutions,
Error,
}; };
/// The `StatefulInProcessForkExecutor` with no user hooks /// The `StatefulInProcessForkExecutor` with no user hooks

View File

@ -10,9 +10,9 @@ use libafl_bolts::tuples::RefIndexable;
use super::HasTimeout; use super::HasTimeout;
use crate::{ use crate::{
Error,
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
observers::ObserversTuple, observers::ObserversTuple,
Error,
}; };
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers /// A [`ShadowExecutor`] wraps an executor and a set of shadow observers

View File

@ -5,9 +5,9 @@ use core::{fmt::Debug, marker::PhantomData};
use libafl_bolts::tuples::RefIndexable; use libafl_bolts::tuples::RefIndexable;
use crate::{ use crate::{
Error,
executors::{Executor, ExitKind, HasObservers}, executors::{Executor, ExitKind, HasObservers},
observers::ObserversTuple, observers::ObserversTuple,
Error,
}; };
/// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`]. /// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`].

View File

@ -3,14 +3,14 @@
use alloc::borrow::Cow; use alloc::borrow::Cow;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, MatchNameRef},
Error, Named, Error, Named,
tuples::{Handle, MatchNameRef},
}; };
use crate::{ use crate::{
HasNamedMetadata,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
observers::{ObserversTuple, ValueObserver}, observers::{ObserversTuple, ValueObserver},
HasNamedMetadata,
}; };
/// This feedback returns `true` or `false` as the `is_interesting` value. /// This feedback returns `true` or `false` as the `is_interesting` value.

View File

@ -2,15 +2,15 @@
use std::{borrow::Cow, cell::RefCell, fmt::Debug, rc::Rc}; use std::{borrow::Cow, cell::RefCell, fmt::Debug, rc::Rc};
use libafl_bolts::{Error, Named}; use libafl_bolts::{Error, Named};
use serde::{de::DeserializeOwned, Serialize}; use serde::{Serialize, de::DeserializeOwned};
use crate::{ use crate::{
HasMetadata,
corpus::Testcase, corpus::Testcase,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
stages::verify_timeouts::TimeoutsToVerify, stages::verify_timeouts::TimeoutsToVerify,
state::HasCorpus, state::HasCorpus,
HasMetadata,
}; };
/// A Feedback that captures all timeouts and stores them in State for re-evaluation later. /// A Feedback that captures all timeouts and stores them in State for re-evaluation later.

View File

@ -8,15 +8,15 @@ use alloc::borrow::Cow;
use core::fmt::Debug; use core::fmt::Debug;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
use crate::{ use crate::{
Error, HasMetadata,
corpus::Testcase, corpus::Testcase,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
observers::concolic::ConcolicObserver, observers::concolic::ConcolicObserver,
Error, HasMetadata,
}; };
/// The concolic feedback. It is used to attach concolic tracing metadata to the testcase. /// The concolic feedback. It is used to attach concolic tracing metadata to the testcase.

View File

@ -5,9 +5,9 @@ use libafl_bolts::Named;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error,
corpus::Testcase, corpus::Testcase,
feedbacks::{Feedback, FeedbackFactory, StateInitializer}, feedbacks::{Feedback, FeedbackFactory, StateInitializer},
Error,
}; };
/// Type which can generate a custom filename for a given input/state pair /// Type which can generate a custom filename for a given input/state pair

View File

@ -4,17 +4,17 @@ use alloc::borrow::Cow;
use core::fmt::{self, Debug, Formatter}; use core::fmt::{self, Debug, Formatter};
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err; use crate::feedbacks::premature_last_result_err;
use crate::{ use crate::{
Error,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, FeedbackFactory, StateInitializer}, feedbacks::{Feedback, FeedbackFactory, StateInitializer},
Error,
}; };
/// The result of a differential test between two observers. /// The result of a differential test between two observers.
@ -179,12 +179,12 @@ where
mod tests { mod tests {
use alloc::borrow::Cow; use alloc::borrow::Cow;
use libafl_bolts::{tuples::tuple_list, Named}; use libafl_bolts::{Named, tuples::tuple_list};
use crate::{ use crate::{
events::NopEventManager, events::NopEventManager,
executors::ExitKind, executors::ExitKind,
feedbacks::{differential::DiffResult, DiffFeedback, Feedback}, feedbacks::{DiffFeedback, Feedback, differential::DiffResult},
inputs::BytesInput, inputs::BytesInput,
observers::Observer, observers::Observer,
state::NopState, state::NopState,

View File

@ -3,16 +3,16 @@ use core::{fmt::Debug, hash::Hash};
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
Error, HasRefCnt, Named, Error, HasRefCnt, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{Deserialize, Serialize, de::DeserializeOwned};
use crate::{ use crate::{
HasNamedMetadata,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
observers::ListObserver, observers::ListObserver,
HasNamedMetadata,
}; };
/// The metadata to remember past observed value /// The metadata to remember past observed value

View File

@ -12,22 +12,22 @@ use core::{
#[rustversion::nightly] #[rustversion::nightly]
use libafl_bolts::AsSlice; use libafl_bolts::AsSlice;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
AsIter, HasRefCnt, Named, AsIter, HasRefCnt, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
use num_traits::PrimInt; use num_traits::PrimInt;
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{Deserialize, Serialize, de::DeserializeOwned};
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err; use crate::feedbacks::premature_last_result_err;
use crate::{ use crate::{
Error, HasMetadata, HasNamedMetadata,
corpus::Testcase, corpus::Testcase,
events::{Event, EventFirer}, events::{Event, EventFirer},
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle, StateInitializer}, feedbacks::{Feedback, HasObserverHandle, StateInitializer},
monitors::stats::{AggregatorOps, UserStats, UserStatsValue}, monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
observers::{CanTrack, MapObserver}, observers::{CanTrack, MapObserver},
Error, HasMetadata, HasNamedMetadata,
}; };
/// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from (`HitcountsMapObserver`)[`crate::observers::HitcountsMapObserver`]. /// A [`MapFeedback`] that implements the AFL algorithm using an [`OrReducer`] combining the bits for the history map and the bit from (`HitcountsMapObserver`)[`crate::observers::HitcountsMapObserver`].
@ -103,11 +103,7 @@ where
{ {
#[inline] #[inline]
fn reduce(first: T, second: T) -> T { fn reduce(first: T, second: T) -> T {
if first > second { if first > second { first } else { second }
first
} else {
second
}
} }
} }
@ -121,11 +117,7 @@ where
{ {
#[inline] #[inline]
fn reduce(first: T, second: T) -> T { fn reduce(first: T, second: T) -> T {
if first < second { if first < second { first } else { second }
first
} else {
second
}
} }
} }

View File

@ -12,8 +12,8 @@ use core::{fmt::Debug, marker::PhantomData};
pub use concolic::ConcolicFeedback; pub use concolic::ConcolicFeedback;
pub use differential::DiffFeedback; pub use differential::DiffFeedback;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
pub use list::*; pub use list::*;
pub use map::*; pub use map::*;
@ -25,7 +25,7 @@ pub use new_hash_feedback::NewHashFeedback;
pub use new_hash_feedback::NewHashFeedbackMetadata; pub use new_hash_feedback::NewHashFeedbackMetadata;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{corpus::Testcase, executors::ExitKind, observers::TimeObserver, Error}; use crate::{Error, corpus::Testcase, executors::ExitKind, observers::TimeObserver};
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod capture_feedback; pub mod capture_feedback;
@ -1016,11 +1016,7 @@ impl ConstFeedback {
impl From<bool> for ConstFeedback { impl From<bool> for ConstFeedback {
fn from(val: bool) -> Self { fn from(val: bool) -> Self {
if val { if val { Self::True } else { Self::False }
Self::True
} else {
Self::False
}
} }
} }

View File

@ -7,6 +7,7 @@ use libafl_bolts::Named;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error, HasMetadata,
common::nautilus::grammartec::{chunkstore::ChunkStore, context::Context}, common::nautilus::grammartec::{chunkstore::ChunkStore, context::Context},
corpus::{Corpus, Testcase}, corpus::{Corpus, Testcase},
executors::ExitKind, executors::ExitKind,
@ -14,7 +15,6 @@ use crate::{
generators::NautilusContext, generators::NautilusContext,
inputs::NautilusInput, inputs::NautilusInput,
state::HasCorpus, state::HasCorpus,
Error, HasMetadata,
}; };
/// Metadata for Nautilus grammar mutator chunks /// Metadata for Nautilus grammar mutator chunks

View File

@ -5,18 +5,18 @@ use std::fmt::Debug;
use hashbrown::HashSet; use hashbrown::HashSet;
use libafl_bolts::{ use libafl_bolts::{
tuples::{Handle, Handled, MatchName, MatchNameRef},
Named, Named,
tuples::{Handle, Handled, MatchName, MatchNameRef},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err; use crate::feedbacks::premature_last_result_err;
use crate::{ use crate::{
Error, HasNamedMetadata,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, HasObserverHandle, StateInitializer}, feedbacks::{Feedback, HasObserverHandle, StateInitializer},
observers::ObserverWithHashField, observers::ObserverWithHashField,
Error, HasNamedMetadata,
}; };
/// The prefix of the metadata names /// The prefix of the metadata names

View File

@ -3,17 +3,16 @@
use alloc::{borrow::Cow, string::String}; use alloc::{borrow::Cow, string::String};
use libafl_bolts::{ use libafl_bolts::{
impl_serdeany, Named, impl_serdeany,
tuples::{Handle, Handled, MatchName, MatchNameRef}, tuples::{Handle, Handled, MatchName, MatchNameRef},
Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error, HasMetadata,
corpus::Testcase, corpus::Testcase,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
observers::{StdErrObserver, StdOutObserver}, observers::{StdErrObserver, StdOutObserver},
Error, HasMetadata,
}; };
/// Metadata for [`StdOutToMetadataFeedback`]. /// Metadata for [`StdOutToMetadataFeedback`].

View File

@ -3,15 +3,15 @@
use alloc::borrow::Cow; use alloc::borrow::Cow;
use libafl_bolts::{impl_serdeany, Error, Named}; use libafl_bolts::{Error, Named, impl_serdeany};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
use crate::feedbacks::premature_last_result_err; use crate::feedbacks::premature_last_result_err;
use crate::{ use crate::{
HasMetadata,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
HasMetadata,
}; };
/// Constant name of the [`TransferringMetadata`]. /// Constant name of the [`TransferringMetadata`].

View File

@ -5,17 +5,16 @@ use core::hash::Hash;
use fastbloom::BloomFilter; use fastbloom::BloomFilter;
use libafl_bolts::{ use libafl_bolts::{
impl_serdeany, Error, Named, impl_serdeany,
tuples::{Handle, MatchNameRef}, tuples::{Handle, MatchNameRef},
Error, Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
HasNamedMetadata,
executors::ExitKind, executors::ExitKind,
feedbacks::{Feedback, StateInitializer}, feedbacks::{Feedback, StateInitializer},
observers::{ObserversTuple, ValueObserver}, observers::{ObserversTuple, ValueObserver},
HasNamedMetadata,
}; };
impl_serdeany!(ValueBloomFeedbackMetadata); impl_serdeany!(ValueBloomFeedbackMetadata);

View File

@ -8,11 +8,12 @@ use std::hash::Hash;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use fastbloom::BloomFilter; use fastbloom::BloomFilter;
use libafl_bolts::{current_time, tuples::MatchName}; use libafl_bolts::{current_time, tuples::MatchName};
use serde::{de::DeserializeOwned, Serialize}; use serde::{Serialize, de::DeserializeOwned};
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::monitors::stats::PerfFeature; use crate::monitors::stats::PerfFeature;
use crate::{ use crate::{
Error, HasMetadata,
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase}, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase},
events::{ events::{
CanSerializeObserver, Event, EventConfig, EventFirer, EventReceiver, ProgressReporter, CanSerializeObserver, Event, EventConfig, EventFirer, EventReceiver, ProgressReporter,
@ -30,7 +31,6 @@ use crate::{
HasCorpus, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasCorpus, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported,
HasLastFoundTime, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable, HasLastFoundTime, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
}, },
Error, HasMetadata,
}; };
/// Send a monitor update all 15 (or more) seconds /// Send a monitor update all 15 (or more) seconds
@ -1129,24 +1129,32 @@ mod tests {
InProcessExecutor::new(&mut harness, (), &mut fuzzer, &mut state, &mut manager) InProcessExecutor::new(&mut harness, (), &mut fuzzer, &mut state, &mut manager)
.unwrap(); .unwrap();
let input = BytesInput::new(vec![1, 2, 3]); let input = BytesInput::new(vec![1, 2, 3]);
assert!(fuzzer assert!(
.evaluate_input(&mut state, &mut executor, &mut manager, &input) fuzzer
.is_ok()); .evaluate_input(&mut state, &mut executor, &mut manager, &input)
.is_ok()
);
assert_eq!(1, *execution_count.borrow()); // evaluate_input does not add it to the filter assert_eq!(1, *execution_count.borrow()); // evaluate_input does not add it to the filter
assert!(fuzzer assert!(
.evaluate_filtered(&mut state, &mut executor, &mut manager, &input) fuzzer
.is_ok()); .evaluate_filtered(&mut state, &mut executor, &mut manager, &input)
.is_ok()
);
assert_eq!(2, *execution_count.borrow()); // at to the filter assert_eq!(2, *execution_count.borrow()); // at to the filter
assert!(fuzzer assert!(
.evaluate_filtered(&mut state, &mut executor, &mut manager, &input) fuzzer
.is_ok()); .evaluate_filtered(&mut state, &mut executor, &mut manager, &input)
.is_ok()
);
assert_eq!(2, *execution_count.borrow()); // the harness is not called assert_eq!(2, *execution_count.borrow()); // the harness is not called
assert!(fuzzer assert!(
.evaluate_input(&mut state, &mut executor, &mut manager, &input) fuzzer
.is_ok()); .evaluate_input(&mut state, &mut executor, &mut manager, &input)
.is_ok()
);
assert_eq!(3, *execution_count.borrow()); // evaluate_input ignores filters assert_eq!(3, *execution_count.borrow()); // evaluate_input ignores filters
} }
} }

View File

@ -6,10 +6,10 @@ use libafl_bolts::rands::Rand;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error,
generators::Generator, generators::Generator,
inputs::{GramatronInput, Terminal}, inputs::{GramatronInput, Terminal},
state::HasRand, state::HasRand,
Error,
}; };
/// A trigger /// A trigger

View File

@ -5,7 +5,7 @@ use core::{marker::PhantomData, num::NonZeroUsize};
use libafl_bolts::rands::Rand; use libafl_bolts::rands::Rand;
use crate::{inputs::bytes::BytesInput, nonzero, state::HasRand, Error}; use crate::{Error, inputs::bytes::BytesInput, nonzero, state::HasRand};
pub mod gramatron; pub mod gramatron;
use core::cmp::max; use core::cmp::max;
@ -44,16 +44,16 @@ where
/// An [`Iterator`] built from a [`Generator`]. /// An [`Iterator`] built from a [`Generator`].
#[derive(Debug)] #[derive(Debug)]
pub struct GeneratorIter<'a, I, S, G> { pub struct GeneratorIter<'a, I, S, G> {
gen: G, generator: G,
state: &'a mut S, state: &'a mut S,
phantom: PhantomData<I>, phantom: PhantomData<I>,
} }
impl<'a, I, S, G> GeneratorIter<'a, I, S, G> { impl<'a, I, S, G> GeneratorIter<'a, I, S, G> {
/// Create a new [`GeneratorIter`] /// Create a new [`GeneratorIter`]
pub fn new(gen: G, state: &'a mut S) -> Self { pub fn new(generator: G, state: &'a mut S) -> Self {
Self { Self {
gen, generator,
state, state,
phantom: PhantomData, phantom: PhantomData,
} }
@ -67,7 +67,7 @@ where
type Item = I; type Item = I;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.gen.generate(self.state).ok() self.generator.generate(self.state).ok()
} }
} }

View File

@ -10,9 +10,8 @@ use libafl_bolts::rands::Rand;
pub use crate::common::nautilus::grammartec::newtypes::NTermId; pub use crate::common::nautilus::grammartec::newtypes::NTermId;
use crate::{ use crate::{
common::nautilus::grammartec::context::Context, generators::Generator, Error, common::nautilus::grammartec::context::Context, generators::Generator,
inputs::nautilus::NautilusInput, nautilus::grammartec::python_grammar_loader, state::HasRand, inputs::nautilus::NautilusInput, nautilus::grammartec::python_grammar_loader, state::HasRand,
Error,
}; };
/// The nautilus context for a generator /// The nautilus context for a generator

View File

@ -8,7 +8,7 @@ use alloc::{
}; };
use core::cell::RefCell; use core::cell::RefCell;
use libafl_bolts::{ownedref::OwnedSlice, HasLen}; use libafl_bolts::{HasLen, ownedref::OwnedSlice};
use super::ValueInput; use super::ValueInput;
use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator}; use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator};

View File

@ -7,8 +7,8 @@ use core::{
}; };
use libafl_bolts::{ use libafl_bolts::{
subrange::{end_index, start_index, sub_range},
HasLen, HasLen,
subrange::{end_index, start_index, sub_range},
}; };
use crate::inputs::{HasMutatorBytes, ResizableMutator}; use crate::inputs::{HasMutatorBytes, ResizableMutator};
@ -24,7 +24,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator};
/// # use alloc::vec::Vec; /// # use alloc::vec::Vec;
/// # /// #
/// # #[cfg(not(feature = "std"))] /// # #[cfg(not(feature = "std"))]
/// # #[no_mangle] /// # #[unsafe(no_mangle)]
/// # pub extern "C" fn external_current_millis() -> u64 { 0 } /// # pub extern "C" fn external_current_millis() -> u64 { 0 }
/// ///
/// let mut bytes_input = BytesInput::new(vec![1, 2, 3]); /// let mut bytes_input = BytesInput::new(vec![1, 2, 3]);
@ -49,7 +49,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator};
/// # use alloc::vec::Vec; /// # use alloc::vec::Vec;
/// # /// #
/// # #[cfg(not(feature = "std"))] /// # #[cfg(not(feature = "std"))]
/// # #[no_mangle] /// # #[unsafe(no_mangle)]
/// # pub extern "C" fn external_current_millis() -> u64 { 0 } /// # pub extern "C" fn external_current_millis() -> u64 { 0 }
/// ///
/// let mut bytes_input = BytesInput::new(vec![1, 2, 3, 4, 5]); /// let mut bytes_input = BytesInput::new(vec![1, 2, 3, 4, 5]);
@ -215,7 +215,7 @@ mod tests {
use crate::{ use crate::{
inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator}, inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator},
mutators::{havoc_mutations_no_crossover, MutatorsTuple}, mutators::{MutatorsTuple, havoc_mutations_no_crossover},
state::NopState, state::NopState,
}; };

View File

@ -6,10 +6,10 @@ use libafl_bolts::impl_serdeany;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error, HasMetadata,
corpus::Testcase, corpus::Testcase,
inputs::BytesInput, inputs::BytesInput,
stages::mutational::{MutatedTransform, MutatedTransformPost}, stages::mutational::{MutatedTransform, MutatedTransformPost},
Error, HasMetadata,
}; };
/// An item of the generalized input /// An item of the generalized input

View File

@ -13,9 +13,9 @@ use core::num::NonZero;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use libafl_bolts::{ use libafl_bolts::{
Error, Named,
rands::Rand as _, rands::Rand as _,
tuples::{Map, MappingFunctor}, tuples::{Map, MappingFunctor},
Error, Named,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -326,7 +326,7 @@ mod tests {
use super::ListInput; use super::ListInput;
use crate::{ use crate::{
inputs::ValueInput, inputs::ValueInput,
mutators::{numeric::IncMutator, MutationResult, MutatorsTuple as _}, mutators::{MutationResult, MutatorsTuple as _, numeric::IncMutator},
state::NopState, state::NopState,
}; };

View File

@ -48,10 +48,9 @@ use std::{fs::File, io::Read, path::Path};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use libafl_bolts::fs::write_file_atomic; use libafl_bolts::fs::write_file_atomic;
use libafl_bolts::{ use libafl_bolts::{
generic_hash_std, Error, HasLen, generic_hash_std,
ownedref::{OwnedMutSlice, OwnedSlice}, ownedref::{OwnedMutSlice, OwnedSlice},
subrange::{SubRangeMutSlice, SubRangeSlice}, subrange::{SubRangeMutSlice, SubRangeSlice},
Error, HasLen,
}; };
#[cfg(feature = "nautilus")] #[cfg(feature = "nautilus")]
pub use nautilus::*; pub use nautilus::*;

View File

@ -3,7 +3,7 @@
use alloc::{fmt::Debug, string::String, vec::Vec}; use alloc::{fmt::Debug, string::String, vec::Vec};
use core::hash::Hash; use core::hash::Hash;
use serde::{de::DeserializeOwned, Serialize}; use serde::{Serialize, de::DeserializeOwned};
use crate::{ use crate::{
corpus::CorpusId, corpus::CorpusId,

View File

@ -3,11 +3,12 @@ use alloc::{rc::Rc, vec::Vec};
use core::cell::RefCell; use core::cell::RefCell;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use libafl_bolts::{ownedref::OwnedSlice, HasLen}; use libafl_bolts::{HasLen, ownedref::OwnedSlice};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::TargetBytesConverter; use super::TargetBytesConverter;
use crate::{ use crate::{
Error,
common::nautilus::grammartec::{ common::nautilus::grammartec::{
newtypes::NodeId, newtypes::NodeId,
rule::RuleIdOrCustom, rule::RuleIdOrCustom,
@ -15,7 +16,6 @@ use crate::{
}, },
generators::nautilus::NautilusContext, generators::nautilus::NautilusContext,
inputs::{BytesInput, Input, InputConverter}, inputs::{BytesInput, Input, InputConverter},
Error,
}; };
/// An [`Input`] implementation for `Nautilus` grammar. /// An [`Input`] implementation for `Nautilus` grammar.

View File

@ -8,7 +8,7 @@ use libafl_bolts::rands::Rand;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use { use {
libafl_bolts::{fs::write_file_atomic, Error}, libafl_bolts::{Error, fs::write_file_atomic},
std::{fs::File, io::Read, path::Path}, std::{fs::File, io::Read, path::Path},
}; };

View File

@ -81,7 +81,7 @@ pub mod stages;
pub mod state; pub mod state;
pub use fuzzer::*; pub use fuzzer::*;
pub use libafl_bolts::{nonzero, Error}; pub use libafl_bolts::{Error, nonzero};
/// The purpose of this module is to alleviate imports of many components by adding a glob import. /// The purpose of this module is to alleviate imports of many components by adding a glob import.
#[cfg(feature = "prelude")] #[cfg(feature = "prelude")]
@ -96,7 +96,7 @@ pub mod prelude {
#[cfg(all(any(doctest, test), not(feature = "std")))] #[cfg(all(any(doctest, test), not(feature = "std")))]
/// Provide custom time in `no_std` tests. /// Provide custom time in `no_std` tests.
#[no_mangle] #[unsafe(no_mangle)]
pub unsafe extern "C" fn external_current_millis() -> u64 { pub unsafe extern "C" fn external_current_millis() -> u64 {
// TODO: use "real" time here // TODO: use "real" time here
1000 1000
@ -116,6 +116,7 @@ mod tests {
#[cfg(miri)] #[cfg(miri)]
use crate::stages::ExecutionCountRestartHelperMetadata; use crate::stages::ExecutionCountRestartHelperMetadata;
use crate::{ use crate::{
StdFuzzer,
corpus::{Corpus, InMemoryCorpus, Testcase}, corpus::{Corpus, InMemoryCorpus, Testcase},
events::NopEventManager, events::NopEventManager,
executors::{ExitKind, InProcessExecutor}, executors::{ExitKind, InProcessExecutor},
@ -123,11 +124,10 @@ mod tests {
fuzzer::Fuzzer, fuzzer::Fuzzer,
inputs::BytesInput, inputs::BytesInput,
monitors::SimpleMonitor, monitors::SimpleMonitor,
mutators::{mutations::BitFlipMutator, StdScheduledMutator}, mutators::{StdScheduledMutator, mutations::BitFlipMutator},
schedulers::RandScheduler, schedulers::RandScheduler,
stages::StdMutationalStage, stages::StdMutationalStage,
state::{HasCorpus, StdState}, state::{HasCorpus, StdState},
StdFuzzer,
}; };
#[test] #[test]

View File

@ -8,10 +8,10 @@ use std::{
path::PathBuf, path::PathBuf,
}; };
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{ClientId, current_time};
use serde_json::json; use serde_json::json;
use crate::monitors::{stats::ClientStatsManager, Monitor}; use crate::monitors::{Monitor, stats::ClientStatsManager};
/// Wrap a monitor and log the current state of the monitor into a Toml file. /// Wrap a monitor and log the current state of the monitor into a Toml file.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View File

@ -6,10 +6,10 @@ use core::{
}; };
use std::{fs::OpenOptions, io::Write, path::PathBuf}; use std::{fs::OpenOptions, io::Write, path::PathBuf};
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{ClientId, current_time};
use serde_json::json; use serde_json::json;
use crate::monitors::{stats::ClientStatsManager, Monitor}; use crate::monitors::{Monitor, stats::ClientStatsManager};
/// A monitor that logs aggregated stats to a JSON file. /// A monitor that logs aggregated stats to a JSON file.
#[derive(Clone)] #[derive(Clone)]

View File

@ -2,7 +2,7 @@
use libafl_bolts::ClientId; use libafl_bolts::ClientId;
use crate::monitors::{stats::ClientStatsManager, Monitor}; use crate::monitors::{Monitor, stats::ClientStatsManager};
/// The wrapped monitor will keep displaying until the closure evaluates to false /// The wrapped monitor will keep displaying until the closure evaluates to false
#[derive(Debug)] #[derive(Debug)]

View File

@ -297,7 +297,7 @@ mod test {
use libafl_bolts::ClientId; use libafl_bolts::ClientId;
use tuple_list::tuple_list; use tuple_list::tuple_list;
use super::{stats::ClientStatsManager, Monitor, NopMonitor, SimpleMonitor}; use super::{Monitor, NopMonitor, SimpleMonitor, stats::ClientStatsManager};
#[test] #[test]
fn test_monitor_tuple_list() { fn test_monitor_tuple_list() {

View File

@ -6,9 +6,9 @@ use core::{
time::Duration, time::Duration,
}; };
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{ClientId, current_time};
use crate::monitors::{stats::ClientStatsManager, Monitor}; use crate::monitors::{Monitor, stats::ClientStatsManager};
/// Tracking monitor during fuzzing and display both per-client and cumulative info. /// Tracking monitor during fuzzing and display both per-client and cumulative info.
#[derive(Clone)] #[derive(Clone)]

View File

@ -31,16 +31,16 @@ use alloc::{borrow::Cow, fmt::Debug, string::String};
use core::{fmt, fmt::Write, time::Duration}; use core::{fmt, fmt::Write, time::Duration};
use std::{ use std::{
string::ToString, string::ToString,
sync::{atomic::AtomicU64, Arc}, sync::{Arc, atomic::AtomicU64},
thread, thread,
}; };
// using thread in order to start the HTTP server in a separate thread // using thread in order to start the HTTP server in a separate thread
use futures::executor::block_on; use futures::executor::block_on;
use libafl_bolts::{current_time, ClientId}; use libafl_bolts::{ClientId, current_time};
// using the official rust client library for Prometheus: https://github.com/prometheus/client_rust // using the official rust client library for Prometheus: https://github.com/prometheus/client_rust
use prometheus_client::{ use prometheus_client::{
encoding::{text::encode, EncodeLabelSet}, encoding::{EncodeLabelSet, text::encode},
metrics::{family::Family, gauge::Gauge}, metrics::{family::Family, gauge::Gauge},
registry::Registry, registry::Registry,
}; };
@ -48,8 +48,8 @@ use prometheus_client::{
use tide::Request; use tide::Request;
use crate::monitors::{ use crate::monitors::{
stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
Monitor, Monitor,
stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
}; };
/// Prometheus metrics for global and each client. /// Prometheus metrics for global and each client.

View File

@ -6,15 +6,15 @@ use alloc::{borrow::Cow, string::String, vec::Vec};
use core::time::Duration; use core::time::Duration;
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{current_time, format_duration_hms, ClientId}; use libafl_bolts::{ClientId, current_time, format_duration_hms};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use serde_json::Value; use serde_json::Value;
use super::{user_stats::UserStatsValue, ClientStats, EdgeCoverage, ProcessTiming}; use super::{ClientStats, EdgeCoverage, ProcessTiming, user_stats::UserStatsValue};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use super::{ use super::{
user_stats::{AggregatorOps, UserStats},
ItemGeometry, ItemGeometry,
user_stats::{AggregatorOps, UserStats},
}; };
/// Manager of all client's statistics /// Manager of all client's statistics

View File

@ -17,8 +17,8 @@ use cadence::{BufferedUdpMetricSink, Gauged, QueuingMetricSink, StatsdClient};
use libafl_bolts::ClientId; use libafl_bolts::ClientId;
use super::{ use super::{
stats::{manager::GlobalStats, ClientStatsManager, EdgeCoverage, ItemGeometry},
Monitor, Monitor,
stats::{ClientStatsManager, EdgeCoverage, ItemGeometry, manager::GlobalStats},
}; };
const METRIC_PREFIX: &str = "fuzzing"; const METRIC_PREFIX: &str = "fuzzing";

View File

@ -19,21 +19,21 @@ use crossterm::{
cursor::{EnableBlinking, Show}, cursor::{EnableBlinking, Show},
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
}; };
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{current_time, format_duration_hms, ClientId}; use libafl_bolts::{ClientId, current_time, format_duration_hms};
use ratatui::{backend::CrosstermBackend, Terminal}; use ratatui::{Terminal, backend::CrosstermBackend};
use typed_builder::TypedBuilder; use typed_builder::TypedBuilder;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature}; use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature};
use crate::monitors::{ use crate::monitors::{
stats::{
manager::ClientStatsManager, user_stats::UserStats, ClientStats, EdgeCoverage,
ItemGeometry, ProcessTiming,
},
Monitor, Monitor,
stats::{
ClientStats, EdgeCoverage, ItemGeometry, ProcessTiming, manager::ClientStatsManager,
user_stats::UserStats,
},
}; };
#[expect(missing_docs)] #[expect(missing_docs)]
@ -568,7 +568,9 @@ fn run_tui_thread<W: Write + Send + Sync + 'static>(
)?; )?;
terminal.show_cursor()?; terminal.show_cursor()?;
println!("\nPress Control-C to stop the fuzzers, otherwise press Enter to resume the visualization\n"); println!(
"\nPress Control-C to stop the fuzzers, otherwise press Enter to resume the visualization\n"
);
let mut line = String::new(); let mut line = String::new();
io::stdin().lock().read_line(&mut line)?; io::stdin().lock().read_line(&mut line)?;

View File

@ -6,6 +6,7 @@ use std::{
}; };
use ratatui::{ use ratatui::{
Frame,
layout::{Alignment, Constraint, Direction, Layout, Rect}, layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
symbols, symbols,
@ -13,12 +14,11 @@ use ratatui::{
widgets::{ widgets::{
Axis, Block, Borders, Cell, Chart, Dataset, List, ListItem, Paragraph, Row, Table, Tabs, Axis, Block, Borders, Cell, Chart, Dataset, List, ListItem, Paragraph, Row, Table, Tabs,
}, },
Frame,
}; };
use super::{ use super::{
current_time, format_duration_hms, Duration, ItemGeometry, ProcessTiming, String, TimedStats, Duration, ItemGeometry, ProcessTiming, String, TimedStats, TuiContext, current_time,
TuiContext, format_duration_hms,
}; };
#[derive(Default, Debug)] #[derive(Default, Debug)]
@ -368,19 +368,21 @@ impl TuiUi {
//log::trace!("max_x: {}, len: {}", max_x, self.graph_data.len()); //log::trace!("max_x: {}, len: {}", max_x, self.graph_data.len());
let datasets = vec![Dataset::default() let datasets = vec![
//.name("data") Dataset::default()
.marker(if self.enhanced_graphics { //.name("data")
symbols::Marker::Braille .marker(if self.enhanced_graphics {
} else { symbols::Marker::Braille
symbols::Marker::Dot } else {
}) symbols::Marker::Dot
.style( })
Style::default() .style(
.fg(Color::LightYellow) Style::default()
.add_modifier(Modifier::BOLD), .fg(Color::LightYellow)
) .add_modifier(Modifier::BOLD),
.data(&self.graph_data)]; )
.data(&self.graph_data),
];
let chart = Chart::new(datasets) let chart = Chart::new(datasets)
.block( .block(
Block::default() Block::default()

View File

@ -11,15 +11,15 @@ use libafl_bolts::{
}; };
use crate::{ use crate::{
Error,
corpus::Corpus, corpus::Corpus,
inputs::EncodedInput, inputs::EncodedInput,
mutators::{ mutators::{
mutations::{buffer_copy, buffer_self_copy, ARITH_MAX},
MutationResult, Mutator, Named, MutationResult, Mutator, Named,
mutations::{ARITH_MAX, buffer_copy, buffer_self_copy},
}, },
nonzero, random_corpus_id_with_disabled, nonzero, random_corpus_id_with_disabled,
state::{HasCorpus, HasMaxSize, HasRand}, state::{HasCorpus, HasMaxSize, HasRand},
Error,
}; };
/// Set a code in the input as a random value /// Set a code in the input as a random value

View File

@ -6,19 +6,19 @@ use core::{cmp::max, num::NonZero};
use hashbrown::HashMap; use hashbrown::HashMap;
use libafl_bolts::{ use libafl_bolts::{
rands::{choose, Rand},
Named, Named,
rands::{Rand, choose},
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
Error, HasMetadata,
corpus::Corpus, corpus::Corpus,
generators::GramatronGenerator, generators::GramatronGenerator,
inputs::{GramatronInput, Terminal}, inputs::{GramatronInput, Terminal},
mutators::{MutationResult, Mutator}, mutators::{MutationResult, Mutator},
nonzero, random_corpus_id, nonzero, random_corpus_id,
state::{HasCorpus, HasRand}, state::{HasCorpus, HasRand},
Error, HasMetadata,
}; };
const RECUR_THRESHOLD: usize = 5; const RECUR_THRESHOLD: usize = 5;
@ -201,15 +201,18 @@ where
self.states.clear(); self.states.clear();
for i in 0..input.terminals().len() { for i in 0..input.terminals().len() {
let s = input.terminals()[i].state; let s = input.terminals()[i].state;
if let Some(entry) = self.counters.get_mut(&s) { match self.counters.get_mut(&s) {
if entry.0 == 1 { Some(entry) => {
// Keep track only of states with more than one node if entry.0 == 1 {
self.states.push(s); // Keep track only of states with more than one node
self.states.push(s);
}
entry.0 += 1;
entry.2 = max(entry.2, i);
}
_ => {
self.counters.insert(s, (1, i, i));
} }
entry.0 += 1;
entry.2 = max(entry.2, i);
} else {
self.counters.insert(s, (1, i, i));
} }
} }

Some files were not shown because too many files have changed in this diff Show More