Skip to content
This repository was archived by the owner on Aug 4, 2020. It is now read-only.

Commit ea74348

Browse files
author
Yevgeny Pats
committed
Swift Tutorial in-progress
1 parent f467835 commit ea74348

File tree

4 files changed

+180
-4
lines changed

4 files changed

+180
-4
lines changed

.travis.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
dist: bionic
2+
3+
services:
4+
- docker
5+
6+
env:
7+
global:
8+
# This is FUZZIT_API_KEY. see https://docs.travis-ci.com/user/environment-variables/#encrypting-environment-variables for how to create secrets in Travis.
9+
secure: "FEm1wF/Ttd5RIvDPg5I/aSAhBWuvkvjmkInFxlVKP4BfLsR1B1ogXV4zKFQiZugyppBta+qP4qP+tSbThSvP9JOCr+/ivnTyYLg/DH1RfQnC7rJmAaZwHGHB+NwblRzU621uIZ4RVvaE391YVJf5519gc+M+bxZ6DO0ScdpbIAVV/7JR9c7Tuvoyi57/MEwAS39k7h83ms8JgRYwuvzpVH9nb6AfYs+CzXuRlsG5mHqFnmzLyG0ewnqh18OoWbyKQwBmM+EoIGmckM8NQZaXWBhEuDP7qdl+QatNfZtK3YwBx2plahBXXMee3NpOAEHOkWxNw1uMb1B8ILDrzrx8oX1A4fF/ZeJl7JLZS/fQUMhDnLG5soA0xaEoAvwhQIHFi3e207rsq9UJsnQlRGhRWzMvx85UR5z+yiur8nVUkogu1DGpH/BPdWbTs+d8behSr7t6Sepo7enjJOPJLz6U67JlP31HvnaLICMEXxJy54BAbdu/47vqFp15lcIMHyDzPltHHWi6uGuRFQPYz8pM5ZAKQ945dO/ZELyEHbjUiLTMFeVoANzahuY56BX6hvsygcOlBWB6ukoJANvxgvM/QYkbh9dMBajYsZqHCWOKRVbBakkqPAUqkBNPOADTp5ZgUwmRySIGzX2X+Efl7cFYZVu+IJl968F8hqYajvS/VCs="
10+
11+
jobs:
12+
include:
13+
- stage: Build, Unit-Tests & Fuzz-Tests
14+
go: 1.12.x
15+
script:
16+
- ./fuzzit.sh local-regression
17+
18+
- stage: Fuzzit (Fuzzing)
19+
if: branch = master AND type IN (push)
20+
go: 1.12.x
21+
script:
22+
- ./fuzzit.sh fuzzing

README.md

