swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.74k stars 1.34k forks source link

[SR-8282] Support fuzzing in Swift Package Manager #4769

Open Lukasa opened 6 years ago

Lukasa commented 6 years ago
Previous ID SR-8282
Radar rdar://problem/42287282
Original Reporter @Lukasa
Type New Feature
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Package Manager | |Labels | New Feature | |Assignee | None | |Priority | Medium | md5: e2de92f1768e4822b39cda6e54c8bd44

Issue Description:

It would be ideal if Swift Package Manager would provide some mechanism to support generating targets for libFuzzer to allow specifying fuzzing targets. Ideally these targets could be largely dormant, but requested via some SwiftPM invocation.

aciidgh commented 6 years ago

@swift-ci create

Lukasa commented 6 years ago

The way this works today in Swift Package Manager is fairly awkward. Each fuzzer needs to be declared as an executable product in Swift PM. However, in its main.swift file, it doesn't have a top-level invocation. Instead, it has a function declared like this:

@_cdecl("LLVMFuzzerTestOneInput") public func fuzzMe(data: UnsafePointer<CChar>, size: CInt) -> CInt {
    return 0
}

This function is going to be invoked from libFuzzer. To actually build the fuzzer requires invoking SwiftPM like this: swift build -Xswiftc -sanitize=fuzzer,address -Xswiftc -parse-as-library. Naturally, this set of flags does not mesh well with SwiftPM's expected behaviours, and so you cannot correctly define fuzz targets in the same package as your library or executable.

Annoyingly, libFuzzer requires that your fuzzing code not have a main function. For SwiftPM to be willing to produce a binary you need an executable target, but removing the main function from it requires that awkward -parse-as-library flag. Without -parse-as-library, the linker complains that there are too many entry points. SwiftPM needs a better idea of how to put these things together such that we can use library targets, and invoke the fuzzer from the command line.

aciidgh commented 6 years ago

It sounds like we need to declare an executable target in SwiftPM which doesn't contain a `main.swift` file. I can think of two approaches:

1. If there is an executable product declared in the manifest, compile its target as an executable.

  1. Provide some API in target decl. to explicitly mark them as library or executable.

1. sounds reasonable to me and composes well with the existing API.

Thoughts?

/cc @neonichu @ddunbar