Make corpus and solution not mutually exclusive (#3029)

* make fuzzer great again

* crash handlers

* hello from windows

* fk

* gee

* m

* temporary fix

* f

* mm

* CICI

* fixer

* Fix Dockerfile

* lol

* clp

* Fuck you clippy

* This lint makes no sense, 0

* ??

* a

* fix

* this lint makes 0 sense

* mm

* clp

* a

* a

* clp

* clippy

* clp

* mm

* FMT

* p

---------

Co-authored-by: Your Name <you@example.com>
Co-authored-by: toka <toka@tokas-MacBook-Air.local>
This commit is contained in:
Dongjia "toka" Zhang 2025-03-05 20:10:04 +01:00 committed by GitHub
parent 89342b22c2
commit 977ff10a0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 398 additions and 521 deletions

View File

@ -156,8 +156,8 @@ std_instead_of_core = "deny"
cargo = { level = "warn", priority = -1 } cargo = { level = "warn", priority = -1 }
# Allow # Allow
negative_feature_names = "allow" # TODO: turn into 'warn' when working negative_feature_names = "allow" # TODO: turn into 'warn' when working
multiple_crate_versions = "allow" # TODO: turn into `warn` when working multiple_crate_versions = "allow" # TODO: turn into `warn` when working
unreadable_literal = "allow" unreadable_literal = "allow"
type_repetition_in_bounds = "allow" type_repetition_in_bounds = "allow"
missing_errors_doc = "allow" missing_errors_doc = "allow"
@ -169,8 +169,8 @@ module_name_repetitions = "allow"
unsafe_derive_deserialize = "allow" unsafe_derive_deserialize = "allow"
similar_names = "allow" similar_names = "allow"
too_many_lines = "allow" too_many_lines = "allow"
comparison_chain = "allow" # This lint makes **ZERO** sense comparison_chain = "allow" # This lint makes **ZERO** sense
unnecessary_debug_formatting = "allow" # :thumbsdown: :thumbsdown: :thumbsdown: :thumbsdown: :thumbsdown: :thumbsdown:
[workspace.lints.rustdoc] [workspace.lints.rustdoc]
# Deny # Deny

View File

@ -68,28 +68,33 @@ RUN set -ex &&\
chmod +x llvm.sh &&\ chmod +x llvm.sh &&\
./llvm.sh ${LLVM_VERSION} ./llvm.sh ${LLVM_VERSION}
RUN apt-get update && \
apt-get install -y \
clang-format-${LLVM_VERSION}
RUN git config --global core.pager cat RUN git config --global core.pager cat
# Install a modern version of QEMU # Install a modern version of QEMU
WORKDIR /root WORKDIR /root
ENV QEMU_VER=9.2.1 ENV QEMU_VER=9.2.1
RUN wget https://download.qemu.org/qemu-${QEMU_VER}.tar.xz RUN wget https://download.qemu.org/qemu-${QEMU_VER}.tar.xz && \
RUN tar xvJf qemu-${QEMU_VER}.tar.xz tar xvJf qemu-${QEMU_VER}.tar.xz && \
WORKDIR /root/qemu-${QEMU_VER} cd /root/qemu-${QEMU_VER} && \
RUN ./configure --target-list="\ ./configure --target-list="\
arm-linux-user,\ arm-linux-user,\
aarch64-linux-user,\ aarch64-linux-user,\
i386-linux-user,\ i386-linux-user,\
ppc-linux-user,\ ppc-linux-user,\
mips-linux-user,\ mips-linux-user,\
arm-softmmu,\ arm-softmmu,\
aarch64-softmmu,\ aarch64-softmmu,\
i386-softmmu,\ i386-softmmu,\
ppc-softmmu,\ ppc-softmmu,\
mips-softmmu" mips-softmmu" && \
RUN make -j make -j && \
RUN make install make install && \
cd /root && \
rm -rf qemu-${QEMU_VER}
# Copy a dummy.rs and Cargo.toml first, so that dependencies are cached # Copy a dummy.rs and Cargo.toml first, so that dependencies are cached
WORKDIR /libafl WORKDIR /libafl

View File

@ -146,12 +146,10 @@ pub fn check_autoresume(fuzzer_dir: &Path, auto_resume: bool) -> Result<Flock<Fi
pub fn create_dir_if_not_exists(path: &Path) -> io::Result<()> { pub fn create_dir_if_not_exists(path: &Path) -> io::Result<()> {
if path.is_file() { if path.is_file() {
return Err(io::Error::new( return Err(io::Error::other(format!(
// TODO: change this to ErrorKind::NotADirectory "{} expected a directory; got a file",
// when stabilitzed https://github.com/rust-lang/rust/issues/86442 path.display()
io::ErrorKind::Other, )));
format!("{} expected a directory; got a file", path.display()),
));
} }
match std::fs::create_dir(path) { match std::fs::create_dir(path) {
Ok(()) => Ok(()), Ok(()) => Ok(()),

View File

@ -100,12 +100,6 @@ where
Ok(()) Ok(())
} }
/// Discard the stored metadata in case that the testcase is not added to the corpus
#[inline]
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.inner.discard_metadata(state, input)?;
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> { fn last_result(&self) -> Result<bool, Error> {
self.inner.last_result() self.inner.last_result()

View File

@ -345,16 +345,6 @@ fn fuzz(
let mut tracing_harness = harness; let mut tracing_harness = harness;
let ctx_hook = CtxHook::new(); let ctx_hook = CtxHook::new();
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = HookableInProcessExecutor::with_timeout_generic(
tuple_list!(ctx_hook),
&mut harness,
tuple_list!(edges_observer, time_observer),
&mut fuzzer,
&mut state,
&mut mgr,
timeout,
)?;
// Setup a tracing stage in which we log comparisons // Setup a tracing stage in which we log comparisons
let tracing = TracingStage::new( let tracing = TracingStage::new(
@ -369,6 +359,17 @@ fn fuzz(
// Give it more time! // Give it more time!
); );
// Create the executor for an in-process function with one observer for edge coverage and one for the execution time
let mut executor = HookableInProcessExecutor::with_timeout_generic(
tuple_list!(ctx_hook),
&mut harness,
tuple_list!(edges_observer, time_observer),
&mut fuzzer,
&mut state,
&mut mgr,
timeout,
)?;
// The order of the stages matter! // The order of the stages matter!
let mut stages = tuple_list!(calibration, tracing, i2s, power); let mut stages = tuple_list!(calibration, tracing, i2s, power);

View File

@ -274,7 +274,7 @@ where
// Spawn clients // Spawn clients
let mut index = 0_usize; let mut index = 0_usize;
for bind_to in core_ids { for bind_to in core_ids {
if self.cores.ids.iter().any(|&x| x == bind_to) { if self.cores.ids.contains(&bind_to) {
for overcommit_id in 0..self.overcommit { for overcommit_id in 0..self.overcommit {
index += 1; index += 1;
self.shmem_provider.pre_fork()?; self.shmem_provider.pre_fork()?;
@ -456,7 +456,7 @@ where
//spawn clients //spawn clients
let mut index = 0; let mut index = 0;
for core_id in core_ids { for core_id in core_ids {
if self.cores.ids.iter().any(|&x| x == core_id) { if self.cores.ids.contains(&core_id) {
for overcommit_i in 0..self.overcommit { for overcommit_i in 0..self.overcommit {
index += 1; index += 1;
// Forward own stdio to child processes, if requested by user // Forward own stdio to child processes, if requested by user
@ -748,7 +748,7 @@ where
// Spawn clients // Spawn clients
let mut index = 0_usize; let mut index = 0_usize;
for bind_to in core_ids { for bind_to in core_ids {
if self.cores.ids.iter().any(|&x| x == bind_to) { if self.cores.ids.contains(&bind_to) {
for overcommit_id in 0..self.overcommit { for overcommit_id in 0..self.overcommit {
index += 1; index += 1;
self.shmem_provider.pre_fork()?; self.shmem_provider.pre_fork()?;

View File

@ -24,7 +24,7 @@ use windows::Win32::System::Threading::{CRITICAL_SECTION, PTP_TIMER};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use crate::executors::hooks::timer::TimerStruct; use crate::executors::hooks::timer::TimerStruct;
use crate::{ use crate::{
Error, HasObjective, Error, HasFeedback, HasObjective,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{Executor, HasObservers, hooks::ExecutorHook, inprocess::HasInProcessHooks}, executors::{Executor, HasObservers, hooks::ExecutorHook, inprocess::HasInProcessHooks},
feedbacks::Feedback, feedbacks::Feedback,
@ -202,7 +202,7 @@ impl<I, S> ExecutorHook<I, S> for InProcessHooks<I, S> {
// Imagine there are two executors, you have to set the correct crash handlers for each of the executor. // Imagine there are two executors, you have to set the correct crash handlers for each of the executor.
unsafe { unsafe {
let data = &raw mut GLOBAL_STATE; let data = &raw mut GLOBAL_STATE;
assert!((*data).crash_handler == null()); assert!((*data).crash_handler.is_null());
// usually timeout handler and crash handler is set together // usually timeout handler and crash handler is set together
// so no check for timeout handler is null or not // so no check for timeout handler is null or not
(*data).crash_handler = self.crash_handler; (*data).crash_handler = self.crash_handler;
@ -232,14 +232,15 @@ impl<I, S> InProcessHooks<I, S> {
/// Create new [`InProcessHooks`]. /// Create new [`InProcessHooks`].
#[cfg(unix)] #[cfg(unix)]
#[allow(unused_variables)] // for `exec_tmout` without `std` #[allow(unused_variables)] // for `exec_tmout` without `std`
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error> pub fn new<E, EM, F, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
where where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>, E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
// # Safety // # Safety
@ -249,7 +250,7 @@ impl<I, S> InProcessHooks<I, S> {
#[cfg(all(not(miri), unix, feature = "std"))] #[cfg(all(not(miri), unix, feature = "std"))]
let data = unsafe { &raw mut GLOBAL_STATE }; let data = unsafe { &raw mut GLOBAL_STATE };
#[cfg(feature = "std")] #[cfg(feature = "std")]
unix_signal_handler::setup_panic_hook::<E, EM, I, OF, S, Z>(); unix_signal_handler::setup_panic_hook::<E, EM, F, I, OF, S, Z>();
// # Safety // # Safety
// Setting up the signal handlers with a pointer to the `GLOBAL_STATE` which should not be NULL at this point. // Setting up the signal handlers with a pointer to the `GLOBAL_STATE` which should not be NULL at this point.
// We are the sole users of `GLOBAL_STATE` right now, and only dereference it in case of Segfault/Panic. // We are the sole users of `GLOBAL_STATE` right now, and only dereference it in case of Segfault/Panic.
@ -262,10 +263,10 @@ impl<I, S> InProcessHooks<I, S> {
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
Ok(Self { Ok(Self {
#[cfg(feature = "std")] #[cfg(feature = "std")]
crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, I, OF, S, Z> crash_handler: unix_signal_handler::inproc_crash_handler::<E, EM, F, I, OF, S, Z>
as *const c_void, as *const c_void,
#[cfg(feature = "std")] #[cfg(feature = "std")]
timeout_handler: unix_signal_handler::inproc_timeout_handler::<E, EM, I, OF, S, Z> timeout_handler: unix_signal_handler::inproc_timeout_handler::<E, EM, F, I, OF, S, Z>
as *const _, as *const _,
#[cfg(feature = "std")] #[cfg(feature = "std")]
timer: TimerStruct::new(exec_tmout), timer: TimerStruct::new(exec_tmout),
@ -276,15 +277,16 @@ impl<I, S> InProcessHooks<I, S> {
/// Create new [`InProcessHooks`]. /// Create new [`InProcessHooks`].
#[cfg(windows)] #[cfg(windows)]
#[allow(unused_variables)] // for `exec_tmout` without `std` #[allow(unused_variables)] // for `exec_tmout` without `std`
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error> pub fn new<E, EM, F, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
where where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>, E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let ret; let ret;
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -293,6 +295,7 @@ impl<I, S> InProcessHooks<I, S> {
crate::executors::hooks::windows::windows_exception_handler::setup_panic_hook::< crate::executors::hooks::windows::windows_exception_handler::setup_panic_hook::<
E, E,
EM, EM,
F,
I, I,
OF, OF,
S, S,
@ -304,6 +307,7 @@ impl<I, S> InProcessHooks<I, S> {
crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::< crate::executors::hooks::windows::windows_exception_handler::inproc_crash_handler::<
E, E,
EM, EM,
F,
I, I,
OF, OF,
S, S,
@ -313,6 +317,7 @@ impl<I, S> InProcessHooks<I, S> {
crate::executors::hooks::windows::windows_exception_handler::inproc_timeout_handler::< crate::executors::hooks::windows::windows_exception_handler::inproc_timeout_handler::<
E, E,
EM, EM,
F,
I, I,
OF, OF,
S, S,
@ -339,13 +344,14 @@ impl<I, S> InProcessHooks<I, S> {
/// Create a new [`InProcessHooks`] /// Create a new [`InProcessHooks`]
#[cfg(all(not(unix), not(windows)))] #[cfg(all(not(unix), not(windows)))]
#[expect(unused_variables)] #[expect(unused_variables)]
pub fn new<E, EM, OF, Z>(exec_tmout: Duration) -> Result<Self, Error> pub fn new<E, EM, F, OF, Z>(exec_tmout: Duration) -> Result<Self, Error>
where where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>, E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I>, S: HasExecutions + HasSolutions<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
#[cfg_attr(miri, allow(unused_variables))] #[cfg_attr(miri, allow(unused_variables))]
let ret = Self { let ret = Self {
@ -472,7 +478,7 @@ impl InProcessExecutorHandlerData {
/// ///
/// Should only be called to signal a crash in the target /// Should only be called to signal a crash in the target
#[cfg(all(unix, feature = "std"))] #[cfg(all(unix, feature = "std"))]
pub unsafe fn maybe_report_crash<E, EM, I, OF, S, Z>( pub unsafe fn maybe_report_crash<E, EM, F, I, OF, S, Z>(
&mut self, &mut self,
bsod_info: Option<BsodInfo>, bsod_info: Option<BsodInfo>,
) -> bool ) -> bool
@ -480,9 +486,10 @@ impl InProcessExecutorHandlerData {
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
unsafe { unsafe {
@ -510,7 +517,7 @@ impl InProcessExecutorHandlerData {
} }
} }
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,

View File

@ -178,7 +178,7 @@ impl TimerStruct {
pub unsafe fn new(exec_tmout: Duration, timeout_handler: *const c_void) -> Self { pub unsafe fn new(exec_tmout: Duration, timeout_handler: *const c_void) -> Self {
let milli_sec = exec_tmout.as_millis() as i64; let milli_sec = exec_tmout.as_millis() as i64;
let timeout_handler: PTP_TIMER_CALLBACK = unsafe { std::mem::transmute(timeout_handler) }; let timeout_handler: PTP_TIMER_CALLBACK = unsafe { core::mem::transmute(timeout_handler) };
let ptp_timer = unsafe { let ptp_timer = unsafe {
CreateThreadpoolTimer( CreateThreadpoolTimer(
Some(timeout_handler), Some(timeout_handler),

View File

@ -12,6 +12,7 @@ pub mod unix_signal_handler {
use libc::siginfo_t; use libc::siginfo_t;
use crate::{ use crate::{
HasFeedback,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, ExitKind, HasObservers, common_signals, Executor, ExitKind, HasObservers, common_signals,
@ -86,14 +87,15 @@ pub mod unix_signal_handler {
} }
/// invokes the `post_exec` hook on all observer in case of panic /// invokes the `post_exec` hook on all observer in case of panic
pub fn setup_panic_hook<E, EM, I, OF, S, Z>() pub fn setup_panic_hook<E, EM, F, I, OF, S, Z>()
where where
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
@ -117,7 +119,7 @@ pub mod unix_signal_handler {
let fuzzer = (*data).fuzzer_mut::<Z>(); let fuzzer = (*data).fuzzer_mut::<Z>();
let event_mgr = (*data).event_mgr_mut::<EM>(); let event_mgr = (*data).event_mgr_mut::<EM>();
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -140,7 +142,7 @@ pub mod unix_signal_handler {
/// Well, signal handling is not safe /// Well, signal handling is not safe
#[cfg(unix)] #[cfg(unix)]
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
pub unsafe fn inproc_timeout_handler<E, EM, I, OF, S, Z>( pub unsafe fn inproc_timeout_handler<E, EM, F, I, OF, S, Z>(
_signal: Signal, _signal: Signal,
_info: &mut siginfo_t, _info: &mut siginfo_t,
_context: Option<&mut ucontext_t>, _context: Option<&mut ucontext_t>,
@ -149,9 +151,10 @@ pub mod unix_signal_handler {
E: HasInProcessHooks<I, S> + HasObservers, E: HasInProcessHooks<I, S> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
unsafe { unsafe {
@ -178,7 +181,7 @@ pub mod unix_signal_handler {
log::error!("Timeout in fuzz run."); log::error!("Timeout in fuzz run.");
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -198,7 +201,7 @@ pub mod unix_signal_handler {
/// # Safety /// # Safety
/// Well, signal handling is not safe /// Well, signal handling is not safe
#[allow(clippy::needless_pass_by_value)] // nightly no longer requires this #[allow(clippy::needless_pass_by_value)] // nightly no longer requires this
pub unsafe fn inproc_crash_handler<E, EM, I, OF, S, Z>( pub unsafe fn inproc_crash_handler<E, EM, F, I, OF, S, Z>(
signal: Signal, signal: Signal,
_info: &mut siginfo_t, _info: &mut siginfo_t,
_context: Option<&mut ucontext_t>, _context: Option<&mut ucontext_t>,
@ -207,9 +210,10 @@ pub mod unix_signal_handler {
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
unsafe { unsafe {
@ -251,7 +255,7 @@ pub mod unix_signal_handler {
} }
} }
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,

View File

@ -9,6 +9,7 @@ pub mod windows_asan_handler {
}; };
use crate::{ use crate::{
HasFeedback,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, ExitKind, HasObservers, hooks::inprocess::GLOBAL_STATE, Executor, ExitKind, HasObservers, hooks::inprocess::GLOBAL_STATE,
@ -23,15 +24,16 @@ pub mod windows_asan_handler {
/// # Safety /// # Safety
/// ASAN deatch handler /// ASAN deatch handler
pub unsafe extern "C" fn asan_death_handler<E, EM, I, OF, S, Z>() pub unsafe extern "C" fn asan_death_handler<E, EM, F, I, OF, S, Z>()
where where
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
unsafe { unsafe {
let data = &raw mut GLOBAL_STATE; let data = &raw mut GLOBAL_STATE;
@ -94,7 +96,7 @@ pub mod windows_asan_handler {
// Make sure we don't crash in the crash handler forever. // Make sure we don't crash in the crash handler forever.
let input = (*data).take_current_input::<I>(); let input = (*data).take_current_input::<I>();
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -137,6 +139,7 @@ pub mod windows_exception_handler {
}; };
use crate::{ use crate::{
HasFeedback,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
@ -197,15 +200,16 @@ pub mod windows_exception_handler {
/// # Safety /// # Safety
/// Well, exception handling is not safe /// Well, exception handling is not safe
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub fn setup_panic_hook<E, EM, I, OF, S, Z>() pub fn setup_panic_hook<E, EM, F, I, OF, S, Z>()
where where
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let old_hook = panic::take_hook(); let old_hook = panic::take_hook();
panic::set_hook(Box::new(move |panic_info| unsafe { panic::set_hook(Box::new(move |panic_info| unsafe {
@ -242,7 +246,7 @@ pub mod windows_exception_handler {
let input = (*data).take_current_input::<I>(); let input = (*data).take_current_input::<I>();
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -262,7 +266,7 @@ pub mod windows_exception_handler {
/// ///
/// # Safety /// # Safety
/// Well, exception handling is not safe /// Well, exception handling is not safe
pub unsafe extern "system" fn inproc_timeout_handler<E, EM, I, OF, S, Z>( pub unsafe extern "system" fn inproc_timeout_handler<E, EM, F, I, OF, S, Z>(
_p0: *mut u8, _p0: *mut u8,
global_state: *mut c_void, global_state: *mut c_void,
_p1: *mut u8, _p1: *mut u8,
@ -271,9 +275,10 @@ pub mod windows_exception_handler {
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let data: &mut InProcessExecutorHandlerData = let data: &mut InProcessExecutorHandlerData =
unsafe { &mut *(global_state as *mut InProcessExecutorHandlerData) }; unsafe { &mut *(global_state as *mut InProcessExecutorHandlerData) };
@ -313,7 +318,7 @@ pub mod windows_exception_handler {
let input = unsafe { (data.current_input_ptr as *const I).as_ref().unwrap() }; let input = unsafe { (data.current_input_ptr as *const I).as_ref().unwrap() };
data.current_input_ptr = ptr::null_mut(); data.current_input_ptr = ptr::null_mut();
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -341,7 +346,7 @@ pub mod windows_exception_handler {
/// ///
/// # Safety /// # Safety
/// Well, exception handling is not safe /// Well, exception handling is not safe
pub unsafe fn inproc_crash_handler<E, EM, I, OF, S, Z>( pub unsafe fn inproc_crash_handler<E, EM, F, I, OF, S, Z>(
exception_pointers: *mut EXCEPTION_POINTERS, exception_pointers: *mut EXCEPTION_POINTERS,
data: &mut InProcessExecutorHandlerData, data: &mut InProcessExecutorHandlerData,
) where ) where
@ -349,9 +354,10 @@ pub mod windows_exception_handler {
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
// Have we set a timer_before? // Have we set a timer_before?
if data.ptp_timer.is_some() { if data.ptp_timer.is_some() {
@ -456,7 +462,7 @@ pub mod windows_exception_handler {
log::warn!("Running observers and exiting!"); log::warn!("Running observers and exiting!");
// // I want to disable the hooks before doing anything, especially before taking a stack dump // // I want to disable the hooks before doing anything, especially before taking a stack dump
let input = unsafe { data.take_current_input::<I>() }; let input = unsafe { data.take_current_input::<I>() };
run_observers_and_save_state::<E, EM, I, OF, S, Z>( run_observers_and_save_state::<E, EM, F, I, OF, S, Z>(
executor, executor,
state, state,
input, input,
@ -473,7 +479,7 @@ pub mod windows_exception_handler {
.unwrap(); .unwrap();
writer.flush().unwrap(); writer.flush().unwrap();
} }
log::error!("{}", std::str::from_utf8(&bsod).unwrap()); log::error!("{}", core::str::from_utf8(&bsod).unwrap());
} }
} else { } else {
// This is not worth saving // This is not worth saving

View File

@ -16,7 +16,7 @@ use crate::executors::hooks::inprocess::HasTimeout;
#[cfg(all(windows, feature = "std"))] #[cfg(all(windows, feature = "std"))]
use crate::executors::hooks::inprocess::HasTimeout; use crate::executors::hooks::inprocess::HasTimeout;
use crate::{ use crate::{
Error, Error, HasFeedback,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, HasObservers, Executor, HasObservers,
@ -132,7 +132,7 @@ where
S: HasExecutions + HasSolutions<I>, S: HasExecutions + HasSolutions<I>,
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn generic<E, OF>( pub fn generic<E, F, OF>(
user_hooks: HT, user_hooks: HT,
observers: OT, observers: OT,
fuzzer: &mut Z, fuzzer: &mut Z,
@ -144,11 +144,12 @@ where
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase<I> + HasSolutions<I>, S: HasCurrentTestcase<I> + HasSolutions<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
Self::with_timeout_generic::<E, OF>( Self::with_timeout_generic::<E, F, OF>(
user_hooks, user_hooks,
observers, observers,
fuzzer, fuzzer,
@ -160,7 +161,7 @@ where
/// Create a new in mem executor with the default timeout and use batch mode(5 sec) /// Create a new in mem executor with the default timeout and use batch mode(5 sec)
#[cfg(all(feature = "std", target_os = "linux"))] #[cfg(all(feature = "std", target_os = "linux"))]
pub fn batched_timeout_generic<E, OF>( pub fn batched_timeout_generic<E, F, OF>(
user_hooks: HT, user_hooks: HT,
observers: OT, observers: OT,
fuzzer: &mut Z, fuzzer: &mut Z,
@ -173,11 +174,12 @@ where
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
I: Input + Clone, I: Input + Clone,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase<I> + HasSolutions<I>, S: HasCurrentTestcase<I> + HasSolutions<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let mut me = Self::with_timeout_generic::<E, OF>( let mut me = Self::with_timeout_generic::<E, F, OF>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
)?; )?;
me.hooks_mut().0.timer_mut().batch_mode = true; me.hooks_mut().0.timer_mut().batch_mode = true;
@ -192,7 +194,7 @@ where
/// * `observers` - the observers observing the target during execution /// * `observers` - the observers observing the target during execution
/// ///
/// This may return an error on unix, if signal handler setup fails /// This may return an error on unix, if signal handler setup fails
pub fn with_timeout_generic<E, OF>( pub fn with_timeout_generic<E, F, OF>(
user_hooks: HT, user_hooks: HT,
observers: OT, observers: OT,
_fuzzer: &mut Z, _fuzzer: &mut Z,
@ -204,12 +206,13 @@ where
E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>, E: Executor<EM, I, S, Z> + HasObservers + HasInProcessHooks<I, S>,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasCurrentTestcase<I> + HasSolutions<I>, S: HasCurrentTestcase<I> + HasSolutions<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
let default = InProcessHooks::new::<E, EM, OF, Z>(timeout)?; let default = InProcessHooks::new::<E, EM, F, OF, Z>(timeout)?;
let mut hooks = tuple_list!(default).merge(user_hooks); let mut hooks = tuple_list!(default).merge(user_hooks);
hooks.init_all(state); hooks.init_all(state);

View File

@ -15,7 +15,7 @@ use core::{
use libafl_bolts::tuples::{RefIndexable, tuple_list}; use libafl_bolts::tuples::{RefIndexable, tuple_list};
use crate::{ use crate::{
Error, HasMetadata, Error, HasFeedback, HasMetadata,
corpus::{Corpus, Testcase}, corpus::{Corpus, Testcase},
events::{Event, EventFirer, EventRestarter}, events::{Event, EventFirer, EventRestarter},
executors::{ executors::{
@ -132,7 +132,7 @@ where
I: Input, I: Input,
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn new<OF>( pub fn new<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
observers: OT, observers: OT,
fuzzer: &mut Z, fuzzer: &mut Z,
@ -141,10 +141,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
Self::with_timeout_generic::<OF>( Self::with_timeout_generic::<F, OF>(
tuple_list!(), tuple_list!(),
harness_fn, harness_fn,
observers, observers,
@ -157,7 +158,7 @@ where
/// Create a new in mem executor with the default timeout and use batch mode(5 sec) /// Create a new in mem executor with the default timeout and use batch mode(5 sec)
#[cfg(all(feature = "std", target_os = "linux"))] #[cfg(all(feature = "std", target_os = "linux"))]
pub fn batched_timeout<OF>( pub fn batched_timeout<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
observers: OT, observers: OT,
fuzzer: &mut Z, fuzzer: &mut Z,
@ -167,10 +168,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, F, OF>(
tuple_list!(), tuple_list!(),
observers, observers,
fuzzer, fuzzer,
@ -194,7 +196,7 @@ where
/// * `observers` - the observers observing the target during execution /// * `observers` - the observers observing the target during execution
/// ///
/// This may return an error on unix, if signal handler setup fails /// This may return an error on unix, if signal handler setup fails
pub fn with_timeout<OF>( pub fn with_timeout<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
observers: OT, observers: OT,
fuzzer: &mut Z, fuzzer: &mut Z,
@ -204,10 +206,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, F, OF>(
tuple_list!(), tuple_list!(),
observers, observers,
fuzzer, fuzzer,
@ -234,7 +237,7 @@ where
I: Input, I: Input,
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn generic<OF>( pub fn generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
observers: OT, observers: OT,
@ -244,10 +247,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
Self::with_timeout_generic::<OF>( Self::with_timeout_generic::<F, OF>(
user_hooks, user_hooks,
harness_fn, harness_fn,
observers, observers,
@ -260,7 +264,7 @@ where
/// Create a new in mem executor with the default timeout and use batch mode(5 sec) /// Create a new in mem executor with the default timeout and use batch mode(5 sec)
#[cfg(all(feature = "std", target_os = "linux"))] #[cfg(all(feature = "std", target_os = "linux"))]
pub fn batched_timeout_generic<OF>( pub fn batched_timeout_generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
observers: OT, observers: OT,
@ -271,10 +275,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, F, OF>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
)?; )?;
@ -293,7 +298,7 @@ where
/// * `observers` - the observers observing the target during execution /// * `observers` - the observers observing the target during execution
/// ///
/// This may return an error on unix, if signal handler setup fails /// This may return an error on unix, if signal handler setup fails
pub fn with_timeout_generic<OF>( pub fn with_timeout_generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
observers: OT, observers: OT,
@ -304,10 +309,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, F, OF>(
user_hooks, observers, fuzzer, state, event_mgr, timeout, user_hooks, observers, fuzzer, state, event_mgr, timeout,
)?; )?;
@ -370,7 +376,7 @@ impl<EM, H, HB, HT, I, OT, S, Z> HasInProcessHooks<I, S>
#[inline] #[inline]
/// Save state if it is an objective /// Save state if it is an objective
pub fn run_observers_and_save_state<E, EM, I, OF, S, Z>( pub fn run_observers_and_save_state<E, EM, F, I, OF, S, Z>(
executor: &mut E, executor: &mut E,
state: &mut S, state: &mut S,
input: &I, input: &I,
@ -382,8 +388,9 @@ pub fn run_observers_and_save_state<E, EM, I, OF, S, Z>(
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
F: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
let mut observers = executor.observers_mut(); let mut observers = executor.observers_mut();
@ -392,12 +399,17 @@ pub fn run_observers_and_save_state<E, EM, I, OF, S, Z>(
.post_exec_all(state, input, &exitkind) .post_exec_all(state, input, &exitkind)
.expect("Observers post_exec_all failed"); .expect("Observers post_exec_all failed");
let interesting = fuzzer let _is_corpus = fuzzer
.feedback_mut()
.is_interesting(state, event_mgr, input, &*observers, &exitkind)
.expect("In run_observers_and_save_state feedback failure");
let is_solution = fuzzer
.objective_mut() .objective_mut()
.is_interesting(state, event_mgr, input, &*observers, &exitkind) .is_interesting(state, event_mgr, input, &*observers, &exitkind)
.expect("In run_observers_and_save_state objective failure."); .expect("In run_observers_and_save_state objective failure.");
if interesting { if is_solution {
let mut new_testcase = Testcase::from(input.clone()); let mut new_testcase = Testcase::from(input.clone());
new_testcase.add_metadata(exitkind); new_testcase.add_metadata(exitkind);
new_testcase.set_parent_id_optional(*state.corpus().current()); new_testcase.set_parent_id_optional(*state.corpus().current());

View File

@ -11,7 +11,7 @@ use core::{
use libafl_bolts::tuples::{RefIndexable, tuple_list}; use libafl_bolts::tuples::{RefIndexable, tuple_list};
use crate::{ use crate::{
Error, Error, HasFeedback,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{ executors::{
Executor, ExitKind, HasObservers, Executor, ExitKind, HasObservers,
@ -131,7 +131,7 @@ where
I: Clone + Input, I: Clone + Input,
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn new<OF>( pub fn new<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
exposed_executor_state: ES, exposed_executor_state: ES,
observers: OT, observers: OT,
@ -141,8 +141,9 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
Self::with_timeout_generic( Self::with_timeout_generic(
tuple_list!(), tuple_list!(),
@ -158,7 +159,7 @@ where
/// Create a new in mem executor with the default timeout and use batch mode(5 sec) /// Create a new in mem executor with the default timeout and use batch mode(5 sec)
#[cfg(all(feature = "std", target_os = "linux"))] #[cfg(all(feature = "std", target_os = "linux"))]
pub fn batched_timeout<OF>( pub fn batched_timeout<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
exposed_executor_state: ES, exposed_executor_state: ES,
observers: OT, observers: OT,
@ -169,10 +170,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, F, OF>(
tuple_list!(), tuple_list!(),
observers, observers,
fuzzer, fuzzer,
@ -197,7 +199,7 @@ where
/// * `observers` - the observers observing the target during execution /// * `observers` - the observers observing the target during execution
/// ///
/// This may return an error on unix, if signal handler setup fails /// This may return an error on unix, if signal handler setup fails
pub fn with_timeout<OF>( pub fn with_timeout<F, OF>(
harness_fn: &'a mut H, harness_fn: &'a mut H,
exposed_executor_state: ES, exposed_executor_state: ES,
observers: OT, observers: OT,
@ -208,10 +210,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, F, OF>(
tuple_list!(), tuple_list!(),
observers, observers,
fuzzer, fuzzer,
@ -254,7 +257,7 @@ where
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
{ {
/// Create a new in mem executor with the default timeout (5 sec) /// Create a new in mem executor with the default timeout (5 sec)
pub fn generic<OF>( pub fn generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
exposed_executor_state: ES, exposed_executor_state: ES,
@ -265,8 +268,9 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
Self::with_timeout_generic( Self::with_timeout_generic(
user_hooks, user_hooks,
@ -283,7 +287,7 @@ where
/// Create a new in mem executor with the default timeout and use batch mode(5 sec) /// Create a new in mem executor with the default timeout and use batch mode(5 sec)
#[cfg(all(feature = "std", target_os = "linux"))] #[cfg(all(feature = "std", target_os = "linux"))]
#[expect(clippy::too_many_arguments)] #[expect(clippy::too_many_arguments)]
pub fn batched_timeout_generic<OF>( pub fn batched_timeout_generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
exposed_executor_state: ES, exposed_executor_state: ES,
@ -295,10 +299,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::batched_timeout_generic::<Self, F, OF>(
user_hooks, observers, fuzzer, state, event_mgr, exec_tmout, user_hooks, observers, fuzzer, state, event_mgr, exec_tmout,
)?; )?;
@ -319,7 +324,7 @@ where
/// ///
/// This may return an error on unix, if signal handler setup fails /// This may return an error on unix, if signal handler setup fails
#[expect(clippy::too_many_arguments)] #[expect(clippy::too_many_arguments)]
pub fn with_timeout_generic<OF>( pub fn with_timeout_generic<F, OF>(
user_hooks: HT, user_hooks: HT,
harness_fn: HB, harness_fn: HB,
exposed_executor_state: ES, exposed_executor_state: ES,
@ -331,10 +336,11 @@ where
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, OF>( let inner = GenericInProcessExecutorInner::with_timeout_generic::<Self, F, OF>(
user_hooks, observers, fuzzer, state, event_mgr, timeout, user_hooks, observers, fuzzer, state, event_mgr, timeout,
)?; )?;

View File

@ -91,10 +91,6 @@ where
Ok(()) Ok(())
} }
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> { fn last_result(&self) -> Result<bool, Error> {
self.last_result.ok_or_else(|| Error::illegal_state("No last result set in `BoolValuefeedback`. Either `is_interesting` has never been called or the fuzzer restarted in the meantime.")) self.last_result.ok_or_else(|| Error::illegal_state("No last result set in `BoolValuefeedback`. Either `is_interesting` has never been called or the fuzzer restarted in the meantime."))

View File

@ -148,12 +148,6 @@ pub trait Feedback<EM, I, OT, S>: StateInitializer<S> + Named {
) -> Result<(), Error> { ) -> Result<(), Error> {
Ok(()) Ok(())
} }
/// Discard the stored metadata in case that the testcase is not added to the corpus
#[inline]
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
Ok(())
}
} }
/// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`) /// Has an associated observer name (mostly used to retrieve the observer with `MatchName` from an `ObserverTuple`)
@ -306,12 +300,6 @@ where
self.second self.second
.append_metadata(state, manager, observers, testcase) .append_metadata(state, manager, observers, testcase)
} }
#[inline]
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.first.discard_metadata(state, input)?;
self.second.discard_metadata(state, input)
}
} }
impl<A, B, FL, T> FeedbackFactory<CombinedFeedback<A, B, FL>, T> for CombinedFeedback<A, B, FL> impl<A, B, FL, T> FeedbackFactory<CombinedFeedback<A, B, FL>, T> for CombinedFeedback<A, B, FL>
@ -670,11 +658,6 @@ where
self.inner self.inner
.append_metadata(state, manager, observers, testcase) .append_metadata(state, manager, observers, testcase)
} }
#[inline]
fn discard_metadata(&mut self, state: &mut S, input: &I) -> Result<(), Error> {
self.inner.discard_metadata(state, input)
}
} }
impl<A> Named for NotFeedback<A> { impl<A> Named for NotFeedback<A> {

View File

@ -115,9 +115,6 @@ where
self.append_nautilus_metadata_to_state(state, testcase) self.append_nautilus_metadata_to_state(state, testcase)
} }
fn discard_metadata(&mut self, _state: &mut S, _input: &NautilusInput) -> Result<(), Error> {
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> { fn last_result(&self) -> Result<bool, Error> {
Ok(false) Ok(false)

View File

@ -188,7 +188,7 @@ pub trait Evaluator<E, EM, I, S> {
executor: &mut E, executor: &mut E,
manager: &mut EM, manager: &mut EM,
input: I, input: I,
) -> Result<CorpusId, Error>; ) -> Result<(CorpusId, ExecuteInputResult), Error>;
/// Adds the input to the corpus as a disabled input. /// Adds the input to the corpus as a disabled input.
/// Used during initial corpus loading. /// Used during initial corpus loading.
@ -246,14 +246,43 @@ pub trait Fuzzer<E, EM, I, S, ST> {
} }
/// The corpus this input should be added to /// The corpus this input should be added to
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Default)]
pub enum ExecuteInputResult { pub struct ExecuteInputResult {
/// No special input is_corpus: bool,
None, is_solution: bool,
/// This input should be stored in the corpus }
Corpus,
/// This input leads to a solution impl ExecuteInputResult {
Solution, /// Constructor
#[must_use]
pub fn new(is_corpus: bool, is_solution: bool) -> Self {
Self {
is_corpus,
is_solution,
}
}
/// if this is corpus worthy
#[must_use]
pub fn is_corpus(&self) -> bool {
self.is_corpus
}
/// if this is solution worthy
#[must_use]
pub fn is_solution(&self) -> bool {
self.is_solution
}
/// tell that this is corpus
pub fn set_is_corpus(&mut self, v: bool) {
self.is_corpus = v;
}
/// tell that this is solution
pub fn set_is_solution(&mut self, v: bool) {
self.is_solution = v;
}
} }
/// Your default fuzzer instance, for everyday use. /// Your default fuzzer instance, for everyday use.
@ -326,7 +355,7 @@ where
observers: &OT, observers: &OT,
exit_kind: &ExitKind, exit_kind: &ExitKind,
) -> Result<ExecuteInputResult, Error> { ) -> Result<ExecuteInputResult, Error> {
let mut res = ExecuteInputResult::None; let mut res = ExecuteInputResult::default();
#[cfg(not(feature = "introspection"))] #[cfg(not(feature = "introspection"))]
let is_solution = self let is_solution = self
@ -339,26 +368,27 @@ where
.is_interesting_introspection(state, manager, input, observers, exit_kind)?; .is_interesting_introspection(state, manager, input, observers, exit_kind)?;
if is_solution { if is_solution {
res = ExecuteInputResult::Solution; res.set_is_solution(true);
} else {
#[cfg(not(feature = "introspection"))]
let corpus_worthy = self
.feedback_mut()
.is_interesting(state, manager, input, observers, exit_kind)?;
#[cfg(feature = "introspection")]
let corpus_worthy = self
.feedback_mut()
.is_interesting_introspection(state, manager, input, observers, exit_kind)?;
if corpus_worthy {
res = ExecuteInputResult::Corpus;
}
} }
#[cfg(not(feature = "introspection"))]
let corpus_worthy = self
.feedback_mut()
.is_interesting(state, manager, input, observers, exit_kind)?;
#[cfg(feature = "introspection")]
let corpus_worthy = self
.feedback_mut()
.is_interesting_introspection(state, manager, input, observers, exit_kind)?;
if corpus_worthy {
res.set_is_corpus(true);
}
Ok(res) Ok(res)
} }
/// Evaluate if a set of observation channels has an interesting state /// Post process a testcase depending the testcase execution results
/// returns corpus id if it put something into corpus (not solution)
fn process_execution( fn process_execution(
&mut self, &mut self,
state: &mut S, state: &mut S,
@ -367,48 +397,36 @@ where
exec_res: &ExecuteInputResult, exec_res: &ExecuteInputResult,
observers: &OT, observers: &OT,
) -> Result<Option<CorpusId>, Error> { ) -> Result<Option<CorpusId>, Error> {
match exec_res { let corpus = if exec_res.is_corpus() {
ExecuteInputResult::None => { // Add the input to the main corpus
self.feedback_mut().discard_metadata(state, input)?; let mut testcase = Testcase::from(input.clone());
self.objective_mut().discard_metadata(state, input)?; #[cfg(feature = "track_hit_feedbacks")]
Ok(None) self.feedback_mut()
} .append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
ExecuteInputResult::Corpus => { self.feedback_mut()
// Not a solution .append_metadata(state, manager, observers, &mut testcase)?;
self.objective_mut().discard_metadata(state, input)?; let id = state.corpus_mut().add(testcase)?;
self.scheduler_mut().on_add(state, id)?;
// Add the input to the main corpus Ok(Some(id))
let mut testcase = Testcase::from(input.clone()); } else {
#[cfg(feature = "track_hit_feedbacks")] Ok(None)
self.feedback_mut() };
.append_hit_feedbacks(testcase.hit_feedbacks_mut())?;
self.feedback_mut() if exec_res.is_solution() {
.append_metadata(state, manager, observers, &mut testcase)?; // The input is a solution, add it to the respective corpus
let id = state.corpus_mut().add(testcase)?; let mut testcase = Testcase::from(input.clone());
self.scheduler_mut().on_add(state, id)?; testcase.set_parent_id_optional(*state.corpus().current());
if let Ok(mut tc) = state.current_testcase_mut() {
Ok(Some(id)) tc.found_objective();
}
ExecuteInputResult::Solution => {
// Not interesting
self.feedback_mut().discard_metadata(state, input)?;
// The input is a solution, add it to the respective corpus
let mut testcase = Testcase::from(input.clone());
testcase.set_parent_id_optional(*state.corpus().current());
if let Ok(mut tc) = state.current_testcase_mut() {
tc.found_objective();
}
#[cfg(feature = "track_hit_feedbacks")]
self.objective_mut()
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
self.objective_mut()
.append_metadata(state, manager, observers, &mut testcase)?;
state.solutions_mut().add(testcase)?;
Ok(None)
} }
#[cfg(feature = "track_hit_feedbacks")]
self.objective_mut()
.append_hit_feedbacks(testcase.hit_objectives_mut())?;
self.objective_mut()
.append_metadata(state, manager, observers, &mut testcase)?;
state.solutions_mut().add(testcase)?;
} }
corpus
} }
fn serialize_and_dispatch( fn serialize_and_dispatch(
@ -421,20 +439,14 @@ where
exit_kind: &ExitKind, exit_kind: &ExitKind,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Now send off the event // Now send off the event
let observers_buf = match exec_res { let observers_buf = if exec_res.is_solution()
ExecuteInputResult::Corpus => { && manager.should_send()
if manager.should_send() { && manager.configuration() != EventConfig::AlwaysUnique
// TODO set None for fast targets {
if manager.configuration() == EventConfig::AlwaysUnique { // TODO set None for fast targets
None manager.serialize_observers(observers)?
} else { } else {
manager.serialize_observers(observers)? None
}
} else {
None
}
}
_ => None,
}; };
self.dispatch_event(state, manager, input, exec_res, observers_buf, exit_kind)?; self.dispatch_event(state, manager, input, exec_res, observers_buf, exit_kind)?;
@ -451,41 +463,38 @@ where
exit_kind: &ExitKind, exit_kind: &ExitKind,
) -> Result<(), Error> { ) -> Result<(), Error> {
// Now send off the event // Now send off the event
match exec_res { if manager.should_send() {
ExecuteInputResult::Corpus => { if exec_res.is_corpus() {
if manager.should_send() { manager.fire(
manager.fire( state,
state, Event::NewTestcase {
Event::NewTestcase { input: input.clone(),
input: input.clone(), observers_buf,
observers_buf, exit_kind: *exit_kind,
exit_kind: *exit_kind, corpus_size: state.corpus().count(),
corpus_size: state.corpus().count(), client_config: manager.configuration(),
client_config: manager.configuration(), time: current_time(),
time: current_time(), forward_id: None,
forward_id: None, #[cfg(all(unix, feature = "std", feature = "multi_machine"))]
#[cfg(all(unix, feature = "std", feature = "multi_machine"))] node_id: None,
node_id: None, },
}, )?;
)?;
}
} }
ExecuteInputResult::Solution => {
if manager.should_send() {
manager.fire(
state,
Event::Objective {
#[cfg(feature = "share_objectives")]
input: input.clone(),
objective_size: state.solutions().count(), if exec_res.is_solution() {
time: current_time(), manager.fire(
}, state,
)?; Event::Objective {
} #[cfg(feature = "share_objectives")]
input: input.clone(),
objective_size: state.solutions().count(),
time: current_time(),
},
)?;
} }
ExecuteInputResult::None => (),
} }
Ok(()) Ok(())
} }
@ -503,7 +512,7 @@ where
if send_events { if send_events {
self.serialize_and_dispatch(state, manager, input, &exec_res, observers, exit_kind)?; self.serialize_and_dispatch(state, manager, input, &exec_res, observers, exit_kind)?;
} }
if exec_res != ExecuteInputResult::None { if exec_res.is_corpus() || exec_res.is_solution() {
*state.last_found_time_mut() = current_time(); *state.last_found_time_mut() = current_time();
} }
Ok((exec_res, corpus_id)) Ok((exec_res, corpus_id))
@ -610,7 +619,7 @@ where
if self.input_filter.should_execute(input) { if self.input_filter.should_execute(input) {
self.evaluate_input(state, executor, manager, input) self.evaluate_input(state, executor, manager, input)
} else { } else {
Ok((ExecuteInputResult::None, None)) Ok((ExecuteInputResult::default(), None))
} }
} }
@ -633,7 +642,7 @@ where
executor: &mut E, executor: &mut E,
manager: &mut EM, manager: &mut EM,
input: I, input: I,
) -> Result<CorpusId, Error> { ) -> Result<(CorpusId, ExecuteInputResult), Error> {
*state.last_found_time_mut() = current_time(); *state.last_found_time_mut() = current_time();
let exit_kind = self.execute_input(state, executor, manager, &input)?; let exit_kind = self.execute_input(state, executor, manager, &input)?;
@ -662,33 +671,30 @@ where
.append_hit_feedbacks(testcase.hit_objectives_mut())?; .append_hit_feedbacks(testcase.hit_objectives_mut())?;
self.objective_mut() self.objective_mut()
.append_metadata(state, manager, &*observers, &mut testcase)?; .append_metadata(state, manager, &*observers, &mut testcase)?;
let id = state.solutions_mut().add(testcase)?; // we don't care about solution id
let _ = state.solutions_mut().add(testcase.clone())?;
manager.fire( manager.fire(
state, state,
Event::Objective { Event::Objective {
#[cfg(feature = "share_objectives")] #[cfg(feature = "share_objectives")]
input, input: input.clone(),
objective_size: state.solutions().count(), objective_size: state.solutions().count(),
time: current_time(), time: current_time(),
}, },
)?; )?;
return Ok(id);
} }
// Not a solution
self.objective_mut().discard_metadata(state, &input)?;
// several is_interesting implementations collect some data about the run, later used in // several is_interesting implementations collect some data about the run, later used in
// append_metadata; we *must* invoke is_interesting here to collect it // append_metadata; we *must* invoke is_interesting here to collect it
#[cfg(not(feature = "introspection"))] #[cfg(not(feature = "introspection"))]
let _corpus_worthy = let corpus_worthy =
self.feedback_mut() self.feedback_mut()
.is_interesting(state, manager, &input, &*observers, &exit_kind)?; .is_interesting(state, manager, &input, &*observers, &exit_kind)?;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
let _corpus_worthy = self.feedback_mut().is_interesting_introspection( let corpus_worthy = self.feedback_mut().is_interesting_introspection(
state, state,
manager, manager,
&input, &input,
@ -724,7 +730,7 @@ where
node_id: None, node_id: None,
}, },
)?; )?;
Ok(id) Ok((id, ExecuteInputResult::new(corpus_worthy, is_solution)))
} }
fn add_disabled_input(&mut self, state: &mut S, input: I) -> Result<CorpusId, Error> { fn add_disabled_input(&mut self, state: &mut S, input: I) -> Result<CorpusId, Error> {

View File

@ -14,12 +14,6 @@ pub mod stacktrace;
#[cfg(feature = "regex")] #[cfg(feature = "regex")]
pub use stacktrace::*; pub use stacktrace::*;
/// Profiler observer
#[cfg(feature = "std")]
pub mod profiling;
#[cfg(feature = "std")]
pub use profiling::*;
pub mod concolic; pub mod concolic;
pub mod map; pub mod map;
pub use map::*; pub use map::*;

View File

@ -1,146 +0,0 @@
use alloc::{borrow::Cow, string::String};
use std::{fs::File, io::BufReader, path::Path};
use hashbrown::HashMap;
use libafl_bolts::{Named, ownedref::OwnedMutPtr};
use serde::{Deserialize, Serialize};
use crate::{Error, observers::Observer};
#[derive(Debug, Serialize, Deserialize)]
/// The json data
pub struct FunctionData {
#[serde(rename = "name")]
name: String,
#[serde(rename = "# BBs")]
bb_count: Option<u32>,
#[serde(rename = "# insts")]
inst_count: Option<u32>,
#[serde(rename = "# edges")]
edge_count: Option<u32>,
#[serde(rename = "# binaryOp")]
binary_op_count: Option<u32>,
#[serde(rename = "# call")]
call_count: Option<u32>,
#[serde(rename = "# cmp")]
cmp_count: Option<u32>,
#[serde(rename = "# load")]
load_count: Option<u32>,
#[serde(rename = "# store")]
store_count: Option<u32>,
#[serde(rename = "# alloca")]
alloca_count: Option<u32>,
#[serde(rename = "# branch")]
branch_count: Option<u32>,
#[serde(rename = "ABC metric")]
abc_metric: Option<f64>,
cyclomatic: Option<u32>,
#[serde(rename = "AP")]
api_calls: Option<HashMap<String, u32>>,
#[serde(rename = "h AP")]
heap_apis: Option<HashMap<String, u32>>,
#[serde(rename = "m AP")]
memory_apis: Option<HashMap<String, u32>>,
#[serde(rename = "ne lv")]
nested_level: Option<HashMap<String, u32>>,
#[serde(rename = "cm gl")]
cmp_globals: Option<HashMap<String, u32>>,
#[serde(rename = "cm nz")]
cmp_non_zeros: Option<HashMap<String, u32>>,
#[serde(rename = "wr st")]
struct_writes: Option<HashMap<String, u32>>,
#[serde(rename = "str arg")]
struct_args: Option<HashMap<String, u32>>,
#[serde(rename = "cm ty")]
cmp_types: Option<HashMap<String, u32>>,
#[serde(rename = "cm cm")]
cmp_complexity: Option<HashMap<String, u32>>,
#[serde(rename = "ar ty")]
call_arg_types: Option<HashMap<String, u32>>,
#[serde(rename = "st ty")]
store_types: Option<HashMap<String, u32>>,
#[serde(rename = "l ty")]
load_types: Option<HashMap<String, u32>>,
#[serde(rename = "al ty")]
alloca_types: Option<HashMap<String, u32>>,
}
#[derive(Debug, Default, Serialize, Deserialize)]
struct AnalysisData {
data: HashMap<usize, FunctionData>,
}
/// The observer to lookup the static analysis data at runtime
#[derive(Debug, Serialize, Deserialize)]
pub struct ProfilingObserver {
/// The name of the observer.
pub name: Cow<'static, str>,
db: AnalysisData,
/// The map
map: OwnedMutPtr<HashMap<usize, usize>>,
}
impl ProfilingObserver {
/// The constructor
pub fn new<P>(json_path: P, map: OwnedMutPtr<HashMap<usize, usize>>) -> Result<Self, Error>
where
P: AsRef<Path>,
{
let f = File::open(json_path.as_ref())?;
let reader = BufReader::new(f);
let analysis_data: AnalysisData = serde_json::from_reader(reader).map_err(|err| {
let path = json_path.as_ref().to_string_lossy();
Error::illegal_argument(format!("Failed to read from path {path}: {err:?}"))
})?;
// debug
/*
for record in &analysis_data.data {
for (key, _value) in record.iter() {
log::info!("Record {} found!", key);
}
}
*/
Ok(Self {
name: Cow::from("profiling"),
db: analysis_data,
map,
})
}
/// Get the map
#[must_use]
pub fn map(&self) -> &HashMap<usize, usize> {
self.map.as_ref()
}
/// lookup the data through db
#[must_use]
pub fn lookup(&self, function_id: usize) -> Option<&FunctionData> {
let item = self.db.data.get(&function_id);
item
}
}
impl Named for ProfilingObserver {
fn name(&self) -> &Cow<'static, str> {
&self.name
}
}
impl<I, S> Observer<I, S> for ProfilingObserver {
fn post_exec(
&mut self,
_state: &mut S,
_input: &I,
_exit_kind: &crate::executors::ExitKind,
) -> Result<(), Error> {
// in reality, this should be done in a stage
// but here just for poc
for (key, _item) in self.map() {
let found = self.lookup(*key);
log::info!("key: {}, data: {:#?}", key, found);
}
log::info!("");
Ok(())
}
}

View File

@ -141,12 +141,11 @@ where
} }
let mut id = self.inner.base_mut().next(state)?; let mut id = self.inner.base_mut().next(state)?;
while { while {
let has = !state !state
.corpus() .corpus()
.get(id)? .get(id)?
.borrow() .borrow()
.has_metadata::<IsFavoredMetadata>(); .has_metadata::<IsFavoredMetadata>()
has
} && state.rand_mut().coinflip(self.skip_non_favored_prob) } && state.rand_mut().coinflip(self.skip_non_favored_prob)
{ {
id = self.inner.base_mut().next(state)?; id = self.inner.base_mut().next(state)?;

View File

@ -107,12 +107,10 @@ where
self.base.on_remove(state, id, testcase)?; self.base.on_remove(state, id, testcase)?;
let mut entries = let mut entries =
if let Some(meta) = state.metadata_map_mut().get_mut::<TopRatedsMetadata>() { if let Some(meta) = state.metadata_map_mut().get_mut::<TopRatedsMetadata>() {
let entries = meta meta.map
.map
.extract_if(|_, other_id| *other_id == id) .extract_if(|_, other_id| *other_id == id)
.map(|(entry, _)| entry) .map(|(entry, _)| entry)
.collect::<Vec<_>>(); .collect::<Vec<_>>()
entries
} else { } else {
return Ok(()); return Ok(());
}; };
@ -215,12 +213,11 @@ where
self.cull(state)?; self.cull(state)?;
let mut id = self.base.next(state)?; let mut id = self.base.next(state)?;
while { while {
let has = !state !state
.corpus() .corpus()
.get(id)? .get(id)?
.borrow() .borrow()
.has_metadata::<IsFavoredMetadata>(); .has_metadata::<IsFavoredMetadata>()
has
} && state.rand_mut().coinflip(self.skip_non_favored_prob) } && state.rand_mut().coinflip(self.skip_non_favored_prob)
{ {
id = self.base.next(state)?; id = self.base.next(state)?;

View File

@ -139,7 +139,7 @@ where
if !corpus_dir.is_dir() { if !corpus_dir.is_dir() {
return Err(Error::os_error( return Err(Error::os_error(
e, e,
format!("Error creating directory {corpus_dir:?}"), format!("Error creating directory {}", corpus_dir.display()),
)); ));
} }
} }
@ -148,7 +148,7 @@ where
if !solutions_dir.is_dir() { if !solutions_dir.is_dir() {
return Err(Error::os_error( return Err(Error::os_error(
e, e,
format!("Error creating directory {solutions_dir:?}"), format!("Error creating directory {}", solutions_dir.display()),
)); ));
} }
} }

View File

@ -26,6 +26,8 @@ use serde::{Deserialize, Serialize, de::DeserializeOwned};
mod stack; mod stack;
pub use stack::StageStack; pub use stack::StageStack;
#[cfg(feature = "std")]
use crate::fuzzer::ExecuteInputResult;
#[cfg(feature = "introspection")] #[cfg(feature = "introspection")]
use crate::monitors::stats::ClientPerfStats; use crate::monitors::stats::ClientPerfStats;
use crate::{ use crate::{
@ -33,7 +35,7 @@ use crate::{
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase}, corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase},
events::{Event, EventFirer, LogSeverity}, events::{Event, EventFirer, LogSeverity},
feedbacks::StateInitializer, feedbacks::StateInitializer,
fuzzer::{Evaluator, ExecuteInputResult}, fuzzer::Evaluator,
generators::Generator, generators::Generator,
inputs::{Input, NopInput}, inputs::{Input, NopInput},
stages::StageId, stages::StageId,
@ -715,15 +717,15 @@ where
Ok(input) => input, Ok(input) => input,
Err(err) => { Err(err) => {
log::error!("Skipping input that we could not load from {path:?}: {err:?}"); log::error!("Skipping input that we could not load from {path:?}: {err:?}");
return Ok(ExecuteInputResult::None); return Ok(ExecuteInputResult::default());
} }
}; };
if config.forced { if config.forced {
let _: CorpusId = fuzzer.add_input(self, executor, manager, input)?; let (_id, result) = fuzzer.add_input(self, executor, manager, input)?;
Ok(ExecuteInputResult::Corpus) Ok(result)
} else { } else {
let (res, _) = fuzzer.evaluate_input(self, executor, manager, &input)?; let (res, _) = fuzzer.evaluate_input(self, executor, manager, &input)?;
if res == ExecuteInputResult::None { if !(res.is_corpus() || res.is_solution()) {
fuzzer.add_disabled_input(self, input)?; fuzzer.add_disabled_input(self, input)?;
log::warn!("input {:?} was not interesting, adding as disabled.", &path); log::warn!("input {:?} was not interesting, adding as disabled.", &path);
} }
@ -748,7 +750,7 @@ where
match self.next_file() { match self.next_file() {
Ok(path) => { Ok(path) => {
let res = self.load_file(&path, manager, fuzzer, executor, &mut config)?; let res = self.load_file(&path, manager, fuzzer, executor, &mut config)?;
if config.exit_on_solution && matches!(res, ExecuteInputResult::Solution) { if config.exit_on_solution && res.is_solution() {
return Err(Error::invalid_corpus(format!( return Err(Error::invalid_corpus(format!(
"Input {} resulted in a solution.", "Input {} resulted in a solution.",
path.display() path.display()
@ -1052,11 +1054,11 @@ where
for _ in 0..num { for _ in 0..num {
let input = generator.generate(self)?; let input = generator.generate(self)?;
if forced { if forced {
let _: CorpusId = fuzzer.add_input(self, executor, manager, input)?; let (_, _) = fuzzer.add_input(self, executor, manager, input)?;
added += 1; added += 1;
} else { } else {
let (res, _) = fuzzer.evaluate_input(self, executor, manager, &input)?; let (res, _) = fuzzer.evaluate_input(self, executor, manager, &input)?;
if res != ExecuteInputResult::None { if res.is_corpus() {
added += 1; added += 1;
} }
} }

View File

@ -463,7 +463,7 @@ mod windows {
#[expect(clippy::cast_ptr_alignment)] #[expect(clippy::cast_ptr_alignment)]
pub fn get_num_logical_cpus_ex_windows() -> Option<usize> { pub fn get_num_logical_cpus_ex_windows() -> Option<usize> {
use std::{ptr, slice}; use core::{ptr, slice};
#[expect(non_upper_case_globals)] #[expect(non_upper_case_globals)]
const RelationProcessorCore: u32 = 0; const RelationProcessorCore: u32 = 0;

View File

@ -990,7 +990,7 @@ impl SimpleStdoutLogger {
#[must_use] #[must_use]
/// Return thread ID without using TLS /// Return thread ID without using TLS
pub fn get_thread_id() -> u64 { pub fn get_thread_id() -> u64 {
use std::arch::asm; use core::arch::asm;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
unsafe { unsafe {
let teb: *const u8; let teb: *const u8;
@ -1031,7 +1031,7 @@ pub fn get_thread_id() -> u64 {
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
mod windows_logging { mod windows_logging {
use std::ptr; use core::ptr;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use winapi::um::{ use winapi::um::{
@ -1291,7 +1291,7 @@ struct TEB {
#[inline(always)] #[inline(always)]
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
fn nt_current_teb() -> *mut TEB { fn nt_current_teb() -> *mut TEB {
use std::arch::asm; use core::arch::asm;
let teb: *mut TEB; let teb: *mut TEB;
unsafe { unsafe {
asm!("mov {}, gs:0x30", out(reg) teb); asm!("mov {}, gs:0x30", out(reg) teb);

View File

@ -47,7 +47,7 @@ pub const fn integer_sqrt(val: u64) -> u64 {
let mut m; let mut m;
while ret != i - 1 { while ret != i - 1 {
m = (ret + i) / 2; m = u64::midpoint(ret, i);
if m.saturating_mul(m) <= val { if m.saturating_mul(m) <= val {
ret = m; ret = m;

View File

@ -499,7 +499,7 @@ where
// log::trace!("got ashmem client: {}, request:{:?}", client_id, request); // log::trace!("got ashmem client: {}, request:{:?}", client_id, request);
// Handle the client request // Handle the client request
let response = match request { match request {
ServedShMemRequest::Hello() => Ok(ServedShMemResponse::Id(client_id)), ServedShMemRequest::Hello() => Ok(ServedShMemResponse::Id(client_id)),
ServedShMemRequest::PreFork() => { ServedShMemRequest::PreFork() => {
// We clone the provider already, waiting for it to reconnect [`PostFork`]. // We clone the provider already, waiting for it to reconnect [`PostFork`].
@ -590,12 +590,10 @@ where
ServedShMemRequest::Exit => { ServedShMemRequest::Exit => {
log::info!("ShMemService - Exiting"); log::info!("ShMemService - Exiting");
// stopping the server // stopping the server
return Err(Error::shutting_down()); Err(Error::shutting_down())
} }
}; }
// log::info!("send ashmem client: {}, response: {:?}", client_id, &response); // log::info!("send ashmem client: {}, response: {:?}", client_id, &response);
response
} }
fn read_request(&mut self, client_id: RawFd) -> Result<ServedShMemRequest, Error> { fn read_request(&mut self, client_id: RawFd) -> Result<ServedShMemRequest, Error> {

View File

@ -554,7 +554,6 @@ pub mod serdeany_registry {
#[cfg(not(feature = "stable_anymap"))] #[cfg(not(feature = "stable_anymap"))]
let type_repr = &type_repr; let type_repr = &type_repr;
#[expect(clippy::manual_map)]
match self.map.get(type_repr) { match self.map.get(type_repr) {
None => None, None => None,
Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())), Some(h) => Some(h.values().map(|x| x.as_any().downcast_ref::<T>().unwrap())),
@ -580,7 +579,6 @@ pub mod serdeany_registry {
#[cfg(not(feature = "stable_anymap"))] #[cfg(not(feature = "stable_anymap"))]
let type_repr = &type_repr; let type_repr = &type_repr;
#[expect(clippy::manual_map)]
match self.map.get_mut(type_repr) { match self.map.get_mut(type_repr) {
None => None, None => None,
Some(h) => Some( Some(h) => Some(

View File

@ -141,9 +141,9 @@ where
return Err(Error::illegal_state(format!( return Err(Error::illegal_state(format!(
"The state restorer map is too small to fit anything, even the filename! "The state restorer map is too small to fit anything, even the filename!
It needs to be at least {} bytes. It needs to be at least {} bytes.
The tmpfile was written to {:?}.", The tmpfile was written to {}.",
len, len,
temp_dir().join(&filename) temp_dir().join(&filename).display()
))); )));
} }

View File

@ -28,6 +28,8 @@
//! name = "SymRuntime" //! name = "SymRuntime"
//! ``` //! ```
#![allow(clippy::std_instead_of_core)]
pub mod filter; pub mod filter;
pub mod tracing; pub mod tracing;

View File

@ -1697,7 +1697,7 @@ impl AsanRuntime {
let insn = disas_count( let insn = disas_count(
&decoder, &decoder,
unsafe { std::slice::from_raw_parts(actual_pc as *mut u8, 4) }, unsafe { core::slice::from_raw_parts(actual_pc as *mut u8, 4) },
1, 1,
)[0]; )[0];

View File

@ -269,7 +269,7 @@ impl AsanErrors {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
let insts = disas_count( let insts = disas_count(
&decoder, &decoder,
unsafe { std::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) }, unsafe { core::slice::from_raw_parts(start_pc as *mut u8, 4 * 11) },
11, 11,
); );
@ -540,7 +540,7 @@ impl AsanErrors {
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
let insts = disas_count( let insts = disas_count(
&decoder, &decoder,
unsafe { std::slice::from_raw_parts(*start_pc as *mut u8, 4 * 11) }, unsafe { core::slice::from_raw_parts(*start_pc as *mut u8, 4 * 11) },
11, 11,
); );
@ -691,11 +691,6 @@ where
Ok(()) Ok(())
} }
fn discard_metadata(&mut self, _state: &mut S, _input: &I) -> Result<(), Error> {
self.errors = None;
Ok(())
}
#[cfg(feature = "track_hit_feedbacks")] #[cfg(feature = "track_hit_feedbacks")]
fn last_result(&self) -> Result<bool, Error> { fn last_result(&self) -> Result<bool, Error> {
Ok(self.errors.is_some()) Ok(self.errors.is_some())

View File

@ -837,7 +837,6 @@ impl AsanRuntime {
#[expect(non_snake_case)] #[expect(non_snake_case)]
#[allow(unknown_lints)] // the compiler is contradicting itself #[allow(unknown_lints)] // the compiler is contradicting itself
#[expect(clippy::used_underscore_items)]
#[inline] #[inline]
pub fn hook__Znwm( pub fn hook__Znwm(
&mut self, &mut self,
@ -874,7 +873,6 @@ impl AsanRuntime {
#[expect(non_snake_case)] #[expect(non_snake_case)]
#[allow(unknown_lints)] // the compiler is contradicting itself #[allow(unknown_lints)] // the compiler is contradicting itself
#[expect(clippy::used_underscore_items)]
#[inline] #[inline]
pub fn hook__ZnwmSt11align_val_t( pub fn hook__ZnwmSt11align_val_t(
&mut self, &mut self,

View File

@ -47,12 +47,12 @@ impl PreviousHook {
let inner = self.0; let inner = self.0;
if inner.is_null() { if inner.is_null() {
unsafe { unsafe {
pthread_introspection_hook_install(std::ptr::null()); pthread_introspection_hook_install(core::ptr::null());
} }
return; return;
} }
unsafe { unsafe {
self.0 = std::ptr::null(); self.0 = core::ptr::null();
pthread_introspection_hook_install(inner); pthread_introspection_hook_install(inner);
} }
} }
@ -64,7 +64,7 @@ unsafe impl Sync for PreviousHook {}
// TODO: This could use a RwLock as well // TODO: This could use a RwLock as well
/// The previous hook /// The previous hook
static mut PREVIOUS_HOOK: PreviousHook = PreviousHook(std::ptr::null()); static mut PREVIOUS_HOOK: PreviousHook = PreviousHook(core::ptr::null());
/// The currently set hook /// The currently set hook
static CURRENT_HOOK: RwLock<Option<PthreadIntrospectionHook>> = RwLock::new(None); static CURRENT_HOOK: RwLock<Option<PthreadIntrospectionHook>> = RwLock::new(None);
@ -197,11 +197,9 @@ pub unsafe fn reset() {
/// The following tests fail if they are not run sequentially. /// The following tests fail if they are not run sequentially.
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::{ use alloc::sync::Arc;
sync::{Arc, Mutex}, use core::time::Duration;
thread, use std::{sync::Mutex, thread};
time::Duration,
};
use serial_test::serial; use serial_test::serial;

View File

@ -103,8 +103,7 @@ impl LibfuzzerCrashCauseFeedback {
let base = if let Some(filename) = testcase.filename() { let base = if let Some(filename) = testcase.filename() {
filename.clone() filename.clone()
} else { } else {
let name = testcase.input().as_ref().unwrap().generate_name(None); testcase.input().as_ref().unwrap().generate_name(None)
name
}; };
let file_path = self.artifact_prefix.dir().join(format!( let file_path = self.artifact_prefix.dir().join(format!(
"{}{prefix}-{base}", "{}{prefix}-{base}",

View File

@ -194,9 +194,11 @@ where
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|e| { self.inner.next().map(|e| {
(*e == self.initial) if *e == self.initial {
.then(|| self.value_obs.default_value()) self.value_obs.default_value()
.unwrap_or_else(|| self.value_obs.value()) } else {
self.value_obs.value()
}
}) })
} }
} }

View File

@ -6,6 +6,7 @@ __Warning__: The documentation is built by default for `x86_64` in `usermode`. T
*/ */
#![cfg_attr(nightly, feature(used_with_arg))] #![cfg_attr(nightly, feature(used_with_arg))]
#![allow(clippy::std_instead_of_core)]
use core::ffi::c_void; use core::ffi::c_void;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]

View File

@ -21,7 +21,7 @@ use libafl::{
inprocess_fork::stateful::StatefulInProcessForkExecutor, inprocess_fork::stateful::StatefulInProcessForkExecutor,
}, },
feedbacks::Feedback, feedbacks::Feedback,
fuzzer::HasObjective, fuzzer::{HasFeedback, HasObjective},
inputs::Input, inputs::Input,
observers::ObserversTuple, observers::ObserversTuple,
state::{HasCurrentTestcase, HasExecutions, HasSolutions}, state::{HasCurrentTestcase, HasExecutions, HasSolutions},
@ -60,7 +60,7 @@ pub struct QemuExecutor<'a, C, CM, ED, EM, ET, H, I, OT, S, SM, Z> {
/// ///
/// This should be used as a crash handler, and nothing else. /// This should be used as a crash handler, and nothing else.
#[cfg(feature = "usermode")] #[cfg(feature = "usermode")]
pub unsafe fn inproc_qemu_crash_handler<E, EM, ET, I, OF, S, Z>( pub unsafe fn inproc_qemu_crash_handler<E, EM, ET, F, I, OF, S, Z>(
signal: Signal, signal: Signal,
info: &mut siginfo_t, info: &mut siginfo_t,
mut context: Option<&mut ucontext_t>, mut context: Option<&mut ucontext_t>,
@ -70,9 +70,10 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, ET, I, OF, S, Z>(
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I> + Unpin, S: HasExecutions + HasSolutions<I> + HasCorpus<I> + HasCurrentTestcase<I> + Unpin,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone + Unpin, I: Input + Clone + Unpin,
{ {
log::debug!("QEMU signal handler has been triggered (signal {signal})"); log::debug!("QEMU signal handler has been triggered (signal {signal})");
@ -126,7 +127,7 @@ pub unsafe fn inproc_qemu_crash_handler<E, EM, ET, I, OF, S, Z>(
log::debug!("Running crash hooks."); log::debug!("Running crash hooks.");
run_target_crash_hooks::<ET, I, S>(signal.into()); run_target_crash_hooks::<ET, I, S>(signal.into());
assert!(unsafe { data.maybe_report_crash::<E, EM, I, OF, S, Z>(None) }); assert!(unsafe { data.maybe_report_crash::<E, EM, F, I, OF, S, Z>(None) });
if let Some(cpu) = qemu.current_cpu() { if let Some(cpu) = qemu.current_cpu() {
eprint!("QEMU Context:\n{}", cpu.display_context()); eprint!("QEMU Context:\n{}", cpu.display_context());
@ -163,7 +164,7 @@ pub(crate) static BREAK_ON_TMOUT: AtomicBool = AtomicBool::new(false);
/// # Safety /// # Safety
/// Can call through the `unix_signal_handler::inproc_timeout_handler`. /// Can call through the `unix_signal_handler::inproc_timeout_handler`.
/// Calling this method multiple times concurrently can lead to race conditions. /// Calling this method multiple times concurrently can lead to race conditions.
pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, I, OF, S, Z>( pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, F, I, OF, S, Z>(
signal: Signal, signal: Signal,
info: &mut siginfo_t, info: &mut siginfo_t,
context: Option<&mut ucontext_t>, context: Option<&mut ucontext_t>,
@ -173,11 +174,12 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, I, OF, S, Z>(
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
ET: EmulatorModuleTuple<I, S>, ET: EmulatorModuleTuple<I, S>,
F: Feedback<EM, I, E::Observers, S>,
I: Unpin, I: Unpin,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + Unpin + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + Unpin + HasCurrentTestcase<I>,
I: Input, I: Input,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
{ {
#[cfg(feature = "systemmode")] #[cfg(feature = "systemmode")]
unsafe { unsafe {
@ -187,6 +189,7 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, I, OF, S, Z>(
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::< libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<
E, E,
EM, EM,
F,
I, I,
OF, OF,
S, S,
@ -205,6 +208,7 @@ pub unsafe fn inproc_qemu_timeout_handler<E, EM, ET, I, OF, S, Z>(
libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::< libafl::executors::hooks::unix::unix_signal_handler::inproc_timeout_handler::<
E, E,
EM, EM,
F,
I, I,
OF, OF,
S, S,
@ -234,7 +238,7 @@ where
OT: ObserversTuple<I, S>, OT: ObserversTuple<I, S>,
S: Unpin + HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: Unpin + HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
{ {
pub fn new<OF>( pub fn new<F, OF>(
emulator: Emulator<C, CM, ED, ET, I, S, SM>, emulator: Emulator<C, CM, ED, ET, I, S, SM>,
harness_fn: &'a mut H, harness_fn: &'a mut H,
observers: OT, observers: OT,
@ -248,8 +252,12 @@ where
CM: CommandManager<C, ED, ET, I, S, SM, Commands = C>, CM: CommandManager<C, ED, ET, I, S, SM, Commands = C>,
ED: EmulatorDriver<C, CM, ET, I, S, SM>, ED: EmulatorDriver<C, CM, ET, I, S, SM>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, OT, S>,
OF: Feedback<EM, I, OT, S>, OF: Feedback<EM, I, OT, S>,
Z: HasObjective<Objective = OF> + HasScheduler<I, S> + ExecutionProcessor<EM, I, OT, S>, Z: HasObjective<Objective = OF>
+ HasScheduler<I, S>
+ ExecutionProcessor<EM, I, OT, S>
+ HasFeedback<Feedback = F>,
{ {
let mut inner = StatefulInProcessExecutor::with_timeout( let mut inner = StatefulInProcessExecutor::with_timeout(
harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout, harness_fn, emulator, observers, fuzzer, state, event_mgr, timeout,
@ -259,7 +267,7 @@ where
#[cfg(feature = "usermode")] #[cfg(feature = "usermode")]
{ {
inner.inprocess_hooks_mut().crash_handler = inner.inprocess_hooks_mut().crash_handler =
inproc_qemu_crash_handler::<Self, EM, ET, I, OF, S, Z> as *const c_void; inproc_qemu_crash_handler::<Self, EM, ET, F, I, OF, S, Z> as *const c_void;
} }
// rewrite the timeout handler pointer // rewrite the timeout handler pointer
@ -267,6 +275,7 @@ where
StatefulInProcessExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, Z>, StatefulInProcessExecutor<'a, EM, Emulator<C, CM, ED, ET, I, S, SM>, H, I, OT, S, Z>,
EM, EM,
ET, ET,
F,
I, I,
OF, OF,
S, S,

View File

@ -16,6 +16,10 @@
// This causes bindgen to generate empty Rust struct that are generally not FFI-safe due to C++ having empty structs with size 1 // This causes bindgen to generate empty Rust struct that are generally not FFI-safe due to C++ having empty structs with size 1
// As the QEMU codebase is C, it is FFI-safe and we just ignore the warning // As the QEMU codebase is C, it is FFI-safe and we just ignore the warning
#![allow(improper_ctypes)] #![allow(improper_ctypes)]
// you don't build this without std
#![allow(clippy::std_instead_of_core)]
// same
#![allow(clippy::std_instead_of_alloc)]
use std::env; use std::env;

View File

@ -1,4 +1,4 @@
use std::ptr; use core::ptr;
/// Generators, responsible for generating block/edge ids /// Generators, responsible for generating block/edge ids
pub use generators::{gen_hashed_block_ids, gen_hashed_edge_ids, gen_unique_edge_ids}; pub use generators::{gen_hashed_block_ids, gen_hashed_edge_ids, gen_unique_edge_ids};

View File

@ -11,19 +11,17 @@ use rangemap::RangeMap;
use crate::Qemu; use crate::Qemu;
// (almost) Copy paste from addr2line/src/bin/addr2line.rs // (almost) Copy paste from addr2line/src/bin/addr2line.rs
fn print_function(name: Option<&str>, language: Option<addr2line::gimli::DwLang>) -> String { fn print_function(name: Option<&str>, language: Option<addr2line::gimli::DwLang>) -> String {
let ret = if let Some(name) = name { if let Some(name) = name {
addr2line::demangle_auto(Cow::from(name), language).to_string() addr2line::demangle_auto(Cow::from(name), language).to_string()
} else { } else {
"??".to_string() "??".to_string()
}; }
// println!("{ret:?}");
ret
} }
/// check if this binary is pie (for 64bit binary only) /// check if this binary is pie (for 64bit binary only)
#[must_use] #[must_use]
pub fn is_pie(file: object::File<'_>) -> bool { pub fn is_pie(file: object::File<'_>) -> bool {
let is_pie = match file { match file {
object::File::Elf64(elf) => { object::File::Elf64(elf) => {
let mut is_pie = false; let mut is_pie = false;
let table = elf.elf_section_table(); let table = elf.elf_section_table();
@ -41,9 +39,7 @@ pub fn is_pie(file: object::File<'_>) -> bool {
is_pie is_pie
} }
_ => false, _ => false,
}; }
is_pie
} }
pub struct AddressResolver { pub struct AddressResolver {

View File

@ -172,7 +172,7 @@ pub struct HookData(u64);
unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool { unsafe extern "C" fn gdb_cmd(data: *mut c_void, buf: *mut u8, len: usize) -> bool {
unsafe { unsafe {
let closure = &mut *(data as *mut Box<dyn for<'r> FnMut(Qemu, &'r str) -> bool>); let closure = &mut *(data as *mut Box<dyn for<'r> FnMut(Qemu, &'r str) -> bool>);
let cmd = std::str::from_utf8_unchecked(std::slice::from_raw_parts(buf, len)); let cmd = core::str::from_utf8_unchecked(std::slice::from_raw_parts(buf, len));
let qemu = Qemu::get_unchecked(); let qemu = Qemu::get_unchecked();
closure(qemu, cmd) closure(qemu, cmd)
} }

View File

@ -1,6 +1,7 @@
//! An `afl`-style forkserver fuzzer. //! An `afl`-style forkserver fuzzer.
//! Use this if your target has complex state that needs to be reset. //! Use this if your target has complex state that needs to be reset.
use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; use core::{net::SocketAddr, time::Duration};
use std::{fs, path::PathBuf};
use libafl::{ use libafl::{
Error, HasMetadata, Error, HasMetadata,

View File

@ -1,8 +1,12 @@
//! In-Memory fuzzing made easy. //! In-Memory fuzzing made easy.
//! Use this sugar for scaling `libfuzzer`-style fuzzers. //! Use this sugar for scaling `libfuzzer`-style fuzzers.
use core::fmt::{self, Debug, Formatter}; use core::{
use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; fmt::{self, Debug, Formatter},
net::SocketAddr,
time::Duration,
};
use std::{fs, path::PathBuf};
use libafl::{ use libafl::{
Error, HasMetadata, Error, HasMetadata,

View File

@ -1,6 +1,10 @@
//! In-memory fuzzer with `QEMU`-based binary-only instrumentation //! In-memory fuzzer with `QEMU`-based binary-only instrumentation
use core::fmt::{self, Debug, Formatter}; use core::{
use std::{fs, net::SocketAddr, path::PathBuf, time::Duration}; fmt::{self, Debug, Formatter},
net::SocketAddr,
time::Duration,
};
use std::{fs, path::PathBuf};
use libafl::{ use libafl::{
HasMetadata, HasMetadata,

View File

@ -217,8 +217,8 @@ impl DrCovModuleEntry {
#[must_use] #[must_use]
pub fn to_module_line(&self) -> String { pub fn to_module_line(&self) -> String {
format!( format!(
"{:03}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, {:?}", "{:03}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, {}",
self.id, self.base, self.end, self.entry, self.checksum, self.timestamp, self.path self.id, self.base, self.end, self.entry, self.checksum, self.timestamp, self.path.display()
) )
} }
} }

View File

@ -1,7 +1,7 @@
//! Setup asan death callbback //! Setup asan death callbback
use libafl::{ use libafl::{
HasObjective, HasFeedback, HasObjective,
events::{EventFirer, EventRestarter}, events::{EventFirer, EventRestarter},
executors::{Executor, HasObservers, hooks::windows::windows_asan_handler::asan_death_handler}, executors::{Executor, HasObservers, hooks::windows::windows_asan_handler::asan_death_handler},
feedbacks::Feedback, feedbacks::Feedback,
@ -29,17 +29,21 @@ unsafe extern "C" {
/// ///
/// # Safety /// # Safety
/// Calls the unsafe `__sanitizer_set_death_callback` symbol, but should be safe to call otherwise. /// Calls the unsafe `__sanitizer_set_death_callback` symbol, but should be safe to call otherwise.
pub unsafe fn setup_asan_callback<E, EM, I, OF, S, Z>(_executor: &E, _event_mgr: &EM, _fuzzer: &Z) pub unsafe fn setup_asan_callback<E, EM, F, I, OF, S, Z>(
where _executor: &E,
_event_mgr: &EM,
_fuzzer: &Z,
) where
E: Executor<EM, I, S, Z> + HasObservers, E: Executor<EM, I, S, Z> + HasObservers,
E::Observers: ObserversTuple<I, S>, E::Observers: ObserversTuple<I, S>,
EM: EventFirer<I, S> + EventRestarter<S>, EM: EventFirer<I, S> + EventRestarter<S>,
F: Feedback<EM, I, E::Observers, S>,
OF: Feedback<EM, I, E::Observers, S>, OF: Feedback<EM, I, E::Observers, S>,
S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>, S: HasExecutions + HasSolutions<I> + HasCurrentTestcase<I>,
Z: HasObjective<Objective = OF>, Z: HasObjective<Objective = OF> + HasFeedback<Feedback = F>,
I: Input + Clone, I: Input + Clone,
{ {
unsafe { unsafe {
__sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, I, OF, S, Z>)); __sanitizer_set_death_callback(Some(asan_death_handler::<E, EM, F, I, OF, S, Z>));
} }
} }

View File

@ -1,6 +1,6 @@
//! Stub out syscalls. Linux only. //! Stub out syscalls. Linux only.
use std::ptr; use core::ptr;
use libc::{c_int, c_void, off_t, size_t}; use libc::{c_int, c_void, off_t, size_t};
use meminterval::Interval; use meminterval::Interval;