Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Set up .local file before invoking LibFuzzer #3269

Merged
merged 10 commits into from
Jul 13, 2023
62 changes: 62 additions & 0 deletions src/agent/onefuzz-task/src/tasks/fuzz/libfuzzer/generic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

use std::path::PathBuf;

use anyhow::Result;
use async_trait::async_trait;
use onefuzz::libfuzzer::LibFuzzer;
Expand Down Expand Up @@ -37,7 +39,67 @@ impl common::LibFuzzerType for GenericLibFuzzer {
config.common.machine_identity.clone(),
))
}

async fn extra_setup(config: &common::Config<Self>) -> Result<()> {
Porges marked this conversation as resolved.
Show resolved Hide resolved
// this is needed on Windows, but we do it unconditionally
let target_exe =
try_resolve_setup_relative_path(&config.common.setup_dir, &config.target_exe).await?;

// Set up a .local file on Windows before invoking the executable,
// so that all DLLs are resolved to the exe’s folder in preference to the Windows/system DLLs.
// The .local file is an empty file that tells DLL resolution to consider the same directory,
// even for system (or KnownDLL) files.
// See: https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-redirection#how-to-redirect-dlls-for-unpackaged-apps
let dotlocal_file = add_dotlocal_extension(target_exe);
if let Err(e) = tokio::fs::write(&dotlocal_file, &[]).await {
// ignore already-exists error, report anything else
if e.kind() != std::io::ErrorKind::AlreadyExists {
return Err(anyhow::Error::from(e).context("creating .local file"));
}
}

info!("Created .local file: {}", dotlocal_file.display());

Ok(())
}
}

fn add_dotlocal_extension(mut path: PathBuf) -> PathBuf {
if let Some(ext) = path.extension() {
let mut ext = ext.to_os_string();
ext.push(".local");
path.set_extension(ext);
} else {
path.set_extension("local");
}

path
}

pub type Config = common::Config<GenericLibFuzzer>;
pub type LibFuzzerFuzzTask = common::LibFuzzerFuzzTask<GenericLibFuzzer>;

#[cfg(test)]
mod test {
use std::path::PathBuf;

use super::add_dotlocal_extension;

#[test]
fn dotlocal_with_extension() {
let path = PathBuf::from("executable.exe");
assert_eq!(
PathBuf::from("executable.exe.local"),
add_dotlocal_extension(path)
);
}

#[test]
fn dotlocal_without_extension() {
let path = PathBuf::from("executable");
assert_eq!(
PathBuf::from("executable.local"),
add_dotlocal_extension(path)
);
}
}