Allow configuring timeout for CommandExecutor (#1269)
* Allow configuring timeout for CommandExecutor * import Duration on windows as well * fix example fuzzers
This commit is contained in:
parent
1da621456f
commit
6d2284d8b9
@ -4,6 +4,7 @@ use std::{
|
|||||||
io::Write,
|
io::Write,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{Child, Command, Stdio},
|
process::{Child, Command, Stdio},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
@ -103,6 +104,10 @@ pub fn main() {
|
|||||||
stdin.write_all(input.target_bytes().as_slice())?;
|
stdin.write_all(input.target_bytes().as_slice())?;
|
||||||
Ok(child)
|
Ok(child)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exec_timeout(&self) -> Duration {
|
||||||
|
Duration::from_secs(5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut executor = MyExecutor { shmem_id }.into_executor(tuple_list!(observer, bt_observer));
|
let mut executor = MyExecutor { shmem_id }.into_executor(tuple_list!(observer, bt_observer));
|
||||||
|
@ -8,6 +8,7 @@ use std::{
|
|||||||
env,
|
env,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{Child, Command, Stdio},
|
process::{Child, Command, Stdio},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use clap::{self, Parser};
|
use clap::{self, Parser};
|
||||||
@ -251,4 +252,8 @@ impl CommandConfigurator for MyCommandConfigurator {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to start process"))
|
.expect("failed to start process"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exec_timeout(&self) -> Duration {
|
||||||
|
Duration::from_secs(5)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,12 @@ use core::{
|
|||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::process::Child;
|
use std::process::Child;
|
||||||
#[cfg(all(feature = "std", unix))]
|
|
||||||
use std::time::Duration;
|
|
||||||
use std::{
|
use std::{
|
||||||
ffi::{OsStr, OsString},
|
ffi::{OsStr, OsString},
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::HasObservers;
|
use super::HasObservers;
|
||||||
@ -80,6 +79,7 @@ pub struct StdCommandConfigurator {
|
|||||||
debug_child: bool,
|
debug_child: bool,
|
||||||
has_stdout_observer: bool,
|
has_stdout_observer: bool,
|
||||||
has_stderr_observer: bool,
|
has_stderr_observer: bool,
|
||||||
|
timeout: Duration,
|
||||||
/// true: input gets delivered via stdink
|
/// true: input gets delivered via stdink
|
||||||
input_location: InputLocation,
|
input_location: InputLocation,
|
||||||
/// The Command to execute
|
/// The Command to execute
|
||||||
@ -153,6 +153,10 @@ impl CommandConfigurator for StdCommandConfigurator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exec_timeout(&self) -> Duration {
|
||||||
|
self.timeout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `CommandExecutor` is a wrapper around [`std::process::Command`] to execute a target as a child process.
|
/// A `CommandExecutor` is a wrapper around [`std::process::Command`] to execute a target as a child process.
|
||||||
@ -219,6 +223,7 @@ where
|
|||||||
pub fn from_cmd_with_file<P>(
|
pub fn from_cmd_with_file<P>(
|
||||||
cmd: &Command,
|
cmd: &Command,
|
||||||
debug_child: bool,
|
debug_child: bool,
|
||||||
|
timeout: Duration,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
path: P,
|
path: P,
|
||||||
) -> Result<Self, Error>
|
) -> Result<Self, Error>
|
||||||
@ -251,6 +256,7 @@ where
|
|||||||
debug_child,
|
debug_child,
|
||||||
has_stdout_observer,
|
has_stdout_observer,
|
||||||
has_stderr_observer,
|
has_stderr_observer,
|
||||||
|
timeout,
|
||||||
},
|
},
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
@ -265,6 +271,7 @@ where
|
|||||||
args: IT,
|
args: IT,
|
||||||
observers: OT,
|
observers: OT,
|
||||||
debug_child: bool,
|
debug_child: bool,
|
||||||
|
timeout: Duration,
|
||||||
) -> Result<Self, Error>
|
) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
IT: IntoIterator<Item = O>,
|
IT: IntoIterator<Item = O>,
|
||||||
@ -273,6 +280,7 @@ where
|
|||||||
let mut atat_at = None;
|
let mut atat_at = None;
|
||||||
let mut builder = CommandExecutorBuilder::new();
|
let mut builder = CommandExecutorBuilder::new();
|
||||||
builder.debug_child(debug_child);
|
builder.debug_child(debug_child);
|
||||||
|
builder.timeout(timeout);
|
||||||
let afl_delim = OsStr::new("@@");
|
let afl_delim = OsStr::new("@@");
|
||||||
|
|
||||||
for (pos, arg) in args.into_iter().enumerate() {
|
for (pos, arg) in args.into_iter().enumerate() {
|
||||||
@ -325,7 +333,7 @@ where
|
|||||||
let mut child = self.configurer.spawn_child(input)?;
|
let mut child = self.configurer.spawn_child(input)?;
|
||||||
|
|
||||||
let res = match child
|
let res = match child
|
||||||
.wait_timeout(Duration::from_secs(5))
|
.wait_timeout(self.configurer.exec_timeout())
|
||||||
.expect("waiting on child failed")
|
.expect("waiting on child failed")
|
||||||
.map(|status| status.signal())
|
.map(|status| status.signal())
|
||||||
{
|
{
|
||||||
@ -405,6 +413,7 @@ pub struct CommandExecutorBuilder {
|
|||||||
input_location: InputLocation,
|
input_location: InputLocation,
|
||||||
cwd: Option<PathBuf>,
|
cwd: Option<PathBuf>,
|
||||||
envs: Vec<(OsString, OsString)>,
|
envs: Vec<(OsString, OsString)>,
|
||||||
|
timeout: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CommandExecutorBuilder {
|
impl Default for CommandExecutorBuilder {
|
||||||
@ -423,6 +432,7 @@ impl CommandExecutorBuilder {
|
|||||||
input_location: InputLocation::StdIn,
|
input_location: InputLocation::StdIn,
|
||||||
cwd: None,
|
cwd: None,
|
||||||
envs: vec![],
|
envs: vec![],
|
||||||
|
timeout: Duration::from_secs(5),
|
||||||
debug_child: false,
|
debug_child: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -541,6 +551,12 @@ impl CommandExecutorBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the execution timeout duration.
|
||||||
|
pub fn timeout(&mut self, timeout: Duration) -> &mut CommandExecutorBuilder {
|
||||||
|
self.timeout = timeout;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Builds the `CommandExecutor`
|
/// Builds the `CommandExecutor`
|
||||||
pub fn build<OT, S>(
|
pub fn build<OT, S>(
|
||||||
&self,
|
&self,
|
||||||
@ -591,6 +607,7 @@ impl CommandExecutorBuilder {
|
|||||||
has_stdout_observer: observers.observes_stdout(),
|
has_stdout_observer: observers.observes_stdout(),
|
||||||
has_stderr_observer: observers.observes_stderr(),
|
has_stderr_observer: observers.observes_stderr(),
|
||||||
input_location: self.input_location.clone(),
|
input_location: self.input_location.clone(),
|
||||||
|
timeout: self.timeout,
|
||||||
command,
|
command,
|
||||||
};
|
};
|
||||||
Ok(configurator.into_executor::<OT, S>(observers))
|
Ok(configurator.into_executor::<OT, S>(observers))
|
||||||
@ -601,7 +618,7 @@ impl CommandExecutorBuilder {
|
|||||||
/// # Example
|
/// # Example
|
||||||
#[cfg_attr(all(feature = "std", unix), doc = " ```")]
|
#[cfg_attr(all(feature = "std", unix), doc = " ```")]
|
||||||
#[cfg_attr(not(all(feature = "std", unix)), doc = " ```ignore")]
|
#[cfg_attr(not(all(feature = "std", unix)), doc = " ```ignore")]
|
||||||
/// use std::{io::Write, process::{Stdio, Command, Child}};
|
/// use std::{io::Write, process::{Stdio, Command, Child}, time::Duration};
|
||||||
/// use libafl::{Error, bolts::AsSlice, inputs::{HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::UsesState};
|
/// use libafl::{Error, bolts::AsSlice, inputs::{HasTargetBytes, Input, UsesInput}, executors::{Executor, command::CommandConfigurator}, state::UsesState};
|
||||||
/// #[derive(Debug)]
|
/// #[derive(Debug)]
|
||||||
/// struct MyExecutor;
|
/// struct MyExecutor;
|
||||||
@ -622,6 +639,10 @@ impl CommandExecutorBuilder {
|
|||||||
/// stdin.write_all(input.target_bytes().as_slice())?;
|
/// stdin.write_all(input.target_bytes().as_slice())?;
|
||||||
/// Ok(child)
|
/// Ok(child)
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
/// fn exec_timeout(&self) -> Duration {
|
||||||
|
/// Duration::from_secs(5)
|
||||||
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn make_executor<EM, Z>() -> impl Executor<EM, Z>
|
/// fn make_executor<EM, Z>() -> impl Executor<EM, Z>
|
||||||
@ -642,6 +663,9 @@ pub trait CommandConfigurator: Sized + Debug {
|
|||||||
where
|
where
|
||||||
I: Input + HasTargetBytes;
|
I: Input + HasTargetBytes;
|
||||||
|
|
||||||
|
/// Provides timeout duration for execution of the child process.
|
||||||
|
fn exec_timeout(&self) -> Duration;
|
||||||
|
|
||||||
/// Create an `Executor` from this `CommandConfigurator`.
|
/// Create an `Executor` from this `CommandConfigurator`.
|
||||||
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self>
|
fn into_executor<OT, S>(self, observers: OT) -> CommandExecutor<OT, S, Self>
|
||||||
where
|
where
|
||||||
@ -699,14 +723,19 @@ mod tests {
|
|||||||
#[cfg_attr(miri, ignore)]
|
#[cfg_attr(miri, ignore)]
|
||||||
fn test_parse_afl_cmdline() {
|
fn test_parse_afl_cmdline() {
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
let mut mgr = SimpleEventManager::new(SimpleMonitor::new(|status| {
|
let mut mgr = SimpleEventManager::new(SimpleMonitor::new(|status| {
|
||||||
log::info!("{status}");
|
log::info!("{status}");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut executor =
|
let mut executor = CommandExecutor::parse_afl_cmdline(
|
||||||
CommandExecutor::parse_afl_cmdline(["file".to_string(), "@@".to_string()], (), true)
|
["file".to_string(), "@@".to_string()],
|
||||||
.unwrap();
|
(),
|
||||||
|
true,
|
||||||
|
Duration::from_secs(5),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
executor
|
executor
|
||||||
.run_target(
|
.run_target(
|
||||||
&mut NopFuzzer::new(),
|
&mut NopFuzzer::new(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user