+130-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,131 @@
1-
# example-swift
1+
[![Build Status](https://travis-ci.org/fuzzitdev/example-swift.svg?branch=master)](https://travis-ci.org/fuzzitdev/example-swift)
2+
[![fuzzit](https://app.fuzzit.dev/badge?org_id=fuzzitdev&branch=master)](https://fuzzit.dev)
23

3-
A description of this package.
4+
# Continuous Fuzzing for Swift Example
5+
6+
This is an example of how to integrate [libFuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.rst)
7+
targets with the [Fuzzit](https://fuzzit.dev) Continuous Fuzzing Platform.
8+
9+
This example will show the following steps:
10+
* [Building and running a simple libfuzzer target locally](#building-libfuzzer-target)
11+
* [Integrate the libFuzzer target with Fuzzit via Travis-CI](#integrating-with-fuzzit-from-ci)
12+
13+
Result:
14+
* Fuzzit will run the fuzz targets continuously on a daily basis with the latest release.
15+
* Fuzzit will run regression tests on every pull-request with the generated corpus and crashes to catch bugs early on.
16+
17+
Fuzzing for swift can help find both complex bugs, security bugs and correctness bugs.
18+
19+
This tutorial focuses less on how to build libFuzzer targets and more on how to integrate the targets with Fuzzit. A lot of
20+
great information is available at the [libFuzzer Tutorial](https://llvm.org/docs/LibFuzzer.html) and [Swift libFuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.rst).
21+
22+
## Building libFuzzer Target
23+
24+
25+
26+
### Understanding the bug
27+
28+
The bug is located at `main.swift` in the following code
29+
30+
```swift
31+
if
32+
buffer[0] == 0x46,
33+
buffer[1] == 0x55,
34+
buffer[2] == 0x5a,
35+
buffer[3] == 0x5a,
36+
buffer[4] == 0x49,
37+
buffer[5] == 0x65
38+
{
39+
fatalError()
40+
}
41+
```
42+
43+
This is the simplest example to demonstrate how libFuzzer find a specified input (`FUZZIT`) that triggers `fatalErro`
44+
using guided code coverage fuzzing.
45+
46+
47+
### Setting up the development environment
48+
49+
libFuzzer is built-in in swift toolchain in the latest development releases. We created a [docker](https://github.com/fuzzitdev/fuzzit/blob/master/docker/ubuntu/bionic/swift/Dockerfile)
50+
image with bionic-swift-5.1-dev and clang-9 hosted at `gcr.io/fuzzit-public/bionic-swift51`
51+
52+
```bash
53+
docker run -it gcr.io/fuzzit-public/bionic-swift51:beb0e9b /bin/bash
54+
55+
# Build libFuzzer target
56+
git clone https://github.com/fuzzitdev/example-swift
57+
cd example-swift
58+
swift build -c release -Xswiftc -sanitize=fuzzer -Xswiftc -parse-as-library
59+
60+
# Run libFuzzer
61+
./.build/release/example-swift
62+
```
63+
64+
Will print the following output and stacktrace:
65+
66+
```text
67+
==66== ERROR: libFuzzer: deadly signal
68+
#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
69+
#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
70+
#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
71+
#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
72+
#4 0x7f21dcf8688f (/lib/x86_64-linux-gnu/libpthread.so.0+0x1288f)
73+
#5 0x7f21dd4e6400 in $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtFTf4xxnnn_n (/usr/lib/swift/linux/libswiftCore.so+0x353400)
74+
#6 0x7f21dd2e0e38 in $ss17_assertionFailure__4file4line5flagss5NeverOs12StaticStringV_SSAHSus6UInt32VtF (/usr/lib/swift/linux/libswiftCore.so+0x14de38)
75+
#7 0x558dcccc00fa in $s13example_swift6fuzzMe4data4sizes5Int32VSPys4Int8VG_AFtF (/app/example-swift/.build/x86_64-unknown-linux/release/example-swift+0xb10fa)
76+
#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
77+
#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
78+
#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
79+
#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
80+
#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
81+
#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
82+
#14 0x7f21dc1e2b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
83+
#15 0x558dccc21279 in _start (/app/example-swift/.build/x86_64-unknown-linux/release/example-swift+0x12279)
84+
85+
NOTE: libFuzzer has rudimentary signal handlers.
86+
Combine libFuzzer with AddressSanitizer or similar for better crash reports.
87+
SUMMARY: libFuzzer: deadly signal
88+
MS: 2 InsertByte-InsertRepeatedBytes-; base unit: 53bc6cb455c00ab402de0304ec2fb992cf8498bc
89+
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,
90+
FUZZIeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee:Z
91+
artifact_prefix='./'; Test unit written to ./crash-207ef2bb62cc2acee33ea863800c4aa638118df2
92+
Base64: RlVaWkllZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZTpa
93+
94+
```
95+
96+
## Integrating with Fuzzit from CI
97+
98+
The best way to integrate with Fuzzit is by adding a two stages in your Continuous Build system
99+
(like Travis CI or Circle CI).
100+
101+
Fuzzing stage:
102+
103+
* Build a fuzzing target
104+
* Download `fuzzit` cli
105+
* Authenticate via passing `FUZZIT_API_KEY` environment variable
106+
* Create a fuzzing job by uploading the fuzzing target
107+
108+
Regression stage
109+
* Build a fuzzing target
110+
* Download `fuzzit` cli
111+
* Authenticate via passing `FUZZIT_API_KEY` environment variable OR defining the corpus as public. This way
112+
No authentication would be require and regression can be used for [forked PRs](https://docs.travis-ci.com/user/pull-requests#pull-requests-and-security-restrictions) as well
113+
* Create a local regression fuzzing job - This will pull all the generated corpuses and run them through
114+
the fuzzing binary. If new bugs are introduced this will fail the CI and alert
115+
116+
Here is the relevant snippet from the [fuzzit.sh](https://github.com/fuzzitdev/example-swift/blob/master/fuzzit.sh)
117+
which is being run by [.travis.yml](https://github.com/fuzzitdev/example-swift/blob/master/.travis.yml)
118+
119+
```bash
120+
wget -q -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.17/fuzzit_Linux_x86_64
121+
chmod a+x fuzzit
122+
123+
## upload fuzz target for long fuzz testing on fuzzit.dev server or run locally for regression
124+
./fuzzit create job --type ${1} --host bionic-swift51 fuzzitdev/example-swift ./.build/release/example-swift
125+
```
126+
127+
In production it is advised to download a pinned version of the [CLI](https://github.com/fuzzitdev/fuzzit)
128+
like in the example. In development you can use the latest version:
129+
https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_${OS}_${ARCH}.
130+
Valid values for `${OS}` are: `Linux`, `Darwin`, `Windows`.
131+
Valid values for `${ARCH}` are: `x86_64` and `i386`.

Sources/example-swift/main.swift

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
@_cdecl("LLVMFuzzerTestOneInput") public func fuzzMe(data: UnsafePointer<CChar>, size: CInt) -> CInt {
2-
3-
return 0
2+
let buffer = UnsafeBufferPointer(start: data, count: Int(size))
3+
guard buffer.count >= 6 else {
4+
return 1
5+
}
6+
if
7+
buffer[0] == 0x46,
8+
buffer[1] == 0x55,
9+
buffer[2] == 0x5a,
10+
buffer[3] == 0x5a,
11+
buffer[4] == 0x49,
12+
buffer[5] == 0x65
13+
{
14+
fatalError()
15+
}
16+
return 0
417
}

fuzzit.sh

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
set -xe
3+
4+
5+
docker run -v `pwd`:/app gcr.io/fuzzit-public/bionic-swift51 /bin/bash -c "swift build -c release -Xswiftc -sanitize=fuzzer -Xswiftc -parse-as-library"
6+
7+
## Install fuzzit specific version for production or latest version for development :
8+
## https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_Linux_x86_64
9+
wget -q -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.31/fuzzit_Linux_x86_64
10+
chmod a+x fuzzit
11+
12+
## upload fuzz target for long fuzz testing on fuzzit.dev server or run locally for regression
13+
./fuzzit create job --type ${1} --host bionic-swift51 fuzzitdev/example-swift ./.build/release/example-swift

0 commit comments

Comments
 (0)