diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index a14e83bacf..38ea8df235 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -498,6 +498,7 @@ where phantom: PhantomData, map_size: Option, timeout: TimeSpec, + crash_exitcode: Option, } impl Debug for ForkserverExecutor @@ -583,6 +584,7 @@ pub struct ForkserverExecutorBuilder<'a, SP> { real_map_size: i32, kill_signal: Option, timeout: Option, + crash_exitcode: Option, } impl<'a, SP> ForkserverExecutorBuilder<'a, SP> { @@ -631,6 +633,7 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> { phantom: PhantomData, map_size: self.map_size, timeout, + crash_exitcode: self.crash_exitcode, }) } @@ -688,6 +691,7 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> { phantom: PhantomData, map_size: self.map_size, timeout, + crash_exitcode: self.crash_exitcode, }) } @@ -999,6 +1003,13 @@ impl<'a, SP> ForkserverExecutorBuilder<'a, SP> { self } + /// Treats an execution as a crash if the provided exitcode is returned + #[must_use] + pub fn crash_exitcode(mut self, exitcode: i8) -> Self { + self.crash_exitcode = Some(exitcode); + self + } + /// Call this if the harness uses deferred forkserver mode; default is false #[must_use] pub fn is_deferred_frksrv(mut self, is_deferred_frksrv: bool) -> Self { @@ -1047,6 +1058,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> { max_input_size: MAX_INPUT_SIZE_DEFAULT, kill_signal: None, timeout: None, + crash_exitcode: None, } } @@ -1072,6 +1084,7 @@ impl<'a> ForkserverExecutorBuilder<'a, UnixShMemProvider> { max_input_size: MAX_INPUT_SIZE_DEFAULT, kill_signal: None, timeout: None, + crash_exitcode: None, } } } @@ -1157,7 +1170,12 @@ where if let Some(status) = self.forkserver.read_st_timed(&self.timeout)? { self.forkserver.set_status(status); - if libc::WIFSIGNALED(self.forkserver().status()) { + let exitcode_is_crash = if let Some(crash_exitcode) = self.crash_exitcode { + (libc::WEXITSTATUS(self.forkserver().status()) as i8) == crash_exitcode + } else { + false + }; + if libc::WIFSIGNALED(self.forkserver().status()) || exitcode_is_crash { exit_kind = ExitKind::Crash; #[cfg(feature = "regex")] if let Some(asan_observer) = self