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:
parent
3d31adcca1
commit
c7207dceb0
1
.github/workflows/build_and_test.yml
vendored
1
.github/workflows/build_and_test.yml
vendored
@ -223,6 +223,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: taiki-e/install-action@cargo-hack
|
||||
- run: rustup upgrade
|
||||
# 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
|
||||
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -74,6 +74,5 @@ libafl_nyx/packer
|
||||
harness
|
||||
program
|
||||
fuzzer_libpng*
|
||||
forkserver_simple
|
||||
|
||||
*.patch
|
||||
|
@ -5,7 +5,7 @@ version = "0.15.1"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://github.com/AFLplusplus/LibAFL/"
|
||||
keywords = ["fuzzing", "testing", "security", "python"]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
categories = ["development-tools::testing", "emulators", "embedded", "os"]
|
||||
|
||||
[dependencies]
|
||||
|
@ -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:
|
||||
|
||||
```rust,ignore
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn external_current_millis() -> u64 {
|
||||
unsafe { my_real_seconds()*1000 }
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ As you can see from the forkserver example,
|
||||
//Coverage map shared between observer and executor
|
||||
let mut shmem = StdShMemProvider::new().unwrap().new_shmem(MAP_SIZE).unwrap();
|
||||
//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();
|
||||
```
|
||||
|
||||
|
@ -21,7 +21,7 @@ debug = true
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.89"
|
||||
bindgen = "0.70.1"
|
||||
bindgen = "0.71.1"
|
||||
cc = "=1.2.7" # fix me later
|
||||
|
||||
[dependencies]
|
||||
|
@ -40,7 +40,9 @@ pub fn main() {
|
||||
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
//let the forkserver know the shmid
|
||||
unsafe {
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
let shmem_map: &mut [u8; MAP_SIZE] = shmem
|
||||
.as_slice_mut()
|
||||
.try_into()
|
||||
|
@ -97,7 +97,9 @@ pub fn main() {
|
||||
// The coverage map shared between observer and executor
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
// the next line is not needed
|
||||
// unsafe { EDGES_MAP_PTR = shmem_buf.as_mut_ptr() };
|
||||
|
@ -2,7 +2,7 @@
|
||||
name = "forkserver_simple"
|
||||
version = "0.14.1"
|
||||
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
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{
|
||||
env,
|
||||
path::Path,
|
||||
process::{exit, Command},
|
||||
process::{Command, exit},
|
||||
};
|
||||
|
||||
const AFL_URL: &str = "https://github.com/AFLplusplus/AFLplusplus";
|
||||
@ -12,7 +12,9 @@ fn main() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
env::remove_var("DEBUG");
|
||||
}
|
||||
let cwd = env::current_dir().unwrap().to_string_lossy().to_string();
|
||||
|
||||
let afl = format!("{}/AFLplusplus", &cwd);
|
||||
|
@ -3,27 +3,26 @@ use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use libafl::{
|
||||
HasMetadata,
|
||||
corpus::{Corpus, InMemoryCorpus, OnDiskCorpus},
|
||||
events::SimpleEventManager,
|
||||
executors::{forkserver::ForkserverExecutor, HasObservers},
|
||||
executors::{HasObservers, forkserver::ForkserverExecutor},
|
||||
feedback_and_fast, feedback_or,
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::BytesInput,
|
||||
monitors::SimpleMonitor,
|
||||
mutators::{havoc_mutations, tokens_mutations, StdScheduledMutator, Tokens},
|
||||
mutators::{StdScheduledMutator, Tokens, havoc_mutations, tokens_mutations},
|
||||
observers::{CanTrack, HitcountsMapObserver, StdMapObserver, TimeObserver},
|
||||
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
|
||||
stages::mutational::StdMutationalStage,
|
||||
state::{HasCorpus, StdState},
|
||||
HasMetadata,
|
||||
};
|
||||
use libafl_bolts::{
|
||||
current_nanos,
|
||||
AsSliceMut, Truncate, current_nanos,
|
||||
rands::StdRand,
|
||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||
tuples::{tuple_list, Handled, Merge},
|
||||
AsSliceMut, Truncate,
|
||||
tuples::{Handled, Merge, tuple_list},
|
||||
};
|
||||
use nix::sys::signal::Signal;
|
||||
|
||||
@ -97,7 +96,9 @@ pub fn main() {
|
||||
// The coverage map shared between observer and executor
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
|
||||
// Create an observation channel using the signals map
|
||||
|
@ -242,7 +242,9 @@ fn fuzz(
|
||||
// The coverage map shared between observer and executor
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
// To let know the AFL++ binary that we have a big map
|
||||
std::env::set_var("AFL_MAP_SIZE", format!("{}", MAP_SIZE));
|
||||
@ -348,7 +350,9 @@ fn fuzz(
|
||||
// The cmplog map shared between observer and executor
|
||||
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
|
||||
}
|
||||
let cmpmap = unsafe { OwnedRefMut::<AFLppCmpLogMap>::from_shmem(&mut cmplog_shmem) };
|
||||
|
||||
let cmplog_observer = StdCmpObserver::new("cmplog", cmpmap, true);
|
||||
|
@ -244,7 +244,9 @@ fn fuzz(
|
||||
// The coverage map shared between observer and executor
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
// To let know the AFL++ binary that we have a big map
|
||||
std::env::set_var("AFL_MAP_SIZE", format!("{MAP_SIZE}"));
|
||||
@ -351,7 +353,9 @@ fn fuzz(
|
||||
// The cmplog map shared between observer and executor
|
||||
let mut cmplog_shmem = shmem_provider.uninit_on_shmem::<AFLppCmpLogMap>().unwrap();
|
||||
// let the forkserver know the shmid
|
||||
unsafe {
|
||||
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
|
||||
}
|
||||
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
|
||||
|
||||
let cmplog_observer = AFLppCmpLogObserver::new("cmplog", cmpmap, true);
|
||||
|
@ -200,7 +200,7 @@ pub fn find_afl_binary(filename: &str, same_dir_as: Option<PathBuf>) -> Result<P
|
||||
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 {
|
||||
u32::from(S_IRUSR) // user can read
|
||||
} else {
|
||||
|
@ -122,7 +122,9 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
|
||||
let mut shmem = shmem_provider
|
||||
.new_shmem(opt.map_size.unwrap_or(AFL_DEFAULT_MAP_SIZE))
|
||||
.unwrap();
|
||||
unsafe {
|
||||
shmem.write_to_env(SHMEM_ENV_VAR).unwrap();
|
||||
}
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
|
||||
// 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.
|
||||
if let Some(preload_env) = &opt.afl_preload {
|
||||
std::env::set_var("LD_PRELOAD", preload_env);
|
||||
std::env::set_var("DYLD_INSERT_LIBRARIES", preload_env);
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
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
|
||||
if opt.frida_mode {
|
||||
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()))?
|
||||
.display()
|
||||
@ -317,8 +322,10 @@ define_run_client!(state, mgr, fuzzer_dir, core_id, opt, is_main_node, {
|
||||
} else {
|
||||
frida_bin
|
||||
};
|
||||
std::env::set_var("LD_PRELOAD", &preload);
|
||||
std::env::set_var("DYLD_INSERT_LIBRARIES", &preload);
|
||||
// TODO: Audit that the environment access only happens in single-threaded code.
|
||||
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")]
|
||||
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
|
||||
let cmplog_executable_path = match &opt.cmplog {
|
||||
None => "-",
|
||||
Some(ref p) => match p.as_str() {
|
||||
Some(p) => match p.as_str() {
|
||||
"0" => opt.executable.to_str().unwrap(),
|
||||
_ => 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 the Forkserver know the CmpLog shared memory map ID.
|
||||
unsafe {
|
||||
cmplog_shmem.write_to_env("__AFL_CMPLOG_SHM_ID").unwrap();
|
||||
}
|
||||
let cmpmap = unsafe { OwnedRefMut::from_shmem(&mut cmplog_shmem) };
|
||||
|
||||
// Create the CmpLog observer.
|
||||
|
@ -5,7 +5,7 @@ authors = [
|
||||
"Andrea Fioraldi <andreafioraldi@gmail.com>",
|
||||
"Dominik Maier <domenukk@gmail.com>",
|
||||
]
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
|
@ -8,10 +8,15 @@ pub fn main() {
|
||||
let mut dir = env::current_exe().unwrap();
|
||||
let wrapper_name = dir.file_name().unwrap().to_str().unwrap();
|
||||
|
||||
let is_cpp = match wrapper_name[wrapper_name.len()-2..].to_lowercase().as_str() {
|
||||
let is_cpp = match wrapper_name[wrapper_name.len() - 2..]
|
||||
.to_lowercase()
|
||||
.as_str()
|
||||
{
|
||||
"cc" => false,
|
||||
"++" | "pp" | "xx" => true,
|
||||
_ => panic!("Could not figure out if c or c++ 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();
|
||||
|
@ -16,47 +16,46 @@ use std::{
|
||||
|
||||
use clap::{Arg, Command};
|
||||
use libafl::{
|
||||
Error, HasMetadata,
|
||||
corpus::{Corpus, InMemoryOnDiskCorpus, OnDiskCorpus},
|
||||
events::SimpleRestartingEventManager,
|
||||
executors::{inprocess::InProcessExecutor, ExitKind},
|
||||
executors::{ExitKind, inprocess::InProcessExecutor},
|
||||
feedback_or,
|
||||
feedbacks::{CrashFeedback, MaxMapFeedback, TimeFeedback},
|
||||
fuzzer::{Fuzzer, StdFuzzer},
|
||||
inputs::{BytesInput, HasTargetBytes},
|
||||
monitors::SimpleMonitor,
|
||||
mutators::{
|
||||
havoc_mutations, token_mutations::I2SRandReplace, tokens_mutations, StdMOptMutator,
|
||||
StdScheduledMutator, Tokens,
|
||||
StdMOptMutator, StdScheduledMutator, Tokens, havoc_mutations,
|
||||
token_mutations::I2SRandReplace, tokens_mutations,
|
||||
},
|
||||
observers::{CanTrack, HitcountsMapObserver, TimeObserver},
|
||||
schedulers::{
|
||||
powersched::PowerSchedule, IndexesLenTimeMinimizerScheduler, StdWeightedScheduler,
|
||||
IndexesLenTimeMinimizerScheduler, StdWeightedScheduler, powersched::PowerSchedule,
|
||||
},
|
||||
stages::{
|
||||
calibrate::CalibrationStage, power::StdPowerMutationalStage, StdMutationalStage,
|
||||
TracingStage,
|
||||
StdMutationalStage, TracingStage, calibrate::CalibrationStage,
|
||||
power::StdPowerMutationalStage,
|
||||
},
|
||||
state::{HasCorpus, StdState},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
use libafl_bolts::{
|
||||
current_time,
|
||||
AsSlice, current_time,
|
||||
os::dup2,
|
||||
rands::StdRand,
|
||||
shmem::{ShMemProvider, StdShMemProvider},
|
||||
tuples::{tuple_list, Merge},
|
||||
AsSlice,
|
||||
tuples::{Merge, tuple_list},
|
||||
};
|
||||
#[cfg(any(target_os = "linux", target_vendor = "apple"))]
|
||||
use libafl_targets::autotokens;
|
||||
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)]
|
||||
use nix::unistd::dup;
|
||||
|
||||
/// The fuzzer main (as `no_mangle` C function)
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn libafl_main() {
|
||||
// Registry the metadata types used in this fuzzer
|
||||
// Needed only on no_std
|
||||
|
@ -95,8 +95,12 @@ pub fn main() {
|
||||
|
||||
// The coverage map shared between observer and executor
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).unwrap();
|
||||
|
||||
unsafe {
|
||||
// let the forkserver know the shmid
|
||||
shmem.write_to_env("__AFL_SHM_ID").unwrap();
|
||||
}
|
||||
|
||||
let shmem_buf = shmem.as_slice_mut();
|
||||
|
||||
// Create an observation channel using the signals map
|
||||
|
@ -11,8 +11,8 @@ repository = "https://github.com/AFLplusplus/LibAFL/"
|
||||
readme = "../README.md"
|
||||
license = "MIT OR Apache-2.0"
|
||||
keywords = ["fuzzing", "testing", "security"]
|
||||
edition = "2021"
|
||||
rust-version = "1.82"
|
||||
edition = "2024"
|
||||
rust-version = "1.85"
|
||||
categories = [
|
||||
"development-tools::testing",
|
||||
"emulators",
|
||||
|
@ -4,9 +4,9 @@
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
use libafl::monitors::{
|
||||
stats::{manager::ClientStatsManager, ClientStats},
|
||||
tui::TuiMonitor,
|
||||
Monitor,
|
||||
stats::{ClientStats, manager::ClientStatsManager},
|
||||
tui::TuiMonitor,
|
||||
};
|
||||
use libafl_bolts::ClientId;
|
||||
|
||||
|
@ -7,8 +7,8 @@ use core::any::type_name;
|
||||
pub mod nautilus;
|
||||
|
||||
use libafl_bolts::{
|
||||
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
|
||||
Error,
|
||||
serdeany::{NamedSerdeAnyMap, SerdeAny, SerdeAnyMap},
|
||||
};
|
||||
/// Trait for elements offering metadata
|
||||
pub trait HasMetadata {
|
||||
|
@ -2,7 +2,7 @@ use alloc::{string::String, vec::Vec};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::Write,
|
||||
sync::{atomic::AtomicBool, RwLock},
|
||||
sync::{RwLock, atomic::AtomicBool},
|
||||
};
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
|
@ -2,7 +2,7 @@ use alloc::vec::Vec;
|
||||
use core::{mem, num::NonZero};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use libafl_bolts::{rands::Rand, Error};
|
||||
use libafl_bolts::{Error, rands::Rand};
|
||||
|
||||
use crate::common::nautilus::grammartec::{
|
||||
chunkstore::ChunkStore,
|
||||
|
@ -3,8 +3,8 @@ use std::fmt;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{
|
||||
rands::{loaded_dice::LoadedDiceSampler, Rand},
|
||||
Error,
|
||||
rands::{Rand, loaded_dice::LoadedDiceSampler},
|
||||
};
|
||||
|
||||
use crate::common::nautilus::grammartec::{
|
||||
|
@ -4,9 +4,9 @@ use std::{cmp, io, io::Write, marker::Sized};
|
||||
use hashbrown::HashSet;
|
||||
use libafl_bolts::rands::Rand;
|
||||
use pyo3::{
|
||||
PyTypeInfo,
|
||||
prelude::{PyObject, PyResult, Python},
|
||||
types::{PyAnyMethods, PyBytes, PyBytesMethods, PyString, PyStringMethods, PyTuple},
|
||||
PyTypeInfo,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -380,11 +380,7 @@ impl Tree {
|
||||
done_nterms.insert(nterm);
|
||||
}
|
||||
}
|
||||
if ret.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(ret)
|
||||
}
|
||||
if ret.is_empty() { None } else { Some(ret) }
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
|
@ -7,12 +7,12 @@ use std::path::Path;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
corpus::{
|
||||
inmemory_ondisk::InMemoryOnDiskCorpus, ondisk::OnDiskMetadataFormat, Corpus, CorpusId,
|
||||
HasTestcase, Testcase,
|
||||
Corpus, CorpusId, HasTestcase, Testcase, inmemory_ondisk::InMemoryOnDiskCorpus,
|
||||
ondisk::OnDiskMetadataFormat,
|
||||
},
|
||||
inputs::Input,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A corpus that keeps a maximum number of [`Testcase`]s in memory
|
||||
|
@ -7,8 +7,8 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::HasTestcase;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
Error,
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
};
|
||||
|
||||
/// 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`
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
pub fn replace(&mut self, id: CorpusId, testcase: Testcase<I>) -> Option<Testcase<I>> {
|
||||
if let Some(entry) = self.map.get_mut(&id) {
|
||||
Some(entry.testcase.replace(testcase))
|
||||
} else {
|
||||
None
|
||||
match self.map.get_mut(&id) {
|
||||
Some(entry) => Some(entry.testcase.replace(testcase)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,23 +75,30 @@ impl<I> TestcaseStorageMap<I> {
|
||||
/// Remove a testcase given a [`CorpusId`]
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
pub fn remove(&mut self, id: CorpusId) -> Option<RefCell<Testcase<I>>> {
|
||||
if let Some(item) = self.map.remove(&id) {
|
||||
match self.map.remove(&id) {
|
||||
Some(item) => {
|
||||
self.remove_key(id);
|
||||
if let Some(prev) = item.prev {
|
||||
match item.prev {
|
||||
Some(prev) => {
|
||||
self.map.get_mut(&prev).unwrap().next = item.next;
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
// first elem
|
||||
self.first_id = item.next;
|
||||
}
|
||||
if let Some(next) = item.next {
|
||||
}
|
||||
match item.next {
|
||||
Some(next) => {
|
||||
self.map.get_mut(&next).unwrap().prev = item.prev;
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
// last elem
|
||||
self.last_id = item.prev;
|
||||
}
|
||||
}
|
||||
Some(item.testcase)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,10 +127,9 @@ impl<I> TestcaseStorageMap<I> {
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
#[must_use]
|
||||
pub fn next(&self, id: CorpusId) -> Option<CorpusId> {
|
||||
if let Some(item) = self.map.get(&id) {
|
||||
item.next
|
||||
} else {
|
||||
None
|
||||
match self.map.get(&id) {
|
||||
Some(item) => item.next,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,10 +157,9 @@ impl<I> TestcaseStorageMap<I> {
|
||||
#[cfg(not(feature = "corpus_btreemap"))]
|
||||
#[must_use]
|
||||
pub fn prev(&self, id: CorpusId) -> Option<CorpusId> {
|
||||
if let Some(item) = self.map.get(&id) {
|
||||
item.prev
|
||||
} else {
|
||||
None
|
||||
match self.map.get(&id) {
|
||||
Some(item) => item.prev,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,13 @@ use libafl_bolts::compress::GzipCompressor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
ondisk::{OnDiskMetadata, OnDiskMetadataFormat},
|
||||
HasTestcase,
|
||||
ondisk::{OnDiskMetadata, OnDiskMetadataFormat},
|
||||
};
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::{Corpus, CorpusId, InMemoryCorpus, Testcase},
|
||||
inputs::Input,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// Creates the given `path` and returns an error if it fails.
|
||||
|
@ -6,14 +6,14 @@ use core::{hash::Hash, marker::PhantomData};
|
||||
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use libafl_bolts::{
|
||||
current_time,
|
||||
AsIter, Named, current_time,
|
||||
tuples::{Handle, Handled},
|
||||
AsIter, Named,
|
||||
};
|
||||
use num_traits::ToPrimitive;
|
||||
use z3::{ast::Bool, Config, Context, Optimize};
|
||||
use z3::{Config, Context, Optimize, ast::Bool};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata, HasScheduler,
|
||||
corpus::Corpus,
|
||||
events::{Event, EventFirer, LogSeverity},
|
||||
executors::{Executor, HasObservers},
|
||||
@ -22,7 +22,6 @@ use crate::{
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
Error, HasMetadata, HasScheduler,
|
||||
};
|
||||
|
||||
/// Minimizes a corpus according to coverage maps, weighting by the specified `TestcaseScore`.
|
||||
|
@ -4,8 +4,8 @@ use core::{cell::RefCell, marker::PhantomData};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
Error,
|
||||
corpus::{Corpus, CorpusId, Testcase},
|
||||
};
|
||||
|
||||
/// A corpus which does not store any [`Testcase`]s.
|
||||
|
@ -16,9 +16,9 @@ use libafl_bolts::serdeany::SerdeAnyMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
corpus::{CachedOnDiskCorpus, Corpus, CorpusId, HasTestcase, Testcase},
|
||||
inputs::Input,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Options for the the format of the on-disk metadata
|
||||
|
@ -11,11 +11,11 @@ use core::{
|
||||
#[cfg(feature = "std")]
|
||||
use std::path::PathBuf;
|
||||
|
||||
use libafl_bolts::{serdeany::SerdeAnyMap, HasLen};
|
||||
use libafl_bolts::{HasLen, serdeany::SerdeAnyMap};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
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`].
|
||||
/// For a normal state, this should return a [`Testcase`] in the corpus, not the objectives.
|
||||
|
@ -1,17 +1,17 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::{fmt::Debug, marker::PhantomData};
|
||||
|
||||
use libafl_bolts::{
|
||||
ClientId, Error,
|
||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||
};
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||
use libafl_bolts::{
|
||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||
ClientId, Error,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
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
|
||||
pub struct CentralizedLlmpHook<I> {
|
||||
|
@ -9,9 +9,9 @@ use std::{
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use libafl_bolts::llmp::LLMP_FLAG_COMPRESSED;
|
||||
use libafl_bolts::{
|
||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag, LLMP_FLAG_FROM_MM},
|
||||
ownedref::OwnedRef,
|
||||
ClientId, Error,
|
||||
llmp::{Flags, LLMP_FLAG_FROM_MM, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||
ownedref::OwnedRef,
|
||||
};
|
||||
use serde::Serialize;
|
||||
use tokio::{
|
||||
@ -23,9 +23,9 @@ use tokio::{
|
||||
|
||||
use crate::{
|
||||
events::{
|
||||
Event,
|
||||
centralized::_LLMP_TAG_TO_MAIN,
|
||||
multi_machine::{MultiMachineMsg, TcpMultiMachineState},
|
||||
Event,
|
||||
},
|
||||
inputs::Input,
|
||||
};
|
||||
|
@ -2,20 +2,20 @@
|
||||
use alloc::vec::Vec;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use libafl_bolts::{
|
||||
ClientId,
|
||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||
};
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||
use libafl_bolts::{
|
||||
llmp::{Flags, LlmpBrokerInner, LlmpHook, LlmpMsgHookResult, Tag},
|
||||
ClientId,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use crate::events::llmp::COMPRESS_THRESHOLD;
|
||||
use crate::{
|
||||
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
Error,
|
||||
events::{BrokerEventResult, Event, llmp::LLMP_TAG_EVENT_TO_BOTH},
|
||||
monitors::{Monitor, stats::ClientStatsManager},
|
||||
};
|
||||
|
||||
/// centralized hook
|
||||
|
@ -11,34 +11,33 @@ use alloc::{string::String, vec::Vec};
|
||||
use core::{fmt::Debug, marker::PhantomData, time::Duration};
|
||||
use std::process;
|
||||
|
||||
use libafl_bolts::{
|
||||
ClientId,
|
||||
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
||||
shmem::{ShMem, ShMemProvider},
|
||||
tuples::{Handle, MatchNameRef},
|
||||
};
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use libafl_bolts::{
|
||||
compress::GzipCompressor,
|
||||
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 super::{AwaitRestartSafe, RecordSerializationTime};
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
use crate::events::llmp::COMPRESS_THRESHOLD;
|
||||
use crate::{
|
||||
Error,
|
||||
common::HasMetadata,
|
||||
events::{
|
||||
serialize_observers_adaptive, std_maybe_report_progress, std_report_progress,
|
||||
AdaptiveSerializer, CanSerializeObserver, Event, EventConfig, EventFirer, EventManagerId,
|
||||
EventReceiver, EventRestarter, HasEventManagerId, LogSeverity, ProgressReporter,
|
||||
SendExiting,
|
||||
SendExiting, serialize_observers_adaptive, std_maybe_report_progress, std_report_progress,
|
||||
},
|
||||
inputs::Input,
|
||||
observers::TimeObserver,
|
||||
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
|
||||
Error,
|
||||
};
|
||||
|
||||
pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
|
||||
@ -389,9 +388,14 @@ where
|
||||
|
||||
/// Write the config for a client `EventManager` to env vars, a new
|
||||
/// client can reattach using [`CentralizedEventManagerBuilder::build_existing_client_from_env()`].
|
||||
pub fn to_env(&self, env_name: &str) {
|
||||
///
|
||||
/// # 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
|
||||
pub fn is_main(&self) -> bool {
|
||||
|
@ -4,7 +4,7 @@
|
||||
//! other clients
|
||||
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`
|
||||
pub trait EventManagerHook<I, S> {
|
||||
|
@ -22,21 +22,21 @@ use std::{net::SocketAddr, string::String};
|
||||
use libafl_bolts::{
|
||||
core_affinity::{CoreId, Cores},
|
||||
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;
|
||||
#[cfg(all(unix, feature = "fork"))]
|
||||
use {
|
||||
crate::{
|
||||
events::{centralized::CentralizedEventManager, CentralizedLlmpHook, StdLlmpEventHook},
|
||||
events::{CentralizedLlmpHook, StdLlmpEventHook, centralized::CentralizedEventManager},
|
||||
inputs::Input,
|
||||
},
|
||||
alloc::string::ToString,
|
||||
libafl_bolts::{
|
||||
core_affinity::get_core_ids,
|
||||
llmp::{Broker, Brokers, LlmpBroker},
|
||||
os::{fork, ForkResult},
|
||||
os::{ForkResult, fork},
|
||||
},
|
||||
std::boxed::Box,
|
||||
};
|
||||
@ -51,13 +51,13 @@ use {libafl_bolts::os::startable_self, std::process::Stdio};
|
||||
#[cfg(all(unix, feature = "fork", feature = "multi_machine"))]
|
||||
use crate::events::multi_machine::{NodeDescriptor, TcpMultiMachineHooks};
|
||||
use crate::{
|
||||
Error,
|
||||
events::{
|
||||
llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr},
|
||||
EventConfig, EventManagerHooksTuple,
|
||||
llmp::{LlmpRestartingEventManager, LlmpShouldSaveState, ManagerKind, RestartingMgr},
|
||||
},
|
||||
monitors::Monitor,
|
||||
observers::TimeObserver,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The (internal) `env` that indicates we're running as client.
|
||||
@ -300,13 +300,16 @@ where
|
||||
if !debug_output {
|
||||
if let Some(file) = &self.opened_stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
if let Some(stderr) = &self.opened_stderr_file {
|
||||
match &self.opened_stderr_file {
|
||||
Some(stderr) => {
|
||||
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let client_description =
|
||||
ClientDescription::new(index, overcommit_id, bind_to);
|
||||
@ -365,7 +368,9 @@ where
|
||||
} else {
|
||||
for handle in &handles {
|
||||
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 {
|
||||
libc::waitpid(*handle, &mut status, 0);
|
||||
if status != 0 {
|
||||
@ -470,10 +475,14 @@ where
|
||||
|
||||
let client_description =
|
||||
ClientDescription::new(index, overcommit_i, core_id);
|
||||
// # Safety
|
||||
// This is set only once, in here, for the child.
|
||||
unsafe {
|
||||
std::env::set_var(
|
||||
_AFL_LAUNCHER_CLIENT,
|
||||
client_description.to_safe_string(),
|
||||
);
|
||||
}
|
||||
let mut child = startable_self()?;
|
||||
let child = (if debug_output {
|
||||
&mut child
|
||||
@ -522,7 +531,9 @@ where
|
||||
handle.kill()?;
|
||||
}
|
||||
} 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 {
|
||||
let ecode = handle.wait()?;
|
||||
if !ecode.success() {
|
||||
@ -759,13 +770,16 @@ where
|
||||
if !debug_output {
|
||||
if let Some(file) = &self.opened_stdout_file {
|
||||
dup2(file.as_raw_fd(), libc::STDOUT_FILENO)?;
|
||||
if let Some(stderr) = &self.opened_stderr_file {
|
||||
match &self.opened_stderr_file {
|
||||
Some(stderr) => {
|
||||
dup2(stderr.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
dup2(file.as_raw_fd(), libc::STDERR_FILENO)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let client_description =
|
||||
ClientDescription::new(index, overcommit_id, bind_to);
|
||||
|
@ -2,24 +2,24 @@
|
||||
|
||||
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")]
|
||||
use libafl_bolts::{
|
||||
compress::GzipCompressor,
|
||||
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
|
||||
};
|
||||
use libafl_bolts::{
|
||||
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
||||
shmem::{NopShMem, NopShMemProvider, ShMem, ShMemProvider},
|
||||
ClientId,
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
events::{Event, EventFirer},
|
||||
fuzzer::EvaluatorObservers,
|
||||
inputs::{Input, InputConverter, NopInput, NopInputConverter},
|
||||
state::{HasCurrentTestcase, HasSolutions, NopState},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The llmp restarting manager
|
||||
@ -242,10 +242,15 @@ where
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn to_env(&self, env_name: &str) {
|
||||
pub unsafe fn to_env(&self, env_name: &str) {
|
||||
unsafe {
|
||||
self.llmp.to_env(env_name).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle arriving events in the client
|
||||
fn handle_in_client<DI, E, EM, Z>(
|
||||
@ -265,7 +270,9 @@ where
|
||||
Event::NewTestcase {
|
||||
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 {
|
||||
return Ok(());
|
||||
|
@ -9,7 +9,7 @@ use alloc::vec::Vec;
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
num::NonZeroUsize,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
time::Duration,
|
||||
};
|
||||
use std::net::SocketAddr;
|
||||
@ -21,7 +21,12 @@ use libafl_bolts::os::startable_self;
|
||||
#[cfg(all(unix, not(miri)))]
|
||||
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
||||
#[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")]
|
||||
use libafl_bolts::{
|
||||
compress::GzipCompressor,
|
||||
@ -31,19 +36,14 @@ use libafl_bolts::{
|
||||
core_affinity::CoreId,
|
||||
current_time,
|
||||
llmp::{
|
||||
Broker, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection, LLMP_FLAG_FROM_MM,
|
||||
Broker, LLMP_FLAG_FROM_MM, LlmpBroker, LlmpClient, LlmpClientDescription, LlmpConnection,
|
||||
},
|
||||
os::CTRL_C_EXIT,
|
||||
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
|
||||
staterestore::StateRestorer,
|
||||
tuples::{tuple_list, Handle, MatchNameRef},
|
||||
tuples::{Handle, MatchNameRef, tuple_list},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use libafl_bolts::{
|
||||
llmp::{recv_tcp_msg, send_tcp_msg, TcpRequest, TcpResponse},
|
||||
IP_LOCALHOST,
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
@ -51,14 +51,15 @@ use crate::events::COMPRESS_THRESHOLD;
|
||||
#[cfg(all(unix, not(miri)))]
|
||||
use crate::events::EVENTMGR_SIGHANDLER_STATE;
|
||||
use crate::{
|
||||
Error,
|
||||
common::HasMetadata,
|
||||
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,
|
||||
std_report_progress, AdaptiveSerializer, AwaitRestartSafe, CanSerializeObserver, Event,
|
||||
EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId, EventReceiver,
|
||||
EventRestarter, HasEventManagerId, LlmpShouldSaveState, ProgressReporter,
|
||||
RecordSerializationTime, SendExiting, StdLlmpEventHook, LLMP_TAG_EVENT_TO_BOTH,
|
||||
_LLMP_TAG_EVENT_TO_BROKER,
|
||||
std_report_progress,
|
||||
},
|
||||
inputs::Input,
|
||||
monitors::Monitor,
|
||||
@ -67,7 +68,6 @@ use crate::{
|
||||
HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime,
|
||||
HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
|
||||
},
|
||||
Error,
|
||||
};
|
||||
|
||||
const INITIAL_EVENT_BUFFER_SIZE: usize = 1024 * 4;
|
||||
@ -285,7 +285,7 @@ where
|
||||
SP: ShMemProvider<ShMem = SHM>,
|
||||
{
|
||||
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();
|
||||
}
|
||||
// Also inform the broker that we are about to exit.
|
||||
@ -366,7 +366,10 @@ where
|
||||
..
|
||||
} => {
|
||||
#[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() {
|
||||
return Ok(Some((event, true)));
|
||||
@ -563,10 +566,15 @@ where
|
||||
{
|
||||
/// Write the config for a client `EventManager` to env vars, a new
|
||||
/// 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")]
|
||||
pub fn to_env(&self, env_name: &str) {
|
||||
pub unsafe fn to_env(&self, env_name: &str) {
|
||||
unsafe {
|
||||
self.llmp.to_env(env_name).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the staterestorer
|
||||
pub fn staterestorer(&self) -> &Option<StateRestorer<SHM, SP>> {
|
||||
@ -842,7 +850,9 @@ where
|
||||
)?;
|
||||
|
||||
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 } => {
|
||||
// We are a client
|
||||
@ -867,7 +877,11 @@ where
|
||||
}
|
||||
|
||||
// We are the fuzzer respawner in a llmp client
|
||||
// # 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.
|
||||
#[cfg(unix)]
|
||||
@ -877,8 +891,13 @@ where
|
||||
#[cfg(not(unix))]
|
||||
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||
|
||||
// Store the information to a map.
|
||||
// # Safety
|
||||
// Very likely single threaded here.
|
||||
unsafe {
|
||||
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
||||
}
|
||||
|
||||
let mut ctr: u64 = 0;
|
||||
// Client->parent loop
|
||||
@ -943,9 +962,14 @@ where
|
||||
log::error!("Failed to detach from broker: {err}");
|
||||
}
|
||||
#[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
|
||||
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);
|
||||
@ -1026,21 +1050,22 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::sync::atomic::{Ordering, compiler_fence};
|
||||
|
||||
use libafl_bolts::{
|
||||
ClientId,
|
||||
llmp::{LlmpClient, LlmpSharedMap},
|
||||
rands::StdRand,
|
||||
shmem::{ShMemProvider, StdShMem, StdShMemProvider},
|
||||
staterestore::StateRestorer,
|
||||
tuples::{tuple_list, Handled},
|
||||
ClientId,
|
||||
tuples::{Handled, tuple_list},
|
||||
};
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::{
|
||||
StdFuzzer,
|
||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||
events::llmp::restarting::{LlmpEventManagerBuilder, _ENV_FUZZER_SENDER},
|
||||
events::llmp::restarting::{_ENV_FUZZER_SENDER, LlmpEventManagerBuilder},
|
||||
executors::{ExitKind, InProcessExecutor},
|
||||
feedbacks::ConstFeedback,
|
||||
fuzzer::Fuzzer,
|
||||
@ -1050,7 +1075,6 @@ mod tests {
|
||||
schedulers::RandScheduler,
|
||||
stages::StdMutationalStage,
|
||||
state::StdState,
|
||||
StdFuzzer,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@ -1131,7 +1155,11 @@ mod tests {
|
||||
assert!(staterestorer.has_content());
|
||||
|
||||
// Store the information to a map.
|
||||
// # Safety
|
||||
// Single-threaded test code
|
||||
unsafe {
|
||||
staterestorer.write_to_env(_ENV_FUZZER_SENDER).unwrap();
|
||||
}
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
|
@ -34,9 +34,9 @@ pub use broker_hooks::*;
|
||||
#[cfg(feature = "std")]
|
||||
pub use launcher::*;
|
||||
#[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;
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use libafl_bolts::os::unix_signals::{Signal, SignalHandler, siginfo_t, ucontext_t};
|
||||
#[cfg(feature = "std")]
|
||||
use libafl_bolts::tuples::MatchNameRef;
|
||||
use libafl_bolts::{current_time, tuples::Handle};
|
||||
@ -45,11 +45,11 @@ use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
executors::ExitKind,
|
||||
inputs::Input,
|
||||
monitors::stats::UserStats,
|
||||
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// Multi-machine mode
|
||||
@ -871,7 +871,7 @@ pub trait AdaptiveSerializer {
|
||||
#[cfg(test)]
|
||||
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 crate::{
|
||||
|
@ -5,17 +5,17 @@ use std::{
|
||||
io::ErrorKind,
|
||||
process,
|
||||
sync::{
|
||||
atomic::{AtomicU64, Ordering},
|
||||
Arc, OnceLock,
|
||||
atomic::{AtomicU64, Ordering},
|
||||
},
|
||||
time::Duration,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use enumflags2::{bitflags, BitFlags};
|
||||
use enumflags2::{BitFlags, bitflags};
|
||||
#[cfg(feature = "llmp_compression")]
|
||||
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 tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
@ -216,6 +216,7 @@ where
|
||||
where
|
||||
I: Input + Send + Sync + 'static,
|
||||
{
|
||||
unsafe {
|
||||
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",
|
||||
@ -233,18 +234,18 @@ where
|
||||
compressor: GzipCompressor::new(),
|
||||
}));
|
||||
|
||||
let rt =
|
||||
Arc::new(Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?);
|
||||
let rt = Arc::new(
|
||||
Runtime::new().map_err(|_| Error::unknown("Tokio runtime spawning failed"))?,
|
||||
);
|
||||
|
||||
unsafe {
|
||||
TcpMultiMachineState::init::<I>(&state.clone(), &rt.clone())?;
|
||||
}
|
||||
|
||||
Ok(TcpMultiMachineHooks {
|
||||
sender: TcpMultiMachineLlmpSenderHook::new(state.clone(), rt.clone()),
|
||||
receiver: TcpMultiMachineLlmpReceiverHook::new(state, rt),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> TcpMultiMachineState<A>
|
||||
|
@ -2,44 +2,44 @@
|
||||
|
||||
use alloc::vec::Vec;
|
||||
#[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 libafl_bolts::ClientId;
|
||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||
use libafl_bolts::os::startable_self;
|
||||
#[cfg(all(unix, feature = "std", not(miri)))]
|
||||
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
||||
#[cfg(all(feature = "std", feature = "fork", unix))]
|
||||
use libafl_bolts::os::{fork, ForkResult};
|
||||
use libafl_bolts::ClientId;
|
||||
use libafl_bolts::os::{ForkResult, fork};
|
||||
#[cfg(feature = "std")]
|
||||
use libafl_bolts::{
|
||||
os::CTRL_C_EXIT,
|
||||
shmem::{ShMem, ShMemProvider},
|
||||
staterestore::StateRestorer,
|
||||
};
|
||||
use serde::Serialize;
|
||||
#[cfg(feature = "std")]
|
||||
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)))]
|
||||
use crate::events::EVENTMGR_SIGHANDLER_STATE;
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
events::{
|
||||
std_maybe_report_progress, std_report_progress, BrokerEventResult, CanSerializeObserver,
|
||||
Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId,
|
||||
SendExiting,
|
||||
BrokerEventResult, CanSerializeObserver, Event, EventFirer, EventManagerId, EventReceiver,
|
||||
EventRestarter, HasEventManagerId, SendExiting, std_maybe_report_progress,
|
||||
std_report_progress,
|
||||
},
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
monitors::{Monitor, stats::ClientStatsManager},
|
||||
state::{
|
||||
HasCurrentStageId, HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable,
|
||||
},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::{
|
||||
monitors::{stats::ClientStats, SimplePrintingMonitor},
|
||||
monitors::{SimplePrintingMonitor, stats::ClientStats},
|
||||
state::HasSolutions,
|
||||
};
|
||||
|
||||
@ -132,7 +132,7 @@ where
|
||||
_ => {
|
||||
return Err(Error::unknown(format!(
|
||||
"Received illegal message that message should not have arrived: {event:?}."
|
||||
)))
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -454,7 +454,12 @@ where
|
||||
StateRestorer::new(shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||
|
||||
//let staterestorer = { LlmpSender::new(shmem_provider.clone(), 0, false)? };
|
||||
|
||||
// # Safety
|
||||
// Launcher is usually running in a single thread.
|
||||
unsafe {
|
||||
staterestorer.write_to_env(_ENV_FUZZER_SENDER)?;
|
||||
}
|
||||
|
||||
let mut ctr: u64 = 0;
|
||||
// Client->parent loop
|
||||
@ -509,10 +514,14 @@ where
|
||||
if !staterestorer.has_content() {
|
||||
#[cfg(unix)]
|
||||
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
|
||||
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);
|
||||
|
@ -4,7 +4,7 @@ use alloc::vec::Vec;
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
num::NonZeroUsize,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
time::Duration,
|
||||
};
|
||||
use std::{
|
||||
@ -21,38 +21,38 @@ use libafl_bolts::os::startable_self;
|
||||
#[cfg(all(unix, not(miri)))]
|
||||
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
||||
#[cfg(all(feature = "fork", unix))]
|
||||
use libafl_bolts::os::{fork, ForkResult};
|
||||
use libafl_bolts::os::{ForkResult, fork};
|
||||
use libafl_bolts::{
|
||||
ClientId,
|
||||
core_affinity::CoreId,
|
||||
os::CTRL_C_EXIT,
|
||||
shmem::{ShMem, ShMemProvider, StdShMem, StdShMemProvider},
|
||||
staterestore::StateRestorer,
|
||||
tuples::tuple_list,
|
||||
ClientId,
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
sync::{broadcast, broadcast::error::RecvError, mpsc},
|
||||
task::{spawn, JoinHandle},
|
||||
task::{JoinHandle, spawn},
|
||||
};
|
||||
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)))]
|
||||
use crate::events::EVENTMGR_SIGHANDLER_STATE;
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
events::{
|
||||
std_on_restart, BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple,
|
||||
EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter,
|
||||
BrokerEventResult, Event, EventConfig, EventFirer, EventManagerHooksTuple, EventManagerId,
|
||||
EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter, std_on_restart,
|
||||
},
|
||||
inputs::Input,
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
monitors::{Monitor, stats::ClientStatsManager},
|
||||
state::{
|
||||
HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime,
|
||||
HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
|
||||
},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// Tries to create (synchronously) a [`TcpListener`] that is `nonblocking` (for later use in tokio).
|
||||
@ -244,7 +244,8 @@ where
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -573,9 +574,14 @@ where
|
||||
S: HasExecutions + HasMetadata + HasImported + Stoppable,
|
||||
{
|
||||
/// Write the client id for a client `EventManager` to env vars
|
||||
pub fn to_env(&self, env_name: &str) {
|
||||
///
|
||||
/// # 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<EMH, I, S> TcpEventManager<EMH, I, S> {
|
||||
@ -684,7 +690,9 @@ where
|
||||
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)
|
||||
&& observers_buf.is_some()
|
||||
{
|
||||
@ -704,7 +712,7 @@ where
|
||||
return Err(Error::unknown(format!(
|
||||
"Received illegal message that message should not have arrived: {:?}.",
|
||||
event.name()
|
||||
)))
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1118,7 +1126,9 @@ where
|
||||
)?;
|
||||
|
||||
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 } => {
|
||||
// We are a client
|
||||
@ -1137,7 +1147,11 @@ where
|
||||
}
|
||||
|
||||
// We are the fuzzer respawner in a tcp client
|
||||
// # 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.
|
||||
#[cfg(unix)]
|
||||
@ -1147,8 +1161,14 @@ where
|
||||
#[cfg(not(unix))]
|
||||
let staterestorer: StateRestorer<SP::ShMem, SP> =
|
||||
StateRestorer::new(self.shmem_provider.new_shmem(256 * 1024 * 1024)?);
|
||||
|
||||
// Store the information to a map.
|
||||
// # 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;
|
||||
// Client->parent loop
|
||||
@ -1206,11 +1226,15 @@ where
|
||||
if child_status == 137 {
|
||||
// Out of Memory, see https://tldp.org/LDP/abs/html/exitcodes.html
|
||||
// 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
|
||||
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);
|
||||
|
@ -7,8 +7,8 @@ use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use super::HasTimeout;
|
||||
use crate::{
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
};
|
||||
|
||||
/// A [`CombinedExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
|
||||
|
@ -22,9 +22,9 @@ use std::{
|
||||
#[cfg(all(feature = "intel_pt", target_os = "linux"))]
|
||||
use libafl_bolts::core_affinity::CoreId;
|
||||
use libafl_bolts::{
|
||||
fs::{get_unique_std_input_file, InputFile},
|
||||
tuples::{Handle, MatchName, RefIndexable},
|
||||
AsSlice,
|
||||
fs::{InputFile, get_unique_std_input_file},
|
||||
tuples::{Handle, MatchName, RefIndexable},
|
||||
};
|
||||
#[cfg(all(feature = "intel_pt", target_os = "linux"))]
|
||||
use libc::STDIN_FILENO;
|
||||
@ -36,8 +36,9 @@ use nix::{
|
||||
signal::Signal,
|
||||
wait::WaitStatus,
|
||||
wait::{
|
||||
waitpid, WaitPidFlag,
|
||||
WaitPidFlag,
|
||||
WaitStatus::{Exited, PtraceEvent, Signaled, Stopped},
|
||||
waitpid,
|
||||
},
|
||||
},
|
||||
unistd::Pid,
|
||||
@ -49,12 +50,12 @@ use super::HasTimeout;
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::executors::hooks::ExecutorHooksTuple;
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::HasTargetBytes,
|
||||
observers::{ObserversTuple, StdErrObserver, StdOutObserver},
|
||||
state::HasExecutions,
|
||||
std::borrow::ToOwned,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// How to deliver input to an external program
|
||||
@ -151,15 +152,20 @@ where
|
||||
InputLocation::StdIn => {
|
||||
let mut handle = self.command.stdin(Stdio::piped()).spawn()?;
|
||||
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()) {
|
||||
Err(err) => {
|
||||
if err.kind() != std::io::ErrorKind::BrokenPipe {
|
||||
return Err(err.into());
|
||||
}
|
||||
} else if let Err(err) = stdin.flush() {
|
||||
}
|
||||
_ => {
|
||||
if let Err(err) = stdin.flush() {
|
||||
if err.kind() != std::io::ErrorKind::BrokenPipe {
|
||||
return Err(err.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(stdin);
|
||||
Ok(handle)
|
||||
}
|
||||
@ -208,9 +214,9 @@ where
|
||||
use nix::{
|
||||
sys::{
|
||||
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() } {
|
||||
@ -482,9 +488,9 @@ where
|
||||
// Stopped(pid, Signal::SIGKILL) if pid == child => ExitKind::Oom,
|
||||
s => {
|
||||
// TODO other cases?
|
||||
return Err(Error::unsupported(
|
||||
format!("Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})")
|
||||
));
|
||||
return Err(Error::unsupported(format!(
|
||||
"Target program returned an unexpected state when waiting on it. {s:?} (waiting for pid {child})"
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -746,11 +752,11 @@ impl CommandExecutorBuilder {
|
||||
/// };
|
||||
///
|
||||
/// use libafl::{
|
||||
/// Error,
|
||||
/// corpus::Corpus,
|
||||
/// executors::{command::CommandConfigurator, Executor},
|
||||
/// executors::{Executor, command::CommandConfigurator},
|
||||
/// inputs::{BytesInput, HasTargetBytes, Input},
|
||||
/// state::HasExecutions,
|
||||
/// Error,
|
||||
/// };
|
||||
/// use libafl_bolts::AsSlice;
|
||||
/// #[derive(Debug)]
|
||||
@ -861,8 +867,8 @@ mod tests {
|
||||
use crate::{
|
||||
events::SimpleEventManager,
|
||||
executors::{
|
||||
command::{CommandExecutor, InputLocation},
|
||||
Executor,
|
||||
command::{CommandExecutor, InputLocation},
|
||||
},
|
||||
fuzzer::NopFuzzer,
|
||||
inputs::{BytesInput, NopInput},
|
||||
|
@ -18,9 +18,9 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::HasTimeout;
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
observers::{DifferentialObserversTuple, ObserversTuple},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A [`DiffExecutor`] wraps a primary executor, forwarding its methods, and a secondary one
|
||||
@ -200,23 +200,23 @@ where
|
||||
{
|
||||
#[expect(deprecated)]
|
||||
fn match_name<T>(&self, name: &str) -> Option<&T> {
|
||||
if let Some(t) = self.primary.as_ref().match_name::<T>(name) {
|
||||
Some(t)
|
||||
} else if let Some(t) = self.secondary.as_ref().match_name::<T>(name) {
|
||||
Some(t)
|
||||
} else {
|
||||
self.differential.match_name::<T>(name)
|
||||
match self.primary.as_ref().match_name::<T>(name) {
|
||||
Some(t) => Some(t),
|
||||
_ => match self.secondary.as_ref().match_name::<T>(name) {
|
||||
Some(t) => Some(t),
|
||||
_ => self.differential.match_name::<T>(name),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(deprecated)]
|
||||
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) {
|
||||
Some(t)
|
||||
} else if let Some(t) = self.secondary.as_mut().match_name_mut::<T>(name) {
|
||||
Some(t)
|
||||
} else {
|
||||
self.differential.match_name_mut::<T>(name)
|
||||
match self.primary.as_mut().match_name_mut::<T>(name) {
|
||||
Some(t) => Some(t),
|
||||
_ => match self.secondary.as_mut().match_name_mut::<T>(name) {
|
||||
Some(t) => Some(t),
|
||||
_ => self.differential.match_name_mut::<T>(name),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,18 +19,18 @@ use std::{
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
fs::{get_unique_std_input_file, InputFile},
|
||||
AsSlice, AsSliceMut, Truncate,
|
||||
fs::{InputFile, get_unique_std_input_file},
|
||||
os::{dup2, pipes::Pipe},
|
||||
ownedref::OwnedSlice,
|
||||
shmem::{ShMem, ShMemProvider, UnixShMem, UnixShMemProvider},
|
||||
tuples::{Handle, Handled, MatchNameRef, Prepend, RefIndexable},
|
||||
AsSlice, AsSliceMut, Truncate,
|
||||
};
|
||||
use libc::RLIM_INFINITY;
|
||||
use nix::{
|
||||
sys::{
|
||||
select::{pselect, FdSet},
|
||||
signal::{kill, SigSet, Signal},
|
||||
select::{FdSet, pselect},
|
||||
signal::{SigSet, Signal, kill},
|
||||
time::TimeSpec,
|
||||
wait::waitpid,
|
||||
},
|
||||
@ -40,15 +40,15 @@ use nix::{
|
||||
use super::HasTimeout;
|
||||
#[cfg(feature = "regex")]
|
||||
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::{
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
inputs::{BytesInput, HasTargetBytes, Input, NopTargetBytesConverter, TargetBytesConverter},
|
||||
mutators::Tokens,
|
||||
observers::{MapObserver, Observer, ObserversTuple},
|
||||
state::HasExecutions,
|
||||
Error,
|
||||
};
|
||||
|
||||
const FORKSRV_FD: i32 = 198;
|
||||
@ -365,7 +365,9 @@ impl Forkserver {
|
||||
kill_signal: Signal,
|
||||
) -> Result<Self, Error> {
|
||||
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() {
|
||||
@ -442,7 +444,7 @@ impl Forkserver {
|
||||
Err(err) => {
|
||||
return Err(Error::illegal_state(format!(
|
||||
"Could not spawn the forkserver: {err:#?}"
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
@ -648,8 +650,8 @@ where
|
||||
impl ForkserverExecutor<(), (), (), UnixShMem, ()> {
|
||||
/// Builder for `ForkserverExecutor`
|
||||
#[must_use]
|
||||
pub fn builder(
|
||||
) -> ForkserverExecutorBuilder<'static, NopTargetBytesConverter<BytesInput>, UnixShMemProvider>
|
||||
pub fn builder()
|
||||
-> ForkserverExecutorBuilder<'static, NopTargetBytesConverter<BytesInput>, UnixShMemProvider>
|
||||
{
|
||||
ForkserverExecutorBuilder::new()
|
||||
}
|
||||
@ -977,7 +979,11 @@ where
|
||||
Some(provider) => {
|
||||
// setup shared memory
|
||||
let mut shmem = provider.new_shmem(self.max_input_size + SHMEM_FUZZ_HDR_SIZE)?;
|
||||
// # 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();
|
||||
shmem.as_slice_mut()[..4].clone_from_slice(&size_in_bytes[..4]);
|
||||
@ -1003,7 +1009,7 @@ where
|
||||
None => {
|
||||
return Err(Error::illegal_argument(
|
||||
"ForkserverExecutorBuilder::build: target file not found".to_string(),
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
@ -1042,7 +1048,9 @@ where
|
||||
let version: u32 = status as u32 - 0x41464c00_u32;
|
||||
match version {
|
||||
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 => {
|
||||
// good, do nothing
|
||||
@ -1101,9 +1109,9 @@ where
|
||||
let tokens_size_max = 0xffffff;
|
||||
|
||||
if !(2..=tokens_size_max).contains(&autotokens_size) {
|
||||
return Err(Error::illegal_state(
|
||||
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."),
|
||||
));
|
||||
return Err(Error::illegal_state(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."
|
||||
)));
|
||||
}
|
||||
log::info!("Autotokens size {autotokens_size:x}");
|
||||
let buf = forkserver
|
||||
@ -1280,12 +1288,15 @@ where
|
||||
// subsequent arguments as regular arguments
|
||||
use_arg_0_as_program = false;
|
||||
} else if item.as_ref() == "@@" {
|
||||
if let Some(name) = &moved.input_filename.clone() {
|
||||
match &moved.input_filename.clone() {
|
||||
Some(name) => {
|
||||
// If the input file name has been modified, use this one
|
||||
moved = moved.arg_input_file(name);
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
moved = moved.arg_input_file_std();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
moved = moved.arg(item);
|
||||
}
|
||||
@ -1469,8 +1480,8 @@ impl<'a> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, Unix
|
||||
/// in case no input file is specified.
|
||||
/// If `debug_child` is set, the child will print to `stdout`/`stderr`.
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
) -> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, UnixShMemProvider> {
|
||||
pub fn new()
|
||||
-> ForkserverExecutorBuilder<'a, NopTargetBytesConverter<BytesInput>, UnixShMemProvider> {
|
||||
ForkserverExecutorBuilder {
|
||||
program: None,
|
||||
arguments: vec![],
|
||||
@ -1623,18 +1634,18 @@ mod tests {
|
||||
use std::ffi::OsString;
|
||||
|
||||
use libafl_bolts::{
|
||||
AsSliceMut,
|
||||
shmem::{ShMem, ShMemProvider, UnixShMemProvider},
|
||||
tuples::tuple_list,
|
||||
AsSliceMut,
|
||||
};
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
corpus::NopCorpus,
|
||||
executors::forkserver::{ForkserverExecutor, FAILED_TO_START_FORKSERVER_MSG},
|
||||
executors::forkserver::{FAILED_TO_START_FORKSERVER_MSG, ForkserverExecutor},
|
||||
inputs::BytesInput,
|
||||
observers::{ConstMapObserver, HitcountsMapObserver},
|
||||
Error,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@ -1648,7 +1659,11 @@ mod tests {
|
||||
let mut shmem_provider = UnixShMemProvider::new().unwrap();
|
||||
|
||||
let mut shmem = shmem_provider.new_shmem(MAP_SIZE).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 edges_observer = HitcountsMapObserver::new(ConstMapObserver::<_, MAP_SIZE>::new(
|
||||
|
@ -2,7 +2,7 @@
|
||||
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||
use core::mem::zeroed;
|
||||
#[cfg(any(unix, all(windows, feature = "std")))]
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::sync::atomic::{Ordering, compiler_fence};
|
||||
use core::{
|
||||
ffi::c_void,
|
||||
marker::PhantomData,
|
||||
@ -13,7 +13,7 @@ use core::{
|
||||
#[cfg(all(target_os = "linux", feature = "std"))]
|
||||
use libafl_bolts::current_time;
|
||||
#[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)))]
|
||||
use libafl_bolts::os::unix_signals::setup_signal_handler;
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
@ -24,16 +24,16 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::executors::hooks::timer::TimerStruct;
|
||||
use crate::{
|
||||
Error, HasObjective,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{hooks::ExecutorHook, inprocess::HasInProcessHooks, Executor, HasObservers},
|
||||
executors::{Executor, HasObservers, hooks::ExecutorHook, inprocess::HasInProcessHooks},
|
||||
feedbacks::Feedback,
|
||||
state::{HasExecutions, HasSolutions},
|
||||
Error, HasObjective,
|
||||
};
|
||||
#[cfg(all(unix, feature = "std"))]
|
||||
use crate::{
|
||||
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,
|
||||
};
|
||||
@ -445,6 +445,7 @@ impl InProcessExecutorHandlerData {
|
||||
Z: HasObjective<Objective = OF>,
|
||||
I: Input + Clone,
|
||||
{
|
||||
unsafe {
|
||||
if self.is_valid() {
|
||||
let executor = self.executor_mut::<E>();
|
||||
// disarms timeout in case of timeout
|
||||
@ -483,6 +484,7 @@ impl InProcessExecutorHandlerData {
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Exception handling needs some nasty unsafe.
|
||||
|
@ -5,23 +5,22 @@ use core::{
|
||||
marker::PhantomData,
|
||||
mem::transmute,
|
||||
ptr::null,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
};
|
||||
|
||||
#[cfg(not(miri))]
|
||||
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 crate::{
|
||||
Error,
|
||||
executors::{
|
||||
common_signals,
|
||||
HasObservers, common_signals,
|
||||
hooks::ExecutorHook,
|
||||
inprocess_fork::{child_signal_handlers, ForkHandlerFuncPtr},
|
||||
HasObservers,
|
||||
inprocess_fork::{ForkHandlerFuncPtr, child_signal_handlers},
|
||||
},
|
||||
observers::ObserversTuple,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The inmem fork executor's hooks.
|
||||
|
@ -10,7 +10,7 @@ pub(crate) const ITIMER_REAL: core::ffi::c_int = 0;
|
||||
use core::{
|
||||
ffi::c_void,
|
||||
ptr::write_volatile,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
@ -19,9 +19,9 @@ use libafl_bolts::current_time;
|
||||
use windows::Win32::{
|
||||
Foundation::FILETIME,
|
||||
System::Threading::{
|
||||
CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection,
|
||||
LeaveCriticalSection, SetThreadpoolTimer, CRITICAL_SECTION, PTP_CALLBACK_INSTANCE,
|
||||
PTP_TIMER, TP_CALLBACK_ENVIRON_V3,
|
||||
CRITICAL_SECTION, CreateThreadpoolTimer, EnterCriticalSection, InitializeCriticalSection,
|
||||
LeaveCriticalSection, PTP_CALLBACK_INSTANCE, PTP_TIMER, SetThreadpoolTimer,
|
||||
TP_CALLBACK_ENVIRON_V3,
|
||||
},
|
||||
};
|
||||
|
||||
@ -59,7 +59,7 @@ pub(crate) struct Itimerval {
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
extern "C" {
|
||||
unsafe extern "C" {
|
||||
pub(crate) fn setitimer(
|
||||
which: libc::c_int,
|
||||
new_value: *mut Itimerval,
|
||||
|
@ -5,16 +5,15 @@ pub mod unix_signal_handler {
|
||||
use core::mem::transmute;
|
||||
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 crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
common_signals,
|
||||
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE},
|
||||
inprocess::{run_observers_and_save_state, HasInProcessHooks},
|
||||
Executor, ExitKind, HasObservers,
|
||||
Executor, ExitKind, HasObservers, common_signals,
|
||||
hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData},
|
||||
inprocess::{HasInProcessHooks, run_observers_and_save_state},
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
@ -147,6 +146,7 @@ pub mod unix_signal_handler {
|
||||
Z: HasObjective<Objective = OF>,
|
||||
I: Input + Clone,
|
||||
{
|
||||
unsafe {
|
||||
// this stuff is for batch timeout
|
||||
if !data.executor_ptr.is_null()
|
||||
&& data
|
||||
@ -181,6 +181,7 @@ pub mod unix_signal_handler {
|
||||
log::info!("Exiting");
|
||||
libc::_exit(55);
|
||||
}
|
||||
}
|
||||
|
||||
/// Crash-Handler for in-process fuzzing.
|
||||
/// Will be used for signal handling.
|
||||
@ -203,6 +204,7 @@ pub mod unix_signal_handler {
|
||||
Z: HasObjective<Objective = OF>,
|
||||
I: Input + Clone,
|
||||
{
|
||||
unsafe {
|
||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||
let _context = _context.map(|p| {
|
||||
&mut *(((core::ptr::from_mut(p) as *mut libc::c_void as usize) + 128)
|
||||
@ -295,4 +297,5 @@ pub mod unix_signal_handler {
|
||||
|
||||
libc::_exit(128 + (signal as i32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"))]
|
||||
pub mod windows_asan_handler {
|
||||
use alloc::string::String;
|
||||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::sync::atomic::{Ordering, compiler_fence};
|
||||
|
||||
use windows::Win32::System::Threading::{
|
||||
EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION,
|
||||
CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::inprocess::GLOBAL_STATE, inprocess::run_observers_and_save_state, Executor,
|
||||
ExitKind, HasObservers,
|
||||
Executor, ExitKind, HasObservers, hooks::inprocess::GLOBAL_STATE,
|
||||
inprocess::run_observers_and_save_state,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
@ -33,11 +33,14 @@ pub mod windows_asan_handler {
|
||||
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
unsafe {
|
||||
let data = &raw mut GLOBAL_STATE;
|
||||
let in_handler = (*data).set_in_handler(true);
|
||||
|
||||
if in_handler {
|
||||
log::error!("We crashed inside a asan death handler, but this should never happen!");
|
||||
log::error!(
|
||||
"We crashed inside a asan death handler, but this should never happen!"
|
||||
);
|
||||
ExitProcess(56);
|
||||
}
|
||||
|
||||
@ -103,6 +106,7 @@ pub mod windows_asan_handler {
|
||||
// Don't need to exit, Asan will exit for us
|
||||
// ExitProcess(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
@ -115,7 +119,7 @@ pub mod windows_exception_handler {
|
||||
ffi::c_void,
|
||||
mem::transmute,
|
||||
ptr,
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use std::io::Write;
|
||||
@ -123,19 +127,19 @@ pub mod windows_exception_handler {
|
||||
use std::panic;
|
||||
|
||||
use libafl_bolts::os::windows_exceptions::{
|
||||
ExceptionCode, ExceptionHandler, CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE,
|
||||
EXCEPTION_POINTERS,
|
||||
CRASH_EXCEPTIONS, EXCEPTION_HANDLERS_SIZE, EXCEPTION_POINTERS, ExceptionCode,
|
||||
ExceptionHandler,
|
||||
};
|
||||
use windows::Win32::System::Threading::{
|
||||
EnterCriticalSection, ExitProcess, LeaveCriticalSection, CRITICAL_SECTION,
|
||||
CRITICAL_SECTION, EnterCriticalSection, ExitProcess, LeaveCriticalSection,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::inprocess::{HasTimeout, InProcessExecutorHandlerData, GLOBAL_STATE},
|
||||
inprocess::{run_observers_and_save_state, HasInProcessHooks},
|
||||
Executor, ExitKind, HasObservers,
|
||||
hooks::inprocess::{GLOBAL_STATE, HasTimeout, InProcessExecutorHandlerData},
|
||||
inprocess::{HasInProcessHooks, run_observers_and_save_state},
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
@ -270,36 +274,41 @@ pub mod windows_exception_handler {
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
let data: &mut InProcessExecutorHandlerData =
|
||||
&mut *(global_state as *mut InProcessExecutorHandlerData);
|
||||
unsafe { &mut *(global_state as *mut InProcessExecutorHandlerData) };
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
EnterCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
if !data.executor_ptr.is_null()
|
||||
&& data
|
||||
.executor_mut::<E>()
|
||||
&& unsafe {
|
||||
data.executor_mut::<E>()
|
||||
.inprocess_hooks_mut()
|
||||
.handle_timeout()
|
||||
}
|
||||
{
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if data.in_target == 1 {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let state = data.state_mut::<S>();
|
||||
let fuzzer = data.fuzzer_mut::<Z>();
|
||||
let event_mgr = data.event_mgr_mut::<EM>();
|
||||
let executor = unsafe { data.executor_mut::<E>() };
|
||||
let state = unsafe { data.state_mut::<S>() };
|
||||
let fuzzer = unsafe { data.fuzzer_mut::<Z>() };
|
||||
let event_mgr = unsafe { data.event_mgr_mut::<EM>() };
|
||||
|
||||
if data.current_input_ptr.is_null() {
|
||||
log::error!("TIMEOUT or SIGUSR2 happened, but currently not fuzzing. Exiting");
|
||||
} else {
|
||||
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();
|
||||
|
||||
run_observers_and_save_state::<E, EM, I, OF, S, Z>(
|
||||
@ -313,11 +322,15 @@ pub mod windows_exception_handler {
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
unsafe {
|
||||
ExitProcess(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
LeaveCriticalSection((data.critical as *mut CRITICAL_SECTION).as_mut().unwrap());
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
// 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.
|
||||
*/
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
EnterCriticalSection(data.critical as *mut CRITICAL_SECTION);
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
data.in_target = 0;
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
unsafe {
|
||||
LeaveCriticalSection(data.critical as *mut CRITICAL_SECTION);
|
||||
}
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
}
|
||||
|
||||
// Is this really crash?
|
||||
let mut is_crash = true;
|
||||
#[cfg(feature = "std")]
|
||||
if let Some(exception_pointers) = exception_pointers.as_mut() {
|
||||
let code: ExceptionCode = ExceptionCode::from(
|
||||
if let Some(exception_pointers) = unsafe { exception_pointers.as_mut() } {
|
||||
let code: ExceptionCode = ExceptionCode::from(unsafe {
|
||||
exception_pointers
|
||||
.ExceptionRecord
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.ExceptionCode
|
||||
.0,
|
||||
);
|
||||
.0
|
||||
});
|
||||
|
||||
let exception_list = data.exceptions();
|
||||
if exception_list.contains(&code) {
|
||||
log::error!(
|
||||
"Crashed with {code} at {:?} in thread {:?}",
|
||||
unsafe {
|
||||
exception_pointers
|
||||
.ExceptionRecord
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.ExceptionAddress,
|
||||
winapi::um::processthreadsapi::GetCurrentThreadId()
|
||||
.ExceptionAddress
|
||||
},
|
||||
unsafe { winapi::um::processthreadsapi::GetCurrentThreadId() }
|
||||
);
|
||||
} else {
|
||||
// log::trace!("Exception code received, but {code} is not in CRASH_EXCEPTIONS");
|
||||
@ -389,13 +408,15 @@ pub mod windows_exception_handler {
|
||||
if data.current_input_ptr.is_null() {
|
||||
{
|
||||
log::error!("Double crash\n");
|
||||
let crash_addr = exception_pointers
|
||||
let crash_addr = unsafe {
|
||||
exception_pointers
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.ExceptionRecord
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.ExceptionAddress as usize;
|
||||
.ExceptionAddress as usize
|
||||
};
|
||||
|
||||
log::error!(
|
||||
"We crashed at addr 0x{crash_addr:x}, but are not in the target... Bug in the fuzzer? Exiting."
|
||||
@ -412,15 +433,15 @@ pub mod windows_exception_handler {
|
||||
|
||||
// TODO tell the parent to not restart
|
||||
} else {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let executor = unsafe { 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>();
|
||||
let state = unsafe { data.state_mut::<S>() };
|
||||
let fuzzer = unsafe { data.fuzzer_mut::<Z>() };
|
||||
let event_mgr = unsafe { data.event_mgr_mut::<EM>() };
|
||||
|
||||
if is_crash {
|
||||
log::error!("Child crashed!");
|
||||
@ -432,7 +453,7 @@ pub mod windows_exception_handler {
|
||||
if is_crash {
|
||||
log::warn!("Running observers and exiting!");
|
||||
// // 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>(
|
||||
executor,
|
||||
state,
|
||||
@ -459,8 +480,10 @@ pub mod windows_exception_handler {
|
||||
|
||||
if is_crash {
|
||||
log::info!("Exiting!");
|
||||
unsafe {
|
||||
ExitProcess(1);
|
||||
}
|
||||
}
|
||||
// log::info!("Not Exiting!");
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,11 @@ use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
ptr::{self, null, write_volatile},
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use libafl_bolts::tuples::{tuple_list, Merge, RefIndexable};
|
||||
use libafl_bolts::tuples::{Merge, RefIndexable, tuple_list};
|
||||
#[cfg(windows)]
|
||||
use windows::Win32::System::Threading::SetThreadStackGuarantee;
|
||||
|
||||
@ -16,21 +16,21 @@ use crate::executors::hooks::inprocess::HasTimeout;
|
||||
#[cfg(all(windows, feature = "std"))]
|
||||
use crate::executors::hooks::inprocess::HasTimeout;
|
||||
use crate::{
|
||||
Error,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
Executor, HasObservers,
|
||||
hooks::{
|
||||
inprocess::{InProcessHooks, GLOBAL_STATE},
|
||||
ExecutorHooksTuple,
|
||||
inprocess::{GLOBAL_STATE, InProcessHooks},
|
||||
},
|
||||
inprocess::HasInProcessHooks,
|
||||
Executor, HasObservers,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::Input,
|
||||
observers::ObserversTuple,
|
||||
state::{HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The internal state of `GenericInProcessExecutor`.
|
||||
|
@ -12,22 +12,22 @@ use core::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||
use libafl_bolts::tuples::{RefIndexable, tuple_list};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::{Corpus, Testcase},
|
||||
events::{Event, EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
|
||||
inprocess::inner::GenericInProcessExecutorInner,
|
||||
Executor, ExitKind, HasObservers,
|
||||
hooks::{ExecutorHooksTuple, inprocess::InProcessHooks},
|
||||
inprocess::inner::GenericInProcessExecutorInner,
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::Input,
|
||||
observers::ObserversTuple,
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// The inner structure of `InProcessExecutor`.
|
||||
@ -271,7 +271,6 @@ where
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
EM: EventFirer<I, S> + EventRestarter<S>,
|
||||
|
||||
OF: Feedback<EM, I, OT, S>,
|
||||
Z: HasObjective<Objective = OF>,
|
||||
{
|
||||
@ -440,6 +439,7 @@ mod tests {
|
||||
use libafl_bolts::{rands::XkcdRand, tuples::tuple_list};
|
||||
|
||||
use crate::{
|
||||
StdFuzzer,
|
||||
corpus::InMemoryCorpus,
|
||||
events::NopEventManager,
|
||||
executors::{Executor, ExitKind, InProcessExecutor},
|
||||
@ -447,7 +447,6 @@ mod tests {
|
||||
inputs::NopInput,
|
||||
schedulers::RandScheduler,
|
||||
state::{NopState, StdState},
|
||||
StdFuzzer,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -8,21 +8,21 @@ use core::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use libafl_bolts::tuples::{tuple_list, RefIndexable};
|
||||
use libafl_bolts::tuples::{RefIndexable, tuple_list};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
events::{EventFirer, EventRestarter},
|
||||
executors::{
|
||||
hooks::{inprocess::InProcessHooks, ExecutorHooksTuple},
|
||||
inprocess::{GenericInProcessExecutorInner, HasInProcessHooks},
|
||||
Executor, ExitKind, HasObservers,
|
||||
hooks::{ExecutorHooksTuple, inprocess::InProcessHooks},
|
||||
inprocess::{GenericInProcessExecutorInner, HasInProcessHooks},
|
||||
},
|
||||
feedbacks::Feedback,
|
||||
fuzzer::HasObjective,
|
||||
inputs::Input,
|
||||
observers::ObserversTuple,
|
||||
state::{HasCurrentTestcase, HasExecutions, HasSolutions},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The process executor simply calls a target function, as mutable reference to a closure
|
||||
|
@ -3,32 +3,32 @@ use core::{
|
||||
fmt::{self, Debug, Formatter},
|
||||
marker::PhantomData,
|
||||
ptr::{self, null_mut, write_volatile},
|
||||
sync::atomic::{compiler_fence, Ordering},
|
||||
sync::atomic::{Ordering, compiler_fence},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
os::unix_signals::Signal,
|
||||
shmem::ShMemProvider,
|
||||
tuples::{tuple_list, Merge, RefIndexable},
|
||||
tuples::{Merge, RefIndexable, tuple_list},
|
||||
};
|
||||
use nix::{
|
||||
sys::wait::{waitpid, WaitStatus},
|
||||
sys::wait::{WaitStatus, waitpid},
|
||||
unistd::Pid,
|
||||
};
|
||||
|
||||
#[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::{
|
||||
Error,
|
||||
executors::{
|
||||
hooks::{
|
||||
inprocess_fork::{InChildProcessHooks, FORK_EXECUTOR_GLOBAL_DATA},
|
||||
ExecutorHooksTuple,
|
||||
},
|
||||
ExitKind, HasObservers,
|
||||
hooks::{
|
||||
ExecutorHooksTuple,
|
||||
inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InChildProcessHooks},
|
||||
},
|
||||
},
|
||||
observers::ObserversTuple,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Inner state of GenericInProcessExecutor-like structures.
|
||||
@ -117,6 +117,7 @@ where
|
||||
mgr: &mut EM,
|
||||
input: &I,
|
||||
) -> Result<(), Error> {
|
||||
unsafe {
|
||||
self.shmem_provider.post_fork(true)?;
|
||||
|
||||
self.enter_target(fuzzer, state, mgr, input);
|
||||
@ -144,6 +145,7 @@ where
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) unsafe fn post_run_target_child(
|
||||
&mut self,
|
||||
@ -152,6 +154,7 @@ where
|
||||
mgr: &mut EM,
|
||||
input: &I,
|
||||
) {
|
||||
unsafe {
|
||||
self.observers
|
||||
.post_exec_child_all(state, input, &ExitKind::Ok)
|
||||
.expect("Failed to run post_exec on observers");
|
||||
@ -161,6 +164,7 @@ where
|
||||
|
||||
libc::_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parent(&mut self, child: Pid) -> Result<ExitKind, Error> {
|
||||
// log::trace!("from parent {} child is {}", std::process::id(), child);
|
||||
|
@ -5,22 +5,22 @@ use core::{
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
os::unix_signals::{ucontext_t, Signal},
|
||||
os::unix_signals::{Signal, ucontext_t},
|
||||
shmem::ShMemProvider,
|
||||
tuples::{tuple_list, RefIndexable},
|
||||
tuples::{RefIndexable, tuple_list},
|
||||
};
|
||||
use libc::siginfo_t;
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
use nix::unistd::{ForkResult, fork};
|
||||
|
||||
use super::hooks::ExecutorHooksTuple;
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{
|
||||
hooks::inprocess_fork::InProcessForkExecutorGlobalData,
|
||||
inprocess_fork::inner::GenericInProcessForkExecutorInner, Executor, ExitKind, HasObservers,
|
||||
Executor, ExitKind, HasObservers, hooks::inprocess_fork::InProcessForkExecutorGlobalData,
|
||||
inprocess_fork::inner::GenericInProcessForkExecutorInner,
|
||||
},
|
||||
observers::ObserversTuple,
|
||||
state::HasExecutions,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The signature of the crash handler function
|
||||
@ -206,13 +206,13 @@ pub mod child_signal_handlers {
|
||||
use alloc::boxed::Box;
|
||||
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 crate::{
|
||||
executors::{
|
||||
hooks::inprocess_fork::{InProcessForkExecutorGlobalData, FORK_EXECUTOR_GLOBAL_DATA},
|
||||
ExitKind, HasObservers,
|
||||
hooks::inprocess_fork::{FORK_EXECUTOR_GLOBAL_DATA, InProcessForkExecutorGlobalData},
|
||||
},
|
||||
observers::ObserversTuple,
|
||||
};
|
||||
@ -259,6 +259,7 @@ pub mod child_signal_handlers {
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<I, S>,
|
||||
{
|
||||
unsafe {
|
||||
if data.is_valid() {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let mut observers = executor.observers_mut();
|
||||
@ -271,6 +272,7 @@ pub mod child_signal_handlers {
|
||||
|
||||
libc::_exit(128 + (_signal as i32));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
|
||||
@ -283,6 +285,7 @@ pub mod child_signal_handlers {
|
||||
E: HasObservers,
|
||||
E::Observers: ObserversTuple<I, S>,
|
||||
{
|
||||
unsafe {
|
||||
if data.is_valid() {
|
||||
let executor = data.executor_mut::<E>();
|
||||
let mut observers = executor.observers_mut();
|
||||
@ -294,6 +297,7 @@ pub mod child_signal_handlers {
|
||||
}
|
||||
libc::_exit(128 + (_signal as i32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -303,7 +307,7 @@ mod tests {
|
||||
use serial_test::serial;
|
||||
|
||||
use crate::{
|
||||
executors::{inprocess_fork::GenericInProcessForkExecutorInner, Executor, ExitKind},
|
||||
executors::{Executor, ExitKind, inprocess_fork::GenericInProcessForkExecutorInner},
|
||||
inputs::NopInput,
|
||||
};
|
||||
|
||||
|
@ -9,18 +9,18 @@ use core::{
|
||||
|
||||
use libafl_bolts::{
|
||||
shmem::ShMemProvider,
|
||||
tuples::{tuple_list, RefIndexable},
|
||||
tuples::{RefIndexable, tuple_list},
|
||||
};
|
||||
use nix::unistd::{fork, ForkResult};
|
||||
use nix::unistd::{ForkResult, fork};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{
|
||||
hooks::ExecutorHooksTuple, inprocess_fork::GenericInProcessForkExecutorInner, Executor,
|
||||
ExitKind, HasObservers,
|
||||
Executor, ExitKind, HasObservers, hooks::ExecutorHooksTuple,
|
||||
inprocess_fork::GenericInProcessForkExecutorInner,
|
||||
},
|
||||
observers::ObserversTuple,
|
||||
state::HasExecutions,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The `StatefulInProcessForkExecutor` with no user hooks
|
||||
|
@ -10,9 +10,9 @@ use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use super::HasTimeout;
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
observers::ObserversTuple,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A [`ShadowExecutor`] wraps an executor and a set of shadow observers
|
||||
|
@ -5,9 +5,9 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
use libafl_bolts::tuples::RefIndexable;
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
executors::{Executor, ExitKind, HasObservers},
|
||||
observers::ObserversTuple,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A wrapper for any [`Executor`] to make it implement [`HasObservers`] using a given [`ObserversTuple`].
|
||||
|
@ -3,14 +3,14 @@
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, MatchNameRef},
|
||||
Error, Named,
|
||||
tuples::{Handle, MatchNameRef},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
HasNamedMetadata,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
observers::{ObserversTuple, ValueObserver},
|
||||
HasNamedMetadata,
|
||||
};
|
||||
|
||||
/// This feedback returns `true` or `false` as the `is_interesting` value.
|
||||
|
@ -2,15 +2,15 @@
|
||||
use std::{borrow::Cow, cell::RefCell, fmt::Debug, rc::Rc};
|
||||
|
||||
use libafl_bolts::{Error, Named};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
|
||||
use crate::{
|
||||
HasMetadata,
|
||||
corpus::Testcase,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
stages::verify_timeouts::TimeoutsToVerify,
|
||||
state::HasCorpus,
|
||||
HasMetadata,
|
||||
};
|
||||
|
||||
/// A Feedback that captures all timeouts and stores them in State for re-evaluation later.
|
||||
|
@ -8,15 +8,15 @@ use alloc::borrow::Cow;
|
||||
use core::fmt::Debug;
|
||||
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::Testcase,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
observers::concolic::ConcolicObserver,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// The concolic feedback. It is used to attach concolic tracing metadata to the testcase.
|
||||
|
@ -5,9 +5,9 @@ use libafl_bolts::Named;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
corpus::Testcase,
|
||||
feedbacks::{Feedback, FeedbackFactory, StateInitializer},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Type which can generate a custom filename for a given input/state pair
|
||||
|
@ -4,17 +4,17 @@ use alloc::borrow::Cow;
|
||||
use core::fmt::{self, Debug, Formatter};
|
||||
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "track_hit_feedbacks")]
|
||||
use crate::feedbacks::premature_last_result_err;
|
||||
use crate::{
|
||||
Error,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, FeedbackFactory, StateInitializer},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The result of a differential test between two observers.
|
||||
@ -179,12 +179,12 @@ where
|
||||
mod tests {
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use libafl_bolts::{tuples::tuple_list, Named};
|
||||
use libafl_bolts::{Named, tuples::tuple_list};
|
||||
|
||||
use crate::{
|
||||
events::NopEventManager,
|
||||
executors::ExitKind,
|
||||
feedbacks::{differential::DiffResult, DiffFeedback, Feedback},
|
||||
feedbacks::{DiffFeedback, Feedback, differential::DiffResult},
|
||||
inputs::BytesInput,
|
||||
observers::Observer,
|
||||
state::NopState,
|
||||
|
@ -3,16 +3,16 @@ use core::{fmt::Debug, hash::Hash};
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Error, HasRefCnt, Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||
|
||||
use crate::{
|
||||
HasNamedMetadata,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
observers::ListObserver,
|
||||
HasNamedMetadata,
|
||||
};
|
||||
|
||||
/// The metadata to remember past observed value
|
||||
|
@ -12,22 +12,22 @@ use core::{
|
||||
#[rustversion::nightly]
|
||||
use libafl_bolts::AsSlice;
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
AsIter, HasRefCnt, Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
use num_traits::PrimInt;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||
|
||||
#[cfg(feature = "track_hit_feedbacks")]
|
||||
use crate::feedbacks::premature_last_result_err;
|
||||
use crate::{
|
||||
Error, HasMetadata, HasNamedMetadata,
|
||||
corpus::Testcase,
|
||||
events::{Event, EventFirer},
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
|
||||
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
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`].
|
||||
@ -103,11 +103,7 @@ where
|
||||
{
|
||||
#[inline]
|
||||
fn reduce(first: T, second: T) -> T {
|
||||
if first > second {
|
||||
first
|
||||
} else {
|
||||
second
|
||||
}
|
||||
if first > second { first } else { second }
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,11 +117,7 @@ where
|
||||
{
|
||||
#[inline]
|
||||
fn reduce(first: T, second: T) -> T {
|
||||
if first < second {
|
||||
first
|
||||
} else {
|
||||
second
|
||||
}
|
||||
if first < second { first } else { second }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
pub use concolic::ConcolicFeedback;
|
||||
pub use differential::DiffFeedback;
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
pub use list::*;
|
||||
pub use map::*;
|
||||
@ -25,7 +25,7 @@ pub use new_hash_feedback::NewHashFeedback;
|
||||
pub use new_hash_feedback::NewHashFeedbackMetadata;
|
||||
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")]
|
||||
pub mod capture_feedback;
|
||||
@ -1016,11 +1016,7 @@ impl ConstFeedback {
|
||||
|
||||
impl From<bool> for ConstFeedback {
|
||||
fn from(val: bool) -> Self {
|
||||
if val {
|
||||
Self::True
|
||||
} else {
|
||||
Self::False
|
||||
}
|
||||
if val { Self::True } else { Self::False }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ use libafl_bolts::Named;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
common::nautilus::grammartec::{chunkstore::ChunkStore, context::Context},
|
||||
corpus::{Corpus, Testcase},
|
||||
executors::ExitKind,
|
||||
@ -14,7 +15,6 @@ use crate::{
|
||||
generators::NautilusContext,
|
||||
inputs::NautilusInput,
|
||||
state::HasCorpus,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// Metadata for Nautilus grammar mutator chunks
|
||||
|
@ -5,18 +5,18 @@ use std::fmt::Debug;
|
||||
|
||||
use hashbrown::HashSet;
|
||||
use libafl_bolts::{
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Named,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "track_hit_feedbacks")]
|
||||
use crate::feedbacks::premature_last_result_err;
|
||||
use crate::{
|
||||
Error, HasNamedMetadata,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
|
||||
observers::ObserverWithHashField,
|
||||
Error, HasNamedMetadata,
|
||||
};
|
||||
|
||||
/// The prefix of the metadata names
|
||||
|
@ -3,17 +3,16 @@
|
||||
use alloc::{borrow::Cow, string::String};
|
||||
|
||||
use libafl_bolts::{
|
||||
impl_serdeany,
|
||||
Named, impl_serdeany,
|
||||
tuples::{Handle, Handled, MatchName, MatchNameRef},
|
||||
Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::Testcase,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
observers::{StdErrObserver, StdOutObserver},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// Metadata for [`StdOutToMetadataFeedback`].
|
||||
|
@ -3,15 +3,15 @@
|
||||
|
||||
use alloc::borrow::Cow;
|
||||
|
||||
use libafl_bolts::{impl_serdeany, Error, Named};
|
||||
use libafl_bolts::{Error, Named, impl_serdeany};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "track_hit_feedbacks")]
|
||||
use crate::feedbacks::premature_last_result_err;
|
||||
use crate::{
|
||||
HasMetadata,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
HasMetadata,
|
||||
};
|
||||
|
||||
/// Constant name of the [`TransferringMetadata`].
|
||||
|
@ -5,17 +5,16 @@ use core::hash::Hash;
|
||||
|
||||
use fastbloom::BloomFilter;
|
||||
use libafl_bolts::{
|
||||
impl_serdeany,
|
||||
Error, Named, impl_serdeany,
|
||||
tuples::{Handle, MatchNameRef},
|
||||
Error, Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
HasNamedMetadata,
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, StateInitializer},
|
||||
observers::{ObserversTuple, ValueObserver},
|
||||
HasNamedMetadata,
|
||||
};
|
||||
|
||||
impl_serdeany!(ValueBloomFeedbackMetadata);
|
||||
|
@ -8,11 +8,12 @@ use std::hash::Hash;
|
||||
#[cfg(feature = "std")]
|
||||
use fastbloom::BloomFilter;
|
||||
use libafl_bolts::{current_time, tuples::MatchName};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase},
|
||||
events::{
|
||||
CanSerializeObserver, Event, EventConfig, EventFirer, EventReceiver, ProgressReporter,
|
||||
@ -30,7 +31,6 @@ use crate::{
|
||||
HasCorpus, HasCurrentStageId, HasCurrentTestcase, HasExecutions, HasImported,
|
||||
HasLastFoundTime, HasLastReportTime, HasSolutions, MaybeHasClientPerfMonitor, Stoppable,
|
||||
},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// 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)
|
||||
.unwrap();
|
||||
let input = BytesInput::new(vec![1, 2, 3]);
|
||||
assert!(fuzzer
|
||||
assert!(
|
||||
fuzzer
|
||||
.evaluate_input(&mut state, &mut executor, &mut manager, &input)
|
||||
.is_ok());
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(1, *execution_count.borrow()); // evaluate_input does not add it to the filter
|
||||
|
||||
assert!(fuzzer
|
||||
assert!(
|
||||
fuzzer
|
||||
.evaluate_filtered(&mut state, &mut executor, &mut manager, &input)
|
||||
.is_ok());
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(2, *execution_count.borrow()); // at to the filter
|
||||
|
||||
assert!(fuzzer
|
||||
assert!(
|
||||
fuzzer
|
||||
.evaluate_filtered(&mut state, &mut executor, &mut manager, &input)
|
||||
.is_ok());
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(2, *execution_count.borrow()); // the harness is not called
|
||||
|
||||
assert!(fuzzer
|
||||
assert!(
|
||||
fuzzer
|
||||
.evaluate_input(&mut state, &mut executor, &mut manager, &input)
|
||||
.is_ok());
|
||||
.is_ok()
|
||||
);
|
||||
assert_eq!(3, *execution_count.borrow()); // evaluate_input ignores filters
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ use libafl_bolts::rands::Rand;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
generators::Generator,
|
||||
inputs::{GramatronInput, Terminal},
|
||||
state::HasRand,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// A trigger
|
||||
|
@ -5,7 +5,7 @@ use core::{marker::PhantomData, num::NonZeroUsize};
|
||||
|
||||
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;
|
||||
use core::cmp::max;
|
||||
@ -44,16 +44,16 @@ where
|
||||
/// An [`Iterator`] built from a [`Generator`].
|
||||
#[derive(Debug)]
|
||||
pub struct GeneratorIter<'a, I, S, G> {
|
||||
gen: G,
|
||||
generator: G,
|
||||
state: &'a mut S,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<'a, I, S, G> GeneratorIter<'a, I, S, G> {
|
||||
/// 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 {
|
||||
gen,
|
||||
generator,
|
||||
state,
|
||||
phantom: PhantomData,
|
||||
}
|
||||
@ -67,7 +67,7 @@ where
|
||||
type Item = I;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.gen.generate(self.state).ok()
|
||||
self.generator.generate(self.state).ok()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,9 +10,8 @@ use libafl_bolts::rands::Rand;
|
||||
|
||||
pub use crate::common::nautilus::grammartec::newtypes::NTermId;
|
||||
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,
|
||||
Error,
|
||||
};
|
||||
|
||||
/// The nautilus context for a generator
|
||||
|
@ -8,7 +8,7 @@ use alloc::{
|
||||
};
|
||||
use core::cell::RefCell;
|
||||
|
||||
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
||||
use libafl_bolts::{HasLen, ownedref::OwnedSlice};
|
||||
|
||||
use super::ValueInput;
|
||||
use crate::inputs::{HasMutatorBytes, HasTargetBytes, ResizableMutator};
|
||||
|
@ -7,8 +7,8 @@ use core::{
|
||||
};
|
||||
|
||||
use libafl_bolts::{
|
||||
subrange::{end_index, start_index, sub_range},
|
||||
HasLen,
|
||||
subrange::{end_index, start_index, sub_range},
|
||||
};
|
||||
|
||||
use crate::inputs::{HasMutatorBytes, ResizableMutator};
|
||||
@ -24,7 +24,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator};
|
||||
/// # use alloc::vec::Vec;
|
||||
/// #
|
||||
/// # #[cfg(not(feature = "std"))]
|
||||
/// # #[no_mangle]
|
||||
/// # #[unsafe(no_mangle)]
|
||||
/// # pub extern "C" fn external_current_millis() -> u64 { 0 }
|
||||
///
|
||||
/// let mut bytes_input = BytesInput::new(vec![1, 2, 3]);
|
||||
@ -49,7 +49,7 @@ use crate::inputs::{HasMutatorBytes, ResizableMutator};
|
||||
/// # use alloc::vec::Vec;
|
||||
/// #
|
||||
/// # #[cfg(not(feature = "std"))]
|
||||
/// # #[no_mangle]
|
||||
/// # #[unsafe(no_mangle)]
|
||||
/// # pub extern "C" fn external_current_millis() -> u64 { 0 }
|
||||
///
|
||||
/// let mut bytes_input = BytesInput::new(vec![1, 2, 3, 4, 5]);
|
||||
@ -215,7 +215,7 @@ mod tests {
|
||||
|
||||
use crate::{
|
||||
inputs::{BytesInput, HasMutatorBytes, NopInput, ResizableMutator},
|
||||
mutators::{havoc_mutations_no_crossover, MutatorsTuple},
|
||||
mutators::{MutatorsTuple, havoc_mutations_no_crossover},
|
||||
state::NopState,
|
||||
};
|
||||
|
||||
|
@ -6,10 +6,10 @@ use libafl_bolts::impl_serdeany;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::Testcase,
|
||||
inputs::BytesInput,
|
||||
stages::mutational::{MutatedTransform, MutatedTransformPost},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
/// An item of the generalized input
|
||||
|
@ -13,9 +13,9 @@ use core::num::NonZero;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use libafl_bolts::{
|
||||
Error, Named,
|
||||
rands::Rand as _,
|
||||
tuples::{Map, MappingFunctor},
|
||||
Error, Named,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
@ -326,7 +326,7 @@ mod tests {
|
||||
use super::ListInput;
|
||||
use crate::{
|
||||
inputs::ValueInput,
|
||||
mutators::{numeric::IncMutator, MutationResult, MutatorsTuple as _},
|
||||
mutators::{MutationResult, MutatorsTuple as _, numeric::IncMutator},
|
||||
state::NopState,
|
||||
};
|
||||
|
||||
|
@ -48,10 +48,9 @@ use std::{fs::File, io::Read, path::Path};
|
||||
#[cfg(feature = "std")]
|
||||
use libafl_bolts::fs::write_file_atomic;
|
||||
use libafl_bolts::{
|
||||
generic_hash_std,
|
||||
Error, HasLen, generic_hash_std,
|
||||
ownedref::{OwnedMutSlice, OwnedSlice},
|
||||
subrange::{SubRangeMutSlice, SubRangeSlice},
|
||||
Error, HasLen,
|
||||
};
|
||||
#[cfg(feature = "nautilus")]
|
||||
pub use nautilus::*;
|
||||
|
@ -3,7 +3,7 @@
|
||||
use alloc::{fmt::Debug, string::String, vec::Vec};
|
||||
use core::hash::Hash;
|
||||
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use serde::{Serialize, de::DeserializeOwned};
|
||||
|
||||
use crate::{
|
||||
corpus::CorpusId,
|
||||
|
@ -3,11 +3,12 @@ use alloc::{rc::Rc, vec::Vec};
|
||||
use core::cell::RefCell;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
|
||||
use libafl_bolts::{HasLen, ownedref::OwnedSlice};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::TargetBytesConverter;
|
||||
use crate::{
|
||||
Error,
|
||||
common::nautilus::grammartec::{
|
||||
newtypes::NodeId,
|
||||
rule::RuleIdOrCustom,
|
||||
@ -15,7 +16,6 @@ use crate::{
|
||||
},
|
||||
generators::nautilus::NautilusContext,
|
||||
inputs::{BytesInput, Input, InputConverter},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// An [`Input`] implementation for `Nautilus` grammar.
|
||||
|
@ -8,7 +8,7 @@ use libafl_bolts::rands::Rand;
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "std")]
|
||||
use {
|
||||
libafl_bolts::{fs::write_file_atomic, Error},
|
||||
libafl_bolts::{Error, fs::write_file_atomic},
|
||||
std::{fs::File, io::Read, path::Path},
|
||||
};
|
||||
|
||||
|
@ -81,7 +81,7 @@ pub mod stages;
|
||||
pub mod state;
|
||||
|
||||
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.
|
||||
#[cfg(feature = "prelude")]
|
||||
@ -96,7 +96,7 @@ pub mod prelude {
|
||||
|
||||
#[cfg(all(any(doctest, test), not(feature = "std")))]
|
||||
/// Provide custom time in `no_std` tests.
|
||||
#[no_mangle]
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn external_current_millis() -> u64 {
|
||||
// TODO: use "real" time here
|
||||
1000
|
||||
@ -116,6 +116,7 @@ mod tests {
|
||||
#[cfg(miri)]
|
||||
use crate::stages::ExecutionCountRestartHelperMetadata;
|
||||
use crate::{
|
||||
StdFuzzer,
|
||||
corpus::{Corpus, InMemoryCorpus, Testcase},
|
||||
events::NopEventManager,
|
||||
executors::{ExitKind, InProcessExecutor},
|
||||
@ -123,11 +124,10 @@ mod tests {
|
||||
fuzzer::Fuzzer,
|
||||
inputs::BytesInput,
|
||||
monitors::SimpleMonitor,
|
||||
mutators::{mutations::BitFlipMutator, StdScheduledMutator},
|
||||
mutators::{StdScheduledMutator, mutations::BitFlipMutator},
|
||||
schedulers::RandScheduler,
|
||||
stages::StdMutationalStage,
|
||||
state::{HasCorpus, StdState},
|
||||
StdFuzzer,
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -8,10 +8,10 @@ use std::{
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use libafl_bolts::{current_time, ClientId};
|
||||
use libafl_bolts::{ClientId, current_time};
|
||||
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.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -6,10 +6,10 @@ use core::{
|
||||
};
|
||||
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 crate::monitors::{stats::ClientStatsManager, Monitor};
|
||||
use crate::monitors::{Monitor, stats::ClientStatsManager};
|
||||
|
||||
/// A monitor that logs aggregated stats to a JSON file.
|
||||
#[derive(Clone)]
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
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
|
||||
#[derive(Debug)]
|
||||
|
@ -297,7 +297,7 @@ mod test {
|
||||
use libafl_bolts::ClientId;
|
||||
use tuple_list::tuple_list;
|
||||
|
||||
use super::{stats::ClientStatsManager, Monitor, NopMonitor, SimpleMonitor};
|
||||
use super::{Monitor, NopMonitor, SimpleMonitor, stats::ClientStatsManager};
|
||||
|
||||
#[test]
|
||||
fn test_monitor_tuple_list() {
|
||||
|
@ -6,9 +6,9 @@ use core::{
|
||||
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.
|
||||
#[derive(Clone)]
|
||||
|
@ -31,16 +31,16 @@ use alloc::{borrow::Cow, fmt::Debug, string::String};
|
||||
use core::{fmt, fmt::Write, time::Duration};
|
||||
use std::{
|
||||
string::ToString,
|
||||
sync::{atomic::AtomicU64, Arc},
|
||||
sync::{Arc, atomic::AtomicU64},
|
||||
thread,
|
||||
};
|
||||
|
||||
// using thread in order to start the HTTP server in a separate thread
|
||||
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
|
||||
use prometheus_client::{
|
||||
encoding::{text::encode, EncodeLabelSet},
|
||||
encoding::{EncodeLabelSet, text::encode},
|
||||
metrics::{family::Family, gauge::Gauge},
|
||||
registry::Registry,
|
||||
};
|
||||
@ -48,8 +48,8 @@ use prometheus_client::{
|
||||
use tide::Request;
|
||||
|
||||
use crate::monitors::{
|
||||
stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
|
||||
Monitor,
|
||||
stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
|
||||
};
|
||||
|
||||
/// Prometheus metrics for global and each client.
|
||||
|
@ -6,15 +6,15 @@ use alloc::{borrow::Cow, string::String, vec::Vec};
|
||||
use core::time::Duration;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{current_time, format_duration_hms, ClientId};
|
||||
use libafl_bolts::{ClientId, current_time, format_duration_hms};
|
||||
#[cfg(feature = "std")]
|
||||
use serde_json::Value;
|
||||
|
||||
use super::{user_stats::UserStatsValue, ClientStats, EdgeCoverage, ProcessTiming};
|
||||
use super::{ClientStats, EdgeCoverage, ProcessTiming, user_stats::UserStatsValue};
|
||||
#[cfg(feature = "std")]
|
||||
use super::{
|
||||
user_stats::{AggregatorOps, UserStats},
|
||||
ItemGeometry,
|
||||
user_stats::{AggregatorOps, UserStats},
|
||||
};
|
||||
|
||||
/// Manager of all client's statistics
|
||||
|
@ -17,8 +17,8 @@ use cadence::{BufferedUdpMetricSink, Gauged, QueuingMetricSink, StatsdClient};
|
||||
use libafl_bolts::ClientId;
|
||||
|
||||
use super::{
|
||||
stats::{manager::GlobalStats, ClientStatsManager, EdgeCoverage, ItemGeometry},
|
||||
Monitor,
|
||||
stats::{ClientStatsManager, EdgeCoverage, ItemGeometry, manager::GlobalStats},
|
||||
};
|
||||
|
||||
const METRIC_PREFIX: &str = "fuzzing";
|
||||
|
@ -19,21 +19,21 @@ use crossterm::{
|
||||
cursor::{EnableBlinking, Show},
|
||||
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{current_time, format_duration_hms, ClientId};
|
||||
use ratatui::{backend::CrosstermBackend, Terminal};
|
||||
use libafl_bolts::{ClientId, current_time, format_duration_hms};
|
||||
use ratatui::{Terminal, backend::CrosstermBackend};
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature};
|
||||
use crate::monitors::{
|
||||
stats::{
|
||||
manager::ClientStatsManager, user_stats::UserStats, ClientStats, EdgeCoverage,
|
||||
ItemGeometry, ProcessTiming,
|
||||
},
|
||||
Monitor,
|
||||
stats::{
|
||||
ClientStats, EdgeCoverage, ItemGeometry, ProcessTiming, manager::ClientStatsManager,
|
||||
user_stats::UserStats,
|
||||
},
|
||||
};
|
||||
|
||||
#[expect(missing_docs)]
|
||||
@ -568,7 +568,9 @@ fn run_tui_thread<W: Write + Send + Sync + 'static>(
|
||||
)?;
|
||||
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();
|
||||
io::stdin().lock().read_line(&mut line)?;
|
||||
|
@ -6,6 +6,7 @@ use std::{
|
||||
};
|
||||
|
||||
use ratatui::{
|
||||
Frame,
|
||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Modifier, Style},
|
||||
symbols,
|
||||
@ -13,12 +14,11 @@ use ratatui::{
|
||||
widgets::{
|
||||
Axis, Block, Borders, Cell, Chart, Dataset, List, ListItem, Paragraph, Row, Table, Tabs,
|
||||
},
|
||||
Frame,
|
||||
};
|
||||
|
||||
use super::{
|
||||
current_time, format_duration_hms, Duration, ItemGeometry, ProcessTiming, String, TimedStats,
|
||||
TuiContext,
|
||||
Duration, ItemGeometry, ProcessTiming, String, TimedStats, TuiContext, current_time,
|
||||
format_duration_hms,
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
@ -368,7 +368,8 @@ impl TuiUi {
|
||||
|
||||
//log::trace!("max_x: {}, len: {}", max_x, self.graph_data.len());
|
||||
|
||||
let datasets = vec![Dataset::default()
|
||||
let datasets = vec![
|
||||
Dataset::default()
|
||||
//.name("data")
|
||||
.marker(if self.enhanced_graphics {
|
||||
symbols::Marker::Braille
|
||||
@ -380,7 +381,8 @@ impl TuiUi {
|
||||
.fg(Color::LightYellow)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)
|
||||
.data(&self.graph_data)];
|
||||
.data(&self.graph_data),
|
||||
];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(
|
||||
Block::default()
|
||||
|
@ -11,15 +11,15 @@ use libafl_bolts::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
corpus::Corpus,
|
||||
inputs::EncodedInput,
|
||||
mutators::{
|
||||
mutations::{buffer_copy, buffer_self_copy, ARITH_MAX},
|
||||
MutationResult, Mutator, Named,
|
||||
mutations::{ARITH_MAX, buffer_copy, buffer_self_copy},
|
||||
},
|
||||
nonzero, random_corpus_id_with_disabled,
|
||||
state::{HasCorpus, HasMaxSize, HasRand},
|
||||
Error,
|
||||
};
|
||||
|
||||
/// Set a code in the input as a random value
|
||||
|
@ -6,19 +6,19 @@ use core::{cmp::max, num::NonZero};
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::{
|
||||
rands::{choose, Rand},
|
||||
Named,
|
||||
rands::{Rand, choose},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error, HasMetadata,
|
||||
corpus::Corpus,
|
||||
generators::GramatronGenerator,
|
||||
inputs::{GramatronInput, Terminal},
|
||||
mutators::{MutationResult, Mutator},
|
||||
nonzero, random_corpus_id,
|
||||
state::{HasCorpus, HasRand},
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
const RECUR_THRESHOLD: usize = 5;
|
||||
@ -201,17 +201,20 @@ where
|
||||
self.states.clear();
|
||||
for i in 0..input.terminals().len() {
|
||||
let s = input.terminals()[i].state;
|
||||
if let Some(entry) = self.counters.get_mut(&s) {
|
||||
match self.counters.get_mut(&s) {
|
||||
Some(entry) => {
|
||||
if entry.0 == 1 {
|
||||
// Keep track only of states with more than one node
|
||||
self.states.push(s);
|
||||
}
|
||||
entry.0 += 1;
|
||||
entry.2 = max(entry.2, i);
|
||||
} else {
|
||||
}
|
||||
_ => {
|
||||
self.counters.insert(s, (1, i, i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.states.is_empty() {
|
||||
return Ok(MutationResult::Skipped);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user