Skip to content

Commit 73cf2a4

Browse files
Fuzzing: Integrate ClusterFuzzLite
1 parent cf41ab2 commit 73cf2a4

File tree

6 files changed

+92
-13
lines changed

6 files changed

+92
-13
lines changed

.clusterfuzzlite/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM gcr.io/oss-fuzz-base/base-builder-swift:v1
2+
RUN apt-get update && apt-get install -y make autoconf automake libtool
3+
ENV SWIFT_PREFIX=/opt/swift
4+
RUN mkdir -p "$SWIFT_PREFIX" && \
5+
curl -L https://download.swift.org/swift-6.0.1-release/ubuntu2004/swift-6.0.1-RELEASE/swift-6.0.1-RELEASE-ubuntu20.04.tar.gz | tar xz -C "$SWIFT_PREFIX" --strip-component 1
6+
ENV PATH="$SWIFT_PREFIX/usr/bin:$PATH"
7+
COPY . $SRC/wasmkit
8+
WORKDIR $SRC/wasmkit
9+
COPY .clusterfuzzlite/build.sh $SRC/

.clusterfuzzlite/build.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash -eu
2+
3+
cd FuzzTesting
4+
./fuzz.py --verbose build --sanitizer="$SANITIZER" FuzzTranslator
5+
6+
find .build/debug/ -maxdepth 1 -type f -name "Fuzz*" -executable -exec cp {} "$OUT/" \;
7+

.clusterfuzzlite/project.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
language: swift

.github/workflows/cflite_pr.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: ClusterFuzzLite PR fuzzing
2+
on:
3+
pull_request:
4+
paths:
5+
- '**'
6+
permissions: read-all
7+
jobs:
8+
PR:
9+
runs-on: ubuntu-latest
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
sanitizer:
17+
- address
18+
# Override this with the sanitizers you want.
19+
# - undefined
20+
# - memory
21+
steps:
22+
- name: Build Fuzzers (${{ matrix.sanitizer }})
23+
id: build
24+
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
25+
with:
26+
language: c++ # Change this to the language you are fuzzing.
27+
github-token: ${{ secrets.GITHUB_TOKEN }}
28+
sanitizer: ${{ matrix.sanitizer }}
29+
# Optional but recommended: used to only run fuzzers that are affected
30+
# by the PR.
31+
# See later section on "Git repo for storage".
32+
# storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git
33+
# storage-repo-branch: main # Optional. Defaults to "main"
34+
# storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages".
35+
- name: Run Fuzzers (${{ matrix.sanitizer }})
36+
id: run
37+
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
38+
with:
39+
github-token: ${{ secrets.GITHUB_TOKEN }}
40+
fuzz-seconds: 600
41+
mode: 'code-change'
42+
sanitizer: ${{ matrix.sanitizer }}
43+
output-sarif: true
44+
# Optional but recommended: used to download the corpus produced by
45+
# batch fuzzing.
46+
# See later section on "Git repo for storage".
47+
# storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git
48+
# storage-repo-branch: main # Optional. Defaults to "main"
49+
# storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages".
50+

FuzzTesting/Package.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,3 @@ let package = Package(
4444
.target(name: "WasmCAPI"),
4545
]
4646
)
47-
48-
let libFuzzerTargets = ["FuzzTranslator", "FuzzExecute"]
49-
50-
for target in package.targets {
51-
guard libFuzzerTargets.contains(target.name) else { continue }
52-
target.swiftSettings = [.unsafeFlags(["-Xfrontend", "-sanitize=fuzzer,address"])]
53-
}

FuzzTesting/fuzz.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ def main():
4646
build_parser = subparsers.add_parser('build', help='Build the fuzzer')
4747
build_parser.add_argument(
4848
'target_name', type=str, help='Name of the target', choices=available_targets)
49+
build_parser.add_argument(
50+
'--sanitizer', type=str, default='address')
4951
build_parser.set_defaults(func=build)
5052

5153
run_parser = subparsers.add_parser('run', help='Run the fuzzer')
@@ -96,18 +98,35 @@ def executable_path(target_name: str) -> str:
9698
def build(args, runner: CommandRunner):
9799
print(f'Building fuzzer for {args.target_name}')
98100

99-
runner.run([
100-
'swift', 'build', '--product', args.target_name
101-
], check=True)
101+
driver_flags = []
102+
if args.sanitizer == 'coverage':
103+
driver_flags += [
104+
'-profile-generate', '-profile-coverage-mapping',
105+
'-sanitize=fuzzer'
106+
]
107+
else:
108+
driver_flags += [f'-sanitize=fuzzer,{args.sanitizer}']
109+
110+
build_args = [
111+
'swift', 'build', '--product', args.target_name,
112+
]
113+
for driver_flag in driver_flags:
114+
build_args += ['-Xswiftc', driver_flag]
115+
116+
runner.run(build_args, check=True)
102117

103118
print('Building fuzzer executable')
104119
# See "Discussion" in Package.swift for why we need to manually link
105120
# the library product.
106121
output = executable_path(args.target_name)
107-
runner.run([
122+
link_args = [
108123
'swiftc', f'./.build/debug/lib{args.target_name}.a', '-g',
109-
'-sanitize=fuzzer,address', '-o', output
110-
], check=True)
124+
# Link Swift runtime statically to allow copying fuzzers to other
125+
# machines (oss-fuzz does this)
126+
'-static-stdlib',
127+
]
128+
link_args += driver_flags
129+
runner.run(link_args, check=True)
111130

112131
print('Fuzzer built successfully: ', output)
113132

0 commit comments

Comments
 (0)