Home

Awesome

fuzzit.dev was acquired by GitLab and the new home for this repo is here

Continuous Fuzzing for Swift Example

This is an example of how to integrate libFuzzer targets with the Fuzzit Continuous Fuzzing Platform.

This example will show the following steps:

Result:

Fuzzing for swift can help find both complex bugs, security bugs and correctness bugs.

This tutorial focuses less on how to build libFuzzer targets and more on how to integrate the targets with Fuzzit. A lot of great information is available at the libFuzzer Tutorial and Swift libFuzzer.

Building libFuzzer Target

Understanding the bug

The bug is located at main.swift in the following code

    if
        buffer[0] == 0x46,
        buffer[1] == 0x55,
        buffer[2] == 0x5a,
        buffer[3] == 0x5a,
        buffer[4] == 0x49,
        buffer[5] == 0x65
    {
        fatalError()
    }

This is the simplest example to demonstrate how libFuzzer find a specified input (FUZZIT) that triggers fatalErro using guided code coverage fuzzing.

Setting up the development environment

libFuzzer is built-in in swift toolchain in the latest development releases. We created a docker image with bionic-swift-5.1-dev and clang-9 hosted at gcr.io/fuzzit-public/bionic-swift51

docker run -it gcr.io/fuzzit-public/bionic-swift51:beb0e9b /bin/bash

# Build libFuzzer target
git clone https://github.com/fuzzitdev/example-swift
cd example-swift
swift build -c release -Xswiftc -sanitize=fuzzer -Xswiftc -parse-as-library

# Run libFuzzer
./.build/release/example-swift

Will print the following output and stacktrace:

==66== ERROR: libFuzzer: deadly signal
    #0 0x558dcccbfb2f in __sanitizer_print_stack_trace /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/ubsan/ubsan_diag_standalone.cc:29:3
    #1 0x558dccc3f798 in fuzzer::PrintStackTrace() /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerUtil.cpp:206:5
    #2 0x558dccc29ff8 in fuzzer::Fuzzer::CrashCallback() /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:237:3
    #3 0x558dccc29fbf in fuzzer::Fuzzer::StaticCrashSignalCallback() /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:209:6
    #4 0x7f21dcf8688f  (/lib/x86_64-linux-gnu/libpthread.so.0+0x1288f)
    #5 0x7f21dd4e6400 in $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtFTf4xxnnn_n (/usr/lib/swift/linux/libswiftCore.so+0x353400)
    #6 0x7f21dd2e0e38 in $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF (/usr/lib/swift/linux/libswiftCore.so+0x14de38)
    #7 0x558dcccc00fa in $s13example_swift6fuzzMe4data4sizes5Int32VSPys4Int8VG_AFtF (/app/example-swift/.build/x86_64-unknown-linux/release/example-swift+0xb10fa)
    #8 0x558dccc2b54a in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:571:15
    #9 0x558dccc2ac95 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:480:3
    #10 0x558dccc2c6ab in fuzzer::Fuzzer::MutateAndTestOne() /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:708:19
    #11 0x558dccc2d385 in fuzzer::Fuzzer::Loop(std::Fuzzer::vector<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> >, fuzzer::fuzzer_allocator<std::Fuzzer::basic_string<char, std::Fuzzer::char_traits<char>, std::Fuzzer::allocator<char> > > > const&) /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerLoop.cpp:839:5
    #12 0x558dccc26dab in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:764:6
    #13 0x558dccc3fe32 in main /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-18_04/llvm/projects/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
    #14 0x7f21dc1e2b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #15 0x558dccc21279 in _start (/app/example-swift/.build/x86_64-unknown-linux/release/example-swift+0x12279)

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 2 InsertByte-InsertRepeatedBytes-; base unit: 53bc6cb455c00ab402de0304ec2fb992cf8498bc
0x46,0x55,0x5a,0x5a,0x49,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x65,0x3a,0x5a,
FUZZIeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:Z
artifact_prefix='./'; Test unit written to ./crash-207ef2bb62cc2acee33ea863800c4aa638118df2
Base64: RlVaWkllZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZTpa

Integrating with Fuzzit from CI

The best way to integrate with Fuzzit is by adding a two stages in your Continuous Build system (like Travis CI or Circle CI).

Fuzzing stage:

Regression stage

Here is the relevant snippet from the fuzzit.sh which is being run by .travis.yml

wget -q -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.17/fuzzit_Linux_x86_64
chmod a+x fuzzit

## upload fuzz target for long fuzz testing on fuzzit.dev server or run locally for regression
./fuzzit create job --type ${1} --host bionic-swift51 fuzzitdev/example-swift ./.build/release/example-swift

In production it is advised to download a pinned version of the CLI like in the example. In development you can use the latest version: https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_${OS}_${ARCH}. Valid values for ${OS} are: Linux, Darwin, Windows. Valid values for ${ARCH} are: x86_64 and i386.