cargo-fuzz
cargo-fuzz copied to clipboard
Add new build option to support Windows DLLs
Hi - this PR implements a new build argument: --no-include-main-msvc
- in order to help enable support for building and fuzzing Windows DLLs.
I recently ran into an issue when attempting to fuzz a Windows-only DLL (#386) where the /include:main
linker argument that is added during FuzzProject::cargo()
for MSVC-based builds gave the DLL a main
symbol it could not resolve, which caused linking to fail:
LINK : error LNK2001: unresolved external symbol main
C:\....\depedency.dll : fatal error LNK1120: 1 unresolved externals
The DLL is, by nature, completely separate from the fuzzing targets in my cargo-fuzz repository, but I still wanted it to be a dependency listed in fuzz/Cargo.toml
, so that it would be built and instrumented in the exact same way as the fuzzing target binaries. I found that by controlling whether or not /include:main
is added to the cargo build
arguments executed by cargo-fuzz, I was able to set up a "dummy" fuzzing target that provides its own main function:
# fuzz/Cargo.toml
# ...
[dependencies]
# the DLL is optional; only to be built with a specific feature
my_dll = { path = "..", optional = true }
# ...
[features]
build_dll = ["dep:my_dll"]
# ...
[[bin]]
name = "dummy_target_build_dll"
path = "fuzz_targets/dummy_target_build_dll.rs"
required-features = ["build_dll"]
test = false
doc = false
bench = false
# ... other binaries ...
// dummy_target_build_dll.rs
fn main()
{
println!("DLL build complete! Now, copy the DLL to your desired location, `
and use `cargo fuzz run` to run your other fuzzing targets.");
// ... do other work, such as copying the DLL into the desired location ...
}
Then, by executing cargo fuzz run --no-include-main-msvc dummy_target
, the DLL would be built successfully. I could then proceed to run all other fuzzing targets, which would load in the instrumented DLL and fuzz it.
TL;DR: This solution allows Windows DLLs to be instrumented & fuzzed, but only if manual control over /include:main
is allowed (hence, --no-include-main-msvc
). This resolves #386.