Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new build option to support Windows DLLs #388

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

cwshugg
Copy link

@cwshugg cwshugg commented Oct 16, 2024

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.

Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@fitzgen
Copy link
Member

fitzgen commented Oct 18, 2024

https://github.com/rust-fuzz/cargo-fuzz/actions/runs/11371974196/job/31744642568?pr=388#step:6:231

error[E0063]: missing field `no_include_main_msvc` in initializer of `options::BuildOptions`
Error:    --> src/options.rs:263:28
    |
263 |         let default_opts = BuildOptions {
    |                            ^^^^^^^^^^^^ missing `no_include_main_msvc`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Fuzzing Windows DLL (cdylib) - Unresolved External Symbol Main
2 participants