diff --git a/libafl/src/executors/forkserver.rs b/libafl/src/executors/forkserver.rs index 2340b0c451..bdcadc89bd 100644 --- a/libafl/src/executors/forkserver.rs +++ b/libafl/src/executors/forkserver.rs @@ -195,15 +195,22 @@ impl Forkserver { out_filefd: RawFd, use_stdin: bool, memlimit: u64, + debug_output: bool, ) -> Result { let mut st_pipe = Pipe::new().unwrap(); let mut ctl_pipe = Pipe::new().unwrap(); + let (stdout, stderr) = if debug_output { + (Stdio::inherit(), Stdio::inherit()) + } else { + (Stdio::null(), Stdio::null()) + }; + match Command::new(target) .args(args) .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) + .stdout(stdout) + .stderr(stderr) .env("LD_BIND_LAZY", "1") .setlimit(memlimit) .setsid() @@ -364,12 +371,13 @@ where match &mut self.executor.map_mut() { Some(map) => { - let size = input.target_bytes().as_slice().len(); + let target_bytes = input.target_bytes(); + let size = target_bytes.as_slice().len(); let size_in_bytes = size.to_ne_bytes(); // The first four bytes tells the size of the shmem. map.map_mut()[..4].copy_from_slice(&size_in_bytes[..4]); map.map_mut()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)] - .copy_from_slice(input.target_bytes().as_slice()); + .copy_from_slice(target_bytes.as_slice()); } None => { self.executor @@ -466,6 +474,16 @@ where arguments: &[String], use_shmem_testcase: bool, observers: OT, + ) -> Result { + Self::with_debug(target, arguments, use_shmem_testcase, observers, false) + } + + pub fn with_debug( + target: String, + arguments: &[String], + use_shmem_testcase: bool, + observers: OT, + debug_output: bool, ) -> Result { let mut args = Vec::::new(); let mut use_stdin = true; @@ -500,6 +518,7 @@ where out_file.as_raw_fd(), use_stdin, 0, + debug_output, )?; let (rlen, status) = forkserver.read_st()?; // Initial handshake, read 4-bytes hello message from the forkserver. @@ -573,12 +592,13 @@ where // Write to testcase match &mut self.map { Some(map) => { - let size = input.target_bytes().as_slice().len(); + let target_bytes = input.target_bytes(); + let size = target_bytes.as_slice().len(); let size_in_bytes = size.to_ne_bytes(); // The first four bytes tells the size of the shmem. map.map_mut()[..4].copy_from_slice(&size_in_bytes[..4]); map.map_mut()[SHMEM_FUZZ_HDR_SIZE..(SHMEM_FUZZ_HDR_SIZE + size)] - .copy_from_slice(input.target_bytes().as_slice()); + .copy_from_slice(target_bytes.as_slice()); } None => { self.out_file.write_buf(input.target_bytes().as_slice()); diff --git a/libafl_sugar/src/forkserver.rs b/libafl_sugar/src/forkserver.rs index 2b863c2fc2..eed5aff118 100644 --- a/libafl_sugar/src/forkserver.rs +++ b/libafl_sugar/src/forkserver.rs @@ -31,10 +31,10 @@ use libafl::{ use crate::{CORPUS_CACHE_SIZE, DEFAULT_TIMEOUT_SECS}; -pub const MAP_SIZE: usize = 65536; +pub const DEFAULT_MAP_SIZE: usize = 65536; #[derive(TypedBuilder)] -pub struct ForkserverBytesCoverageSugar<'a> { +pub struct ForkserverBytesCoverageSugar<'a, const MAP_SIZE: usize> { /// Laucher configuration (default is random) #[builder(default = None, setter(strip_option))] configuration: Option, @@ -66,13 +66,13 @@ pub struct ForkserverBytesCoverageSugar<'a> { #[builder(default = false)] /// Use shared mem testcase delivery shmem_testcase: bool, - // Coverage map size - //#[builder(default = MAP_SIZE)] - //map_size: usize, + #[builder(default = false)] + /// Print target program output + debug_output: bool, } #[allow(clippy::similar_names)] -impl<'a> ForkserverBytesCoverageSugar<'a> { +impl<'a, const MAP_SIZE: usize> ForkserverBytesCoverageSugar<'a, MAP_SIZE> { #[allow(clippy::too_many_lines, clippy::similar_names)] pub fn run(&mut self) { let conf = match self.configuration.as_ref() { @@ -166,11 +166,12 @@ impl<'a> ForkserverBytesCoverageSugar<'a> { // Create the executor for an in-process function with one observer for edge coverage and one for the execution time let mut executor = TimeoutForkserverExecutor::new( - ForkserverExecutor::new( + ForkserverExecutor::with_debug( self.program.clone(), self.arguments, self.shmem_testcase, tuple_list!(edges_observer, time_observer), + self.debug_output, ) .expect("Failed to create the executor."), timeout, @@ -248,16 +249,14 @@ impl<'a> ForkserverBytesCoverageSugar<'a> { } } -/* #[cfg(feature = "python")] pub mod pybind { - use crate::inmemory; + use crate::forkserver; use pyo3::prelude::*; - use pyo3::types::PyBytes; use std::path::PathBuf; #[pyclass(unsendable)] - struct InMemoryBytesCoverageSugar { + struct ForkserverBytesCoverageSugar { input_dirs: Vec, output_dir: PathBuf, broker_port: u16, @@ -265,7 +264,7 @@ pub mod pybind { } #[pymethods] - impl InMemoryBytesCoverageSugar { + impl ForkserverBytesCoverageSugar { #[new] fn new( input_dirs: Vec, @@ -282,27 +281,21 @@ pub mod pybind { } #[allow(clippy::needless_pass_by_value)] - pub fn run(&self, harness: PyObject) { - inmemory::InMemoryBytesCoverageSugar::builder() + pub fn run(&self, program: String, arguments: Vec) { + forkserver::ForkserverBytesCoverageSugar::<{ forkserver::DEFAULT_MAP_SIZE }>::builder() .input_dirs(&self.input_dirs) .output_dir(self.output_dir.clone()) .broker_port(self.broker_port) .cores(&self.cores) - .harness(|buf| { - Python::with_gil(|py| -> PyResult<()> { - let args = (PyBytes::new(py, buf),); // TODO avoid copy - harness.call1(py, args)?; - Ok(()) - }) - .unwrap(); - }) + .program(program) + .arguments(&arguments) .build() .run(); } } pub fn register(_py: Python, m: &PyModule) -> PyResult<()> { - m.add_class::()?; + m.add_class::()?; Ok(()) } -}*/ +}