Fuzzing Swift
The Swift compiler has built-in libFuzzer integration, making it possible to coverage-guided fuzz-test Swift code with the same LLVM libFuzzer engine used for C/C++. The official documentation lives in the Swift repository (docs/libFuzzerIntegration.md).
Defining a fuzz target
Annotate an entry-point function with @_cdecl("LLVMFuzzerTestOneInput"). It receives a raw pointer plus a byte count; converting that byte stream into whatever inputs the code under test needs is the fuzz target’s job:
@_cdecl("LLVMFuzzerTestOneInput")
public func test(_ start: UnsafeRawPointer, _ count: Int) -> CInt {
let bytes = UnsafeRawBufferPointer(start: start, count: count)
// TODO: Test the code using the provided bytes.
return 0
}libFuzzer supplies the process main, the mutation engine, corpus management, and crash detection — the target only consumes bytes.
Compiling and running
Two flags are required: -sanitize=fuzzer links libFuzzer and enables coverage instrumentation, and -parse-as-library omits the main symbol so the fuzzer’s entry point is used instead:
swiftc -sanitize=fuzzer -parse-as-library myfile.swift
./myfile # start fuzzinglibFuzzer can be combined with other sanitizers, e.g. AddressSanitizer:
swiftc -sanitize=fuzzer,address -parse-as-library myfile.swiftAll standard libFuzzer command-line options work on the resulting binary — -max_total_time, -jobs/-workers for parallelism, corpus directories, -artifact_prefix for crash output, and so on.
Practical notes
- Toolchains matter. The libFuzzer integration depends on the compiler build; the Xcode-bundled Swift toolchain has historically omitted sanitizer/fuzzer components, while the downloadable toolchains from swift.org include them. Select a toolchain in Xcode or invoke one explicitly at the command line via
xcrun --toolchain <id> swiftc. - Memory hygiene. libFuzzer never frees allocations between runs; long-running fuzz jobs of Objective-C-bridge-heavy Swift code should wrap iterations in
autoreleasepoolto avoid unbounded growth. - Sanitizer interactions. Not every sanitizer composes with every API — e.g. AddressSanitizer instrumentation is known to interfere with some system services on Apple platforms, so validate the harness with a short run before scaling out.
Related
- gobuster / wfuzz — black-box web fuzzing, the other end of the spectrum from coverage-guided binary fuzzing
- nmap — NSE
fuzzercategory scripts - create-arbitrarily-long-strings-bash — quick manual boundary testing without a fuzzer