From a600769d69ac940b455caa0bfdb69b59f8223670 Mon Sep 17 00:00:00 2001 From: Joe Ranweiler Date: Thu, 27 Jan 2022 12:48:52 -0800 Subject: [PATCH] Add `test-input` example (#1624) --- src/agent/Cargo.lock | 1 + src/agent/onefuzz/Cargo.toml | 3 + src/agent/onefuzz/examples/test-input.rs | 84 ++++++++++++++++++++++++ 3 files changed, 88 insertions(+) create mode 100644 src/agent/onefuzz/examples/test-input.rs diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock index ce2973892..794adf6ab 100644 --- a/src/agent/Cargo.lock +++ b/src/agent/Cargo.lock @@ -1792,6 +1792,7 @@ dependencies = [ "sha2", "stacktrace-parser", "storage-queue", + "structopt", "strum", "strum_macros", "tempfile", diff --git a/src/agent/onefuzz/Cargo.toml b/src/agent/onefuzz/Cargo.toml index 093e009f7..be2efa053 100644 --- a/src/agent/onefuzz/Cargo.toml +++ b/src/agent/onefuzz/Cargo.toml @@ -55,3 +55,6 @@ nix = "0.23" pete = "0.8" rstack = "0.3" proc-maps = "0.2" + +[dev-dependencies] +structopt = "0.3" \ No newline at end of file diff --git a/src/agent/onefuzz/examples/test-input.rs b/src/agent/onefuzz/examples/test-input.rs new file mode 100644 index 000000000..fe87c5ac4 --- /dev/null +++ b/src/agent/onefuzz/examples/test-input.rs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +use std::path::PathBuf; + +use anyhow::Result; +use onefuzz::input_tester::Tester; +use structopt::StructOpt; + +#[derive(Debug, PartialEq, StructOpt)] +#[structopt(name = "test-input")] +struct Opt { + #[structopt(short, long)] + pub exe: PathBuf, + + #[structopt(short, long, long_help = "Defaults to `{input}`")] + pub options: Vec, + + #[structopt(short, long, long_help = "Defaults to dir of `exe`")] + pub setup_dir: Option, + + #[structopt(short, long)] + pub input: PathBuf, + + #[structopt(long)] + pub check_asan_log: bool, + + #[structopt(long)] + pub check_asan_stderr: bool, + + #[structopt(long)] + pub no_check_debugger: bool, + + #[structopt(short, long, long_help = "Timeout (seconds)", default_value = "5")] + pub timeout: u64, +} + +#[tokio::main] +async fn main() -> Result<()> { + let opt = Opt::from_args(); + + // Default `setup_dir` to base dir of + let setup_dir = opt.setup_dir.clone().unwrap_or_else(|| { + opt.exe + .parent() + .expect("target exe missing file component") + .to_owned() + }); + + let mut target_options = opt.options.clone(); + if target_options.is_empty() { + target_options.push("{input}".into()); + } + + let env = Default::default(); + let tester = Tester::new(&setup_dir, &opt.exe, &target_options, &env); + + let check_debugger = !opt.no_check_debugger; + let tester = tester + .timeout(opt.timeout) + .check_debugger(check_debugger) + .check_asan_log(opt.check_asan_log) + .check_asan_stderr(opt.check_asan_stderr); + + let test_result = tester.test_input(&opt.input).await?; + + if let Some(crash) = test_result.crash_log.as_ref() { + println!("[+] crash detected!"); + println!(); + let text: &str = crash.text.as_ref().map(|s| s.as_str()).unwrap_or_default(); + println!(" sanitizer = {}", crash.sanitizer); + println!(" summary = {}", crash.summary); + println!(" text = {}", text); + } else { + println!("[-] no crash detected."); + } + + println!(); + println!("[+] verbose test result:"); + println!(); + println!("{:?}", test_result); + + Ok(()) +}