diff --git a/Cargo.lock b/Cargo.lock index 211b11a..b6bcdda 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,6 +71,7 @@ dependencies = [ "anyhow", "assert_cmd", "cargo_metadata", + "cc", "clap", "current_platform", "predicates", @@ -104,9 +105,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.77" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" diff --git a/Cargo.toml b/Cargo.toml index ada61cb..e93ac2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,9 @@ toml = "0.5.9" rustc_version = "0.4.0" cargo_metadata = "0.18.1" +[target.'cfg(target_env = "msvc")'.dependencies] +cc = "1.1" + [dev-dependencies] assert_cmd = "2.0.7" predicates = "2.1.4" diff --git a/src/project.rs b/src/project.rs index 3bcc37e..1200adc 100644 --- a/src/project.rs +++ b/src/project.rs @@ -454,6 +454,17 @@ impl FuzzProject { cmd.arg(format!("-fork={}", run.jobs)); } + #[cfg(target_env = "msvc")] + { + use crate::utils::{append_to_pathvar, get_asan_path}; + // On Windows asan is in a DLL. This DLL is not on PATH by default, so the recommended + // action is to add the directory to PATH when running. + let asan = get_asan_path().with_context(|| "could not find AddressSanitizer DLL")?; + let new_path = + append_to_pathvar(asan).with_context(|| "could not get PATH variable")?; + cmd.env("PATH", new_path); + } + // When libfuzzer finds failing inputs, those inputs will end up in the // artifacts directory. To easily filter old artifacts from new ones, // get the current time, and then later we only consider files modified diff --git a/src/utils.rs b/src/utils.rs index acf0dba..f1d3cd6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,32 @@ +use std::ffi::OsString; + /// The default target to pass to cargo, to workaround issue #11. pub fn default_target() -> &'static str { current_platform::CURRENT_PLATFORM } + +/// Gets the path to the asan DLL required for the asan instrumented binary to run. +#[cfg(target_env = "msvc")] +pub fn get_asan_path() -> Option { + // The asan DLL sits next to cl & link.exe. So grab the parent path. + Some( + cc::windows_registry::find_tool(default_target(), "link.exe")? + .path() + .parent()? + .to_owned(), + ) +} + +/// Append a value to the PATH variable +#[cfg(target_env = "msvc")] +pub fn append_to_pathvar(path: std::path::PathBuf) -> Option { + use std::env; + + if let Some(current) = env::var_os("PATH") { + let mut current = env::split_paths(¤t).collect::>(); + current.push(path); + return env::join_paths(current).ok(); + } + + return None; +}