Closed cwshugg closed 3 weeks ago
After doing a bit more studying and experimenting with the source code, I realized that the build arguments established during exec_build()
aren't individually executed for each dependency of the fuzz targets; rather, it's a single cargo build ...
command that passes all of these arguments to every dependency.
Because of this, the code snippet I shared above under "Possible Solution" wouldn't work. I think this lines up with Nick's reasoning in #340.
Though, I've found a way to implement a solution for building Windows DLLs in the PR I linked to this issue.
Hi cargo-fuzz devs! I am working on fuzzing a Windows DLL with cargo-fuzz and have been hitting a wall with a particular linker error. I've reproduced the problem in a small & simple Cargo project to demonstrate the issue.
Problem Description
The issue arises when the to-be-fuzzed Cargo project defines its
crate-type
as["cdylib"]
, specifically on Windows (it will compile into a DLL). TheCargo.toml
looks something like this:A very basic DLL
DllMain
function inlib.rs
looks like this:After running
cargo fuzz init
to initialize a basic fuzzing sub-project, the commandcargo fuzz build
(orcargo fuzz run
) will fail during building with the following linker error:Steps to Reproduce
cargo init --lib ./simplelib
cargo fuzz init
cargo fuzz build
Problem Analysis
I spent time digging through the various options passed to the Rust compiler by cargo-fuzz, and found this commit, which adds the
/include:main
linker argument for builds using themsvc
triple. Based on the comment left with that line of code, and reading up on the /include option, I understand the intention is to force libraries compiled on Windows to include themain
symbol, so it can be found within LibFuzzer.I also found #281, and based on the discussion there it seems like
crate-type = ["cdylib"]
may not be supported by cargo-fuzz. If I'm thinking about this problem correctly, I understand whycdylib
crates cause issues: DLLs/shared libraries, by nature, are loaded at runtime and don't have (don't need) prior knowledge of amain
function. But, as it sits now, it appears that Cargo projects that can only build ascdylibs
aren't able to be built by cargo-fuzz. (Please correct me if I am wrong)Possible Solution
Would it be possible to modify the cargo-fuzz building routine to build & instrument DLLs without the
main
function? This would allow the DLL to be built and instrumented in the same way as the fuzzing targets, but it would then be up to the user as to where the DLL should be dropped, so it can be loaded during fuzzing. (Since the DLL would be built with Sanitizer Coverage instrumentation, LibFuzzer should still be able to detect code coverage changes when the fuzzing target loads it in at runtime and invokes the DLL's functions.)Perhaps something like this:
I've been testing this theory locally (modifying my local copy of cargo-fuzz's code by commenting out the
rustflags.push_str(" -Clink-arg=/include:main")
when building the DLL), and it's building successfully with instrumentation. After it's built, I drop it into a location where my fuzzing target can pick it up for loading, and when I runcargo fuzz run my_fuzz_target
, LibFuzzer appears to be quickly discovering a set of cascading if-statements and a bug I inserted inside the DLL.