Skip to content

Commit

Permalink
Added get_path function
Browse files Browse the repository at this point in the history
  • Loading branch information
Avgor46 committed Sep 6, 2023
1 parent 48055a7 commit d8d3470
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 32 deletions.
1 change: 1 addition & 0 deletions casr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ gdb-command = "0.7"
nix = "0.26"
rayon = "1.7"
num_cpus = "1.15"
is_executable = "1.0"
linux-personality = "1.0"
colored = "2.0"
serde = { version = "1.0", features = ["derive"] }
Expand Down
5 changes: 2 additions & 3 deletions casr/src/bin/casr-java.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ fn main() -> Result<()> {
.long("sub-tool")
.default_value("casr-san")
.action(ArgAction::Set)
.value_parser(clap::value_parser!(PathBuf))
.value_name("PATH")
.value_name("SUB_TOOL")
.help(
"Path to sub tool for crash analysis that will be called when main tool fails to detect a crash",
"Sub tool name for crash analysis that will be called when main tool fails to detect a crash",
),
)
.arg(
Expand Down
5 changes: 2 additions & 3 deletions casr/src/bin/casr-python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,9 @@ fn main() -> Result<()> {
.long("sub-tool")
.default_value("casr-san")
.action(ArgAction::Set)
.value_parser(clap::value_parser!(PathBuf))
.value_name("PATH")
.value_name("SUB_TOOL")
.help(
"Path to sub tool for crash analysis that will be called when main tool fails to detect a crash",
"Sub tool name for crash analysis that will be called when main tool fails to detect a crash",
),
)
.arg(
Expand Down
77 changes: 51 additions & 26 deletions casr/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ use std::collections::{HashMap, HashSet};
use std::fs::{self, OpenOptions};
use std::io::Write;
use std::io::{BufRead, BufReader};
use std::os::unix::fs::PermissionsExt;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::sync::RwLock;
use std::time::Duration;

use is_executable::IsExecutable;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use wait_timeout::ChildExt;
use walkdir::WalkDir;
use which::which;

/// Call sub tool with the provided options
///
Expand All @@ -35,19 +34,8 @@ use which::which;
///
/// * `argv` - executable file options
pub fn call_sub_tool(matches: &ArgMatches, argv: &[&str], name: &str) -> Result<()> {
let tool = matches.get_one::<PathBuf>("sub-tool").unwrap();
if which(tool).is_err() {
if !tool.exists() {
bail!("Sub tool {tool:?} doesn't exist");
}
if !tool.is_file() {
bail!("Sub tool {tool:?} isn't a file");
}
if tool.metadata()?.permissions().mode() & 0o111 == 0 {
bail!("Sub tool {tool:?} isn't executable");
}
}
let mut cmd = Command::new(tool);
let tool = get_path(matches.get_one::<String>("sub-tool").unwrap())?;
let mut cmd = Command::new(&tool);
if let Some(report_path) = matches.get_one::<PathBuf>("output") {
cmd.args(["--output", report_path.to_str().unwrap()]);
} else {
Expand Down Expand Up @@ -348,7 +336,7 @@ impl<'a> CrashInfo {
///
/// # Arguments
///
/// * `tool` - tool that generates reports
/// * `tool` - path to tool that generates reports
///
/// * `output_dir` - save report to specified directory or use the same directory as crash
///
Expand All @@ -357,7 +345,7 @@ impl<'a> CrashInfo {
/// * `envs` - environment variables for target
pub fn run_casr<T: Into<Option<&'a Path>>>(
&self,
tool: &str,
tool: &PathBuf,
output_dir: T,
timeout: u64,
envs: &HashMap<String, String>,
Expand All @@ -380,7 +368,8 @@ impl<'a> CrashInfo {
let input = args[at_index + 3].replace("@@", self.path.to_str().unwrap());
args[at_index + 3] = input;
}
if tool.eq("casr-python") {
let tool_name = tool.file_name().unwrap().to_str().unwrap();
if tool_name.ends_with("casr-python") {
args.insert(3, "python3".to_string());
}
if self.at_index.is_none() {
Expand All @@ -392,7 +381,6 @@ impl<'a> CrashInfo {
args.insert(0, "-t".to_string());
}

let tool = if self.is_asan { tool } else { "casr-gdb" };
let mut casr_cmd = Command::new(tool);
casr_cmd.args(&args);
casr_cmd.envs(envs);
Expand Down Expand Up @@ -437,7 +425,7 @@ impl<'a> CrashInfo {
error!("Error occurred while copying the file: {:?}", self.path);
}
} else if err.contains("Program terminated (no crash)") {
warn!("{}: No crash on input {}", tool, self.path.display());
warn!("{}: No crash on input {}", tool_name, self.path.display());
} else {
error!("{} for input: {}", err.trim(), self.path.display());
}
Expand All @@ -464,6 +452,10 @@ pub fn generate_reports(
tool: &str,
gdb_argv: &Vec<String>,
) -> Result<()> {
// Get tool paths
let casr_tool = get_path(tool)?;
let casr_gdb = get_path("casr-gdb")?;
let casr_cluster = get_path("casr-cluster")?;
// Get timeout
let timeout = if let Some(timeout) = matches.get_one::<u64>("timeout") {
*timeout
Expand Down Expand Up @@ -517,6 +509,7 @@ pub fn generate_reports(
.join(
|| {
crashes.par_iter().try_for_each(|(_, crash)| {
let tool = if crash.is_asan { &casr_tool } else { &casr_gdb };
if let Err(e) = crash.run_casr(tool, output_dir.as_path(), timeout, &envs) {
// Disable util::log_progress
*counter.write().unwrap() = total;
Expand All @@ -536,11 +529,11 @@ pub fn generate_reports(
return summarize_results(output_dir, crashes, gdb_argv, num_of_threads, timeout);
}
info!("Deduplicating CASR reports...");
let casr_cluster_d = Command::new("casr-cluster")
let casr_cluster_d = Command::new(&casr_cluster)
.arg("-d")
.arg(output_dir.clone().into_os_string())
.output()
.with_context(|| "Couldn't launch casr-cluster".to_string())?;
.with_context(|| format!("Couldn't launch {casr_cluster:?}"))?;

if casr_cluster_d.status.success() {
info!(
Expand All @@ -567,11 +560,11 @@ pub fn generate_reports(
return summarize_results(output_dir, crashes, gdb_argv, num_of_threads, timeout);
}
info!("Clustering CASR reports...");
let casr_cluster_c = Command::new("casr-cluster")
let casr_cluster_c = Command::new(&casr_cluster)
.arg("-c")
.arg(output_dir.clone().into_os_string())
.output()
.with_context(|| "Couldn't launch casr-cluster".to_string())?;
.with_context(|| format!("Couldn't launch {casr_cluster:?}"))?;

if casr_cluster_c.status.success() {
info!(
Expand Down Expand Up @@ -620,6 +613,7 @@ fn summarize_results(
copy_crashes(dir, crashes)?;

if !gdb_args.is_empty() {
let casr_gdb = get_path("casr-gdb")?;
// Run casr-gdb on uninstrumented binary.
let crashes: Vec<_> = WalkDir::new(dir)
.into_iter()
Expand Down Expand Up @@ -655,7 +649,7 @@ fn summarize_results(
is_asan: false,
})
.run_casr(
"casr-gdb",
&casr_gdb,
None,
timeout,
&HashMap::new(),
Expand All @@ -674,8 +668,9 @@ fn summarize_results(
}
}

let casr_cli = get_path("casr-cli")?;
// Print summary
let status = Command::new("casr-cli")
let status = Command::new(casr_cli)
.arg(dir)
.stderr(std::process::Stdio::inherit())
.stdout(std::process::Stdio::inherit())
Expand Down Expand Up @@ -788,3 +783,33 @@ pub fn symbols_list(path: &Path) -> Result<HashSet<&str>> {

Ok(found_symbols)
}

/// Function searches for path to the tool
///
/// # Arguments
///
/// * 'tool' - tool name
///
/// # Return value
///
/// Path to the tool
fn get_path(tool: &str) -> Result<PathBuf> {
let mut path_to_tool = std::env::current_exe()?;
let current_tool = path_to_tool
.file_name()
.unwrap()
.to_str()
.unwrap()
.to_string();
path_to_tool.pop();
path_to_tool.push(tool);
if path_to_tool.is_executable() {
Ok(path_to_tool)
} else if let Ok(path_to_tool) = which::which(tool) {
Ok(path_to_tool)
} else {
bail!(
"{path_to_tool:?}: No {tool} next to {current_tool}. And there is no {tool} in PATH."
);
}
}

0 comments on commit d8d3470

Please sign in to comment.