Rust 2024 edition (#3022)

* Rust 2024 edition

* gen = generalized

* Fixes

* more fix

* More fix

* even more fix

* fix libfuzzer

* ignore clippy lint

* even more

* fix docs?

* more?

* More pub more better

* win

* docs

* more

* More

* doc stuff?

* counter_maps->counters_maps

* libafl qemu fixes for rust 2024

* fix?

* fmt

* unsafe lint

* final fixes

* fmt

* working?

* not working

* unused import

* win?

* update libafl qemu hash

* fmt

* fix

* unused imports

* fix

* fix

* more foix

* less edition

* fix

---------

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

View File

@ -223,6 +223,7 @@ jobs:
steps:
- 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
View File

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

View File

@ -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]

View File

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

View File

@ -32,7 +32,9 @@ As you can see from the forkserver example,
//Coverage map shared between observer and executor
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();
```

View File

@ -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]

View File

@ -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()

View File

@ -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() };

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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.

View File

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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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;

View File

@ -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 {

View File

@ -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};

View File

@ -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,

View File

@ -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::{

View File

@ -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)]

View File

@ -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

View File

@ -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,
}
}

View File

@ -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.

View File

@ -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`.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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> {

View File

@ -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,
};

View File

@ -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

View File

@ -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 {

View File

@ -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> {

View File

@ -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);

View File

@ -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(());

View File

@ -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);

View File

@ -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::{

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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},

View File

@ -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),
},
}
}
}

View File

@ -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(

View File

@ -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.

View File

@ -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.

View File

@ -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,

View File

@ -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));
}
}
}

View File

@ -1,18 +1,18 @@
/// Same as `inproc_crash_handler`, but this is called when address sanitizer exits, not from the exception handler
/// In-Process crash handling for `Windows`
#[cfg(all(windows, feature = "std"))]
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!");
}
}

View File

@ -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`.

View File

@ -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]

View File

@ -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

View File

@ -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);

View File

@ -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,
};

View File

@ -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

View File

@ -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

View File

@ -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`].

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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 }
}
}

View File

@ -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 }
}
}

View File

@ -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

View File

@ -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

View File

@ -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`].

View File

@ -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`].

View File

@ -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);

View File

@ -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
}
}

View File

@ -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

View File

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

View File

@ -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

View File

@ -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};

View File

@ -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,
};

View File

@ -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

View File

@ -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,
};

View File

@ -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::*;

View File

@ -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,

View File

@ -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.

View File

@ -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},
};

View File

@ -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]

View File

@ -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)]

View File

@ -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)]

View File

@ -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)]

View File

@ -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() {

View File

@ -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)]

View File

@ -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.

View File

@ -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

View File

@ -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";

View File

@ -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)?;

View File

@ -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()

View File

@ -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

View File

@ -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