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:
parent
89342b22c2
commit
977ff10a0f
@ -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
|
||||||
|
39
Dockerfile
39
Dockerfile
@ -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
|
||||||
|
@ -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(()),
|
||||||
|
@ -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()
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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()?;
|
||||||
|
@ -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,
|
||||||
|
@ -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),
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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());
|
||||||
|
@ -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,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -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."))
|
||||||
|
@ -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> {
|
||||||
|
@ -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)
|
||||||
|
@ -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> {
|
||||||
|
@ -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::*;
|
||||||
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -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)?;
|
||||||
|
@ -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)?;
|
||||||
|
@ -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()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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> {
|
||||||
|
@ -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(
|
||||||
|
@ -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()
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
|
||||||
|
@ -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())
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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}",
|
||||||
|
@ -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()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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")]
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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};
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user