├── .bazelignore
├── .bazelrc
├── .bazelversion
├── .bcr
├── config.yml
├── metadata.template.json
├── presubmit.yml
└── source.template.json
├── .clang-format
├── .github
├── ISSUE_TEMPLATE.md
└── workflows
│ ├── bazel_lint.yml
│ ├── bazel_test.yml
│ ├── cpp_lint.yml
│ └── oss_fuzz.yml
├── .gitignore
├── BUILD
├── CODEOWNERS
├── LICENSE
├── MODULE.bazel
├── README.md
├── WORKSPACE
├── WORKSPACE.bzlmod
├── docs
├── BUILD
├── cc-fuzzing-rules.md
├── code-of-conduct.md
├── contributing.md
├── guide.md
└── java-fuzzing-rules.md
├── examples
├── BUILD
├── bzlmod
│ ├── .bazelrc
│ ├── BUILD
│ ├── JavaFuzzTest.java
│ ├── MODULE.bazel
│ ├── WORKSPACE.bzlmod
│ └── cc_fuzz_test.cc
├── corpus_0.txt
├── corpus_1.txt
├── corpus_dir
│ ├── corpus_2.txt
│ ├── corpus_3.txt
│ └── secondary_dir
│ │ └── corpus_4.txt
├── dictionaries
│ ├── invalid.dict
│ ├── valid_part1.dict
│ └── valid_part2.dict
├── empty_fuzz_test.cc
├── fuzzed_data_provider_fuzz_test.cc
├── hang_fuzz_test.cc
├── input_buffer_overflow_fuzz_test.cc
├── java
│ ├── BUILD
│ ├── com
│ │ └── example
│ │ │ ├── EmptyFuzzTest.java
│ │ │ ├── FuzzTest.java
│ │ │ ├── NativeFuzzTest.cpp
│ │ │ ├── NativeFuzzTest.h
│ │ │ ├── NativeFuzzTest.java
│ │ │ ├── NativeRunfileFuzzTest.cpp
│ │ │ ├── NativeRunfileFuzzTest.h
│ │ │ ├── NativeRunfileFuzzTest.java
│ │ │ ├── NativeUbsanFuncPtrFuzzTest.cpp
│ │ │ ├── NativeUbsanFuncPtrFuzzTest.h
│ │ │ └── NativeUbsanFuncPtrFuzzTest.java
│ ├── corpus_0.txt
│ └── corpus_1.txt
├── msan_fuzz_test.cc
├── new_buffer_overflow_fuzz_test.cc
├── oom_fuzz_test.cc
├── re2_fuzz_test.cc
├── runfiles_fuzz_test.cc
├── test_corpus_dir
│ └── corpus_0.txt
├── ubsan_function_ptr_fuzz_test.cc
└── ubsan_int_overflow_fuzz_test.cc
├── fuzzing
├── BUILD
├── cc_defs.bzl
├── engines
│ ├── BUILD
│ ├── honggfuzz_launcher.sh
│ ├── jazzer_launcher.sh
│ ├── libfuzzer_launcher.sh
│ └── replay_launcher.sh
├── init.bzl
├── instrum_opts.bzl
├── java_defs.bzl
├── private
│ ├── BUILD
│ ├── binary.bzl
│ ├── common.bzl
│ ├── engine.bzl
│ ├── engine_test.bzl
│ ├── extensions.bzl
│ ├── fuzz_test.bzl
│ ├── instrum_opts.bzl
│ ├── java_utils.bzl
│ ├── local_jazzer_sanitizer_options.sh
│ ├── oss_fuzz
│ │ ├── BUILD
│ │ ├── BUILD.tpl
│ │ ├── instrum.bzl.tpl
│ │ ├── package.bzl
│ │ └── repository.bzl
│ ├── oss_fuzz_jazzer_sanitizer_options.sh
│ ├── regression.bzl
│ ├── runtime
│ │ ├── BUILD
│ │ └── clang_runtime_lib.bzl
│ └── util.bzl
├── replay
│ ├── BUILD
│ ├── file_util.cc
│ ├── file_util.h
│ ├── file_util_test.cc
│ ├── replay_main.cc
│ ├── status_util.cc
│ ├── status_util.h
│ ├── status_util_test.cc
│ ├── test_file_buffer.cc
│ ├── test_file_buffer.h
│ ├── test_file_buffer_test.cc
│ ├── test_replayer.cc
│ ├── test_replayer.h
│ └── test_replayer_test.cc
├── repositories.bzl
├── requirements.txt
└── tools
│ ├── BUILD
│ ├── dict_validation.py
│ ├── dict_validation_test.py
│ ├── launcher.py
│ ├── make_corpus_dir.py
│ ├── noop_lcov_merger.sh
│ └── validate_dict.py
├── honggfuzz.BUILD
└── update_docs.sh
/.bazelignore:
--------------------------------------------------------------------------------
1 | examples/bzlmod
2 |
--------------------------------------------------------------------------------
/.bazelrc:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Force the use of Clang for all builds.
16 | build --repo_env=CC=clang
17 |
18 | # Needed for abseil-cpp until https://github.com/bazelbuild/bazel/pull/19794 is released.
19 | build --cxxopt=-std=c++14
20 |
21 | # Workaround for https://github.com/bazelbuild/bazel/issues/3236
22 | build --sandbox_tmpfs_path=/tmp
23 |
24 | # Strict dependency check for C++ includes.
25 | build --features=layering_check
26 |
27 | # Target Java 11 to squelch warnings about Java 8 being deprecated.
28 | build --java_language_version=11
29 | build --java_runtime_version=remotejdk_11
30 | build --tool_java_language_version=11
31 | build --tool_java_runtime_version=remotejdk_11
32 |
33 | # The ASAN configuration suitable for C++ unit tests.
34 | build:asan --copt=-fsanitize=address
35 | build:asan --linkopt=-fsanitize=address
36 |
37 | # LibFuzzer + ASAN
38 | build:asan-libfuzzer --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
39 | build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
40 | build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
41 |
42 | # LibFuzzer + MSAN
43 | build:msan-libfuzzer --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
44 | build:msan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
45 | build:msan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=msan
46 |
47 | # LibFuzzer + MSAN (reproduction mode)
48 | build:msan-libfuzzer-repro --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
49 | build:msan-libfuzzer-repro --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
50 | build:msan-libfuzzer-repro --@rules_fuzzing//fuzzing:cc_engine_sanitizer=msan-origin-tracking
51 |
52 | # LibFuzzer + UBSAN
53 | build:ubsan-libfuzzer --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
54 | build:ubsan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
55 | build:ubsan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=ubsan
56 |
57 | # LibFuzzer + ASAN + UBSAN
58 | build:asan-ubsan-libfuzzer --//fuzzing:cc_engine=//fuzzing/engines:libfuzzer
59 | build:asan-ubsan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
60 | build:asan-ubsan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan-ubsan
61 |
62 | # Honggfuzz + ASAN
63 | build:asan-honggfuzz --//fuzzing:cc_engine=//fuzzing/engines:honggfuzz
64 | build:asan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=honggfuzz
65 | build:asan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
66 |
67 | # Honggfuzz + MSAN
68 | build:msan-honggfuzz --//fuzzing:cc_engine=//fuzzing/engines:honggfuzz
69 | build:msan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=honggfuzz
70 | build:msan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=msan
71 |
72 | # Honggfuzz + UBSAN
73 | build:ubsan-honggfuzz --//fuzzing:cc_engine=//fuzzing/engines:honggfuzz
74 | build:ubsan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=honggfuzz
75 | build:ubsan-honggfuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=ubsan
76 |
77 | # Replay + ASAN
78 | build:asan-replay --//fuzzing:cc_engine=//fuzzing/engines:replay
79 | build:asan-replay --@rules_fuzzing//fuzzing:cc_engine_instrumentation=none
80 | build:asan-replay --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
81 |
82 | # Replay + ASAN + UBSAN
83 | build:asan-ubsan-replay --//fuzzing:cc_engine=//fuzzing/engines:replay
84 | build:asan-ubsan-replay --@rules_fuzzing//fuzzing:cc_engine_instrumentation=none
85 | build:asan-ubsan-replay --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan-ubsan
86 |
87 | build:oss-fuzz --//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:oss_fuzz
88 | build:oss-fuzz --//fuzzing:java_engine=@rules_fuzzing//fuzzing/engines:oss_fuzz_java
89 | build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_instrumentation=oss-fuzz
90 | build:oss-fuzz --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none
91 |
92 | # Jazzer without sanitizer (Java only)
93 | build:jazzer --//fuzzing:java_engine=//fuzzing/engines:jazzer
94 | build:jazzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=jazzer
95 | build:jazzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none
96 | # Workaround for https://github.com/bazelbuild/bazel/issues/11128
97 | build:jazzer --//fuzzing:cc_engine_sanitizer=none
98 |
99 | # Jazzer + ASAN
100 | build:asan-jazzer --//fuzzing:java_engine=//fuzzing/engines:jazzer
101 | build:asan-jazzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=jazzer
102 | build:asan-jazzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
103 | # Workaround for https://github.com/bazelbuild/bazel/issues/11128
104 | build:asan-jazzer --//fuzzing:cc_engine_sanitizer=asan
105 |
106 | # Jazzer + UBSAN
107 | build:ubsan-jazzer --//fuzzing:java_engine=//fuzzing/engines:jazzer
108 | build:ubsan-jazzer --@rules_fuzzing//fuzzing:cc_engine_instrumentation=jazzer
109 | build:ubsan-jazzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=ubsan
110 | # Workaround for https://github.com/bazelbuild/bazel/issues/11128
111 | build:ubsan-jazzer --//fuzzing:cc_engine_sanitizer=ubsan
112 |
113 | # Coverage with Replay (C/C++ only)
114 | coverage --//fuzzing:cc_engine=//fuzzing/engines:replay
115 | coverage --@rules_fuzzing//fuzzing:cc_engine_instrumentation=none
116 | coverage --@rules_fuzzing//fuzzing:cc_engine_sanitizer=none
117 | coverage --instrument_test_targets
118 | coverage --action_env=BAZEL_USE_LLVM_NATIVE_COVERAGE=1
119 | coverage --action_env=GCOV=llvm-profdata
120 | coverage --action_env=BAZEL_LLVM_COV=llvm-cov
121 | coverage --combined_report=lcov
122 | coverage --experimental_use_llvm_covmap
123 | coverage --experimental_generate_llvm_lcov
124 |
--------------------------------------------------------------------------------
/.bazelversion:
--------------------------------------------------------------------------------
1 | 8.0.1
2 |
--------------------------------------------------------------------------------
/.bcr/config.yml:
--------------------------------------------------------------------------------
1 | fixedReleaser:
2 | login: fmeum
3 | email: fabian@meumertzhe.im
4 |
--------------------------------------------------------------------------------
/.bcr/metadata.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "homepage": "https://github.com/bazelbuild/rules_fuzzing",
3 | "maintainers": [
4 | {
5 | "email": "fabian@meumertzhe.im",
6 | "github": "fmeum",
7 | "name": "Fabian Meumertzheim"
8 | }
9 | ],
10 | "versions": [],
11 | "yanked_versions": {}
12 | }
13 |
--------------------------------------------------------------------------------
/.bcr/presubmit.yml:
--------------------------------------------------------------------------------
1 | matrix:
2 | platform: ["macos", "ubuntu2204"]
3 |
4 | tasks:
5 | build_targets:
6 | name: "Build targets"
7 | platform: ${{ platform }}
8 | build_targets:
9 | - "@rules_fuzzing//fuzzing/..."
10 |
11 | bcr_test_module:
12 | module_path: "examples/bzlmod"
13 | matrix:
14 | platform: ["macos", "ubuntu2204"]
15 | bazel: ["6.x", "7.x", "8.x"]
16 | tasks:
17 | run_tests:
18 | name: "Run test module"
19 | platform: ${{ platform }}
20 | bazel: ${{ bazel }}
21 | test_targets:
22 | - "//..."
23 |
--------------------------------------------------------------------------------
/.bcr/source.template.json:
--------------------------------------------------------------------------------
1 | {
2 | "integrity": "",
3 | "strip_prefix": "",
4 | "url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/rules_fuzzing-{VERSION}.tar.gz"
5 | }
6 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: Google
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Expected Behavior
2 |
3 |
4 | ## Actual Behavior
5 |
6 |
7 | ## Steps to Reproduce the Problem
8 |
9 | 1.
10 | 1.
11 | 1.
12 |
13 | ## Specifications
14 |
15 | - Version:
16 | - Platform:
--------------------------------------------------------------------------------
/.github/workflows/bazel_lint.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 |
16 | # Lint Bazel and BUILD files
17 |
18 | name: bazel_lint
19 | on:
20 | push:
21 | paths:
22 | - '**/BUILD'
23 | - '**.bzl'
24 | - '**/BUILD.bazel'
25 | pull_request:
26 | paths:
27 | - '**/BUILD'
28 | - '**.bzl'
29 | - '**/BUILD.bazel'
30 | jobs:
31 | bazel_lint:
32 | runs-on: ubuntu-latest
33 | steps:
34 | - uses: actions/checkout@v1
35 | - uses: actions/setup-go@v2
36 | with:
37 | go-version: '^1.13.1' # The Go version to download (if necessary) and use.
38 | - run: go install github.com/bazelbuild/buildtools/buildifier@latest
39 | - run: buildifier -lint=warn -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD -or -name *.bzl \))
40 |
41 |
--------------------------------------------------------------------------------
/.github/workflows/bazel_test.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | name: Bazel Test
16 |
17 | on:
18 | push:
19 | pull_request:
20 | schedule:
21 | - cron: '0 0 * * *'
22 | workflow_dispatch:
23 | env:
24 | # Run daily CI checks against a very recent Bazel commit, but use the version
25 | # pinned in .bazelrc for regular PR checks.
26 | # This is a hacky workaround for GitHub Action's lack of inline conditionals.
27 | # It is important that the value in the true case is not the empty string,
28 | # see:
29 | # https://github.com/actions/runner/issues/409#issuecomment-1013325196
30 | USE_BAZEL_VERSION: ${{ github.event.schedule != '' && 'last_green' || '' }}
31 |
32 | jobs:
33 | unit_tests:
34 | name: All unit tests
35 | runs-on: ubuntu-20.04
36 | timeout-minutes: 30
37 | steps:
38 | - name: Checkout repository
39 | uses: actions/checkout@v2
40 | - name: Install dependencies
41 | run: |
42 | sudo apt-get update && sudo apt-get install -yq \
43 | clang \
44 | libunwind-dev \
45 | libblocksruntime-dev
46 | - name: Run unit tests
47 | run: |
48 | bazel test --test_tag_filters=-fuzz-test --build_tests_only //...
49 | - name: Run Address Sanitizer tests
50 | run: |
51 | bazel test --test_tag_filters=-fuzz-test --build_tests_only --config=asan //...
52 | fuzzer_run_tests:
53 | name: Brief fuzz test runs (C++)
54 | runs-on: ubuntu-20.04
55 | timeout-minutes: 30
56 | strategy:
57 | matrix:
58 | config: ["asan-libfuzzer", "msan-libfuzzer", "asan-honggfuzz"]
59 | target: ["//examples:empty_fuzz_test_run", "//examples:re2_fuzz_test_run"]
60 | exclude:
61 | # MSAN currently fails on the RE2 target.
62 | - config: "msan-libfuzzer"
63 | target: "//examples:re2_fuzz_test_run"
64 | steps:
65 | - name: Checkout repository
66 | uses: actions/checkout@v2
67 | - name: Install dependencies
68 | run: |
69 | sudo apt-get update && sudo apt-get install -yq \
70 | clang \
71 | libunwind-dev \
72 | libblocksruntime-dev
73 | - name: Run smoke test
74 | run: |
75 | bazel run ${{ matrix.target }} --config=${{ matrix.config }} -- --clean --timeout_secs=5
76 | regression_tests:
77 | name: Regression tests (C++)
78 | runs-on: ubuntu-20.04
79 | timeout-minutes: 30
80 | strategy:
81 | matrix:
82 | config: ["asan-replay", "asan-libfuzzer", "asan-honggfuzz"]
83 | steps:
84 | - name: Checkout repository
85 | uses: actions/checkout@v2
86 | - name: Install dependencies
87 | run: |
88 | sudo apt-get update && sudo apt-get install -yq \
89 | clang \
90 | libunwind-dev \
91 | libblocksruntime-dev
92 | - name: Run regression tests
93 | run: |
94 | bazel test --verbose_failures --test_output=all \
95 | --build_tag_filters=fuzz-test --config=${{ matrix.config }} \
96 | //examples:all
97 | coverage:
98 | name: Coverage gathering (C++)
99 | runs-on: ubuntu-20.04
100 | timeout-minutes: 30
101 | steps:
102 | - name: Checkout repository
103 | uses: actions/checkout@v2
104 | - name: Install dependencies
105 | run: |
106 | sudo apt-get update && sudo apt-get install -yq \
107 | clang \
108 | llvm \
109 | libunwind-dev \
110 | libblocksruntime-dev
111 | - name: Gather coverage
112 | run: |
113 | bazel coverage //examples:re2_fuzz_test
114 | - name: Check coverage report
115 | run: |
116 | grep "SF:examples/re2_fuzz_test.cc" bazel-out/_coverage/_coverage_report.dat
117 | fuzzer_run_tests_java:
118 | name: Brief fuzz test runs (Java)
119 | runs-on: ubuntu-20.04
120 | timeout-minutes: 30
121 | strategy:
122 | matrix:
123 | config: ["jazzer", "asan-jazzer"]
124 | target: ["//examples/java:EmptyFuzzTest_run"]
125 | steps:
126 | - name: Checkout repository
127 | uses: actions/checkout@v2
128 | - name: Install dependencies
129 | run: sudo apt-get update && sudo apt-get install -yq clang
130 | - name: Run smoke test
131 | run: |
132 | bazel run ${{ matrix.target }} --config=${{ matrix.config }} -- --clean --timeout_secs=5
133 | regression_tests_java:
134 | name: Regression tests (Java)
135 | runs-on: ubuntu-20.04
136 | timeout-minutes: 30
137 | strategy:
138 | matrix:
139 | config: ["jazzer", "asan-jazzer"]
140 | steps:
141 | - name: Checkout repository
142 | uses: actions/checkout@v2
143 | - name: Install dependencies
144 | run: sudo apt-get update && sudo apt-get install -yq clang
145 | - name: Run regression tests
146 | run: |
147 | bazel test --verbose_failures --test_output=all \
148 | --build_tag_filters=fuzz-test --config=${{ matrix.config }} \
149 | //examples/java/...
150 | regression_tests_gcc:
151 | name: Regression tests (GCC)
152 | runs-on: ubuntu-20.04
153 | timeout-minutes: 30
154 | steps:
155 | - name: Checkout repository
156 | uses: actions/checkout@v2
157 | - name: Run regression tests with GCC
158 | run: |
159 | bazel test --action_env=CC=gcc --action_env=CXX=g++ \
160 | --verbose_failures --test_output=all \
161 | //examples/...
162 | regression_tests_mac:
163 | name: Regression tests (macOS)
164 | runs-on: macos-latest
165 | timeout-minutes: 30
166 | steps:
167 | - name: Checkout repository
168 | uses: actions/checkout@v2
169 | - name: Run regression tests on macOS
170 | run: |
171 | bazel test --verbose_failures --test_output=all //examples/...
172 | bzlmod_examples_libfuzzer:
173 | name: Bzlmod examples (libFuzzer)
174 | runs-on: ubuntu-20.04
175 | steps:
176 | - name: Checkout repository
177 | uses: actions/checkout@v2
178 | - name: Run regression tests on macOS
179 | run: |
180 | cd examples/bzlmod
181 | bazel test --verbose_failures --test_output=all --@my_rules_fuzzing//fuzzing:cc_engine=@my_rules_fuzzing//fuzzing/engines:libfuzzer //...
182 | bzlmod_examples_replay:
183 | name: Bzlmod examples (replay)
184 | runs-on: ubuntu-20.04
185 | steps:
186 | - name: Checkout repository
187 | uses: actions/checkout@v2
188 | - name: Run regression tests on macOS
189 | run: |
190 | cd examples/bzlmod
191 | bazel test --verbose_failures --test_output=all --@my_rules_fuzzing//fuzzing:cc_engine=@my_rules_fuzzing//fuzzing/engines:replay //...
192 |
--------------------------------------------------------------------------------
/.github/workflows/cpp_lint.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | #
15 |
16 | # Lint C++ files
17 |
18 | name: cpplint
19 | on:
20 | push:
21 | paths:
22 | - '**.cc'
23 | - '**.h'
24 | - '**.cpp'
25 | pull_request:
26 | paths:
27 | - '**.cc'
28 | - '**.h'
29 | - '**.cpp'
30 | jobs:
31 | cpplint:
32 | runs-on: ubuntu-latest
33 | steps:
34 | - uses: actions/checkout@v1
35 | - uses: actions/setup-python@v1
36 | - run: pip install cpplint
37 | - run: cpplint --recursive .
38 |
--------------------------------------------------------------------------------
/.github/workflows/oss_fuzz.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | name: OSS-Fuzz CI Fuzz Test
16 | on:
17 | push:
18 | branches:
19 | - master
20 | pull_request:
21 | schedule:
22 | - cron: '0 0 * * *'
23 |
24 | jobs:
25 | fuzzing:
26 | name: Brief run of OSS-Fuzz fuzzing (C++)
27 | runs-on: ubuntu-latest
28 | timeout-minutes: 60
29 | steps:
30 | - name: Build fuzzers
31 | id: build
32 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
33 | with:
34 | oss-fuzz-project-name: 'bazel-rules-fuzzing-test'
35 | dry-run: false
36 | - name: Run fuzzers
37 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
38 | with:
39 | oss-fuzz-project-name: 'bazel-rules-fuzzing-test'
40 | fuzz-seconds: 60
41 | dry-run: false
42 | - name: Upload crashes
43 | uses: actions/upload-artifact@v4
44 | if: failure() && steps.build.outcome == 'success'
45 | with:
46 | name: artifacts
47 | path: ./out/artifacts
48 |
49 | fuzzing-java:
50 | name: Brief run of OSS-Fuzz fuzzing (Java)
51 | runs-on: ubuntu-latest
52 | timeout-minutes: 60
53 | steps:
54 | - name: Build fuzzers
55 | id: build
56 | uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
57 | with:
58 | oss-fuzz-project-name: 'bazel-rules-fuzzing-test-java'
59 | language: jvm
60 | dry-run: false
61 | - name: Run fuzzers
62 | uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
63 | with:
64 | oss-fuzz-project-name: 'bazel-rules-fuzzing-test-java'
65 | language: jvm
66 | fuzz-seconds: 60
67 | dry-run: false
68 | - name: Upload crashes
69 | uses: actions/upload-artifact@v4
70 | if: failure() && steps.build.outcome == 'success'
71 | with:
72 | name: artifacts
73 | path: ./out/artifacts
74 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Bazel-generated files.
16 | /bazel-*
17 | /examples/bzlmod/bazel-*
18 |
19 | # Visual Studio Code configuration.
20 | /.vscode
21 |
22 | # IntelliSense configuration generated by
23 | # https://github.com/grailbio/bazel-compilation-database
24 | compile_commands.json
25 |
26 | # IntelliJ & CLion
27 | .clwb
28 | .ijwb
29 |
30 | # The Bzlmod lockfile is platform-dependent with Python and thus hard
31 | # to keep up-to-date in CI. It still speeds up local development.
32 | MODULE.bazel.lock
33 |
--------------------------------------------------------------------------------
/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | config_setting(
16 | name = "clang",
17 | flag_values = {"@bazel_tools//tools/cpp:compiler": "clang"},
18 | visibility = ["//:__subpackages__"],
19 | )
20 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | * @asraa @inferno-chromium @fniksic @oliverchang @stefanbucur @xinhaoyuan
16 |
--------------------------------------------------------------------------------
/MODULE.bazel:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | module(
16 | name = "rules_fuzzing",
17 | # Automatically updated during releases by the Publish to BCR app.
18 | version = "0.0.0",
19 | )
20 |
21 | bazel_dep(name = "bazel_features", version = "1.20.0")
22 | bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "com_google_absl")
23 | bazel_dep(name = "bazel_skylib", version = "1.5.0")
24 | bazel_dep(name = "platforms", version = "0.0.8")
25 | bazel_dep(name = "rules_python", version = "0.28.0")
26 | bazel_dep(name = "rules_cc", version = "0.0.17")
27 | bazel_dep(name = "rules_java", version = "6.5.2")
28 | bazel_dep(name = "rules_shell", version = "0.3.0")
29 |
30 | bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc")
31 | bazel_dep(name = "googletest", version = "1.14.0.bcr.1", dev_dependency = True, repo_name = "com_google_googletest")
32 | bazel_dep(name = "re2", version = "2023-11-01", dev_dependency = True)
33 |
34 | non_module_dependencies = use_extension("//fuzzing/private:extensions.bzl", "non_module_dependencies")
35 | use_repo(
36 | non_module_dependencies,
37 | "honggfuzz",
38 | "rules_fuzzing_jazzer",
39 | "rules_fuzzing_jazzer_api",
40 | "rules_fuzzing_oss_fuzz",
41 | )
42 |
43 | SUPPORTED_PYTHON_VERSIONS = [
44 | "3.8",
45 | "3.9",
46 | "3.10",
47 | "3.11",
48 | "3.12",
49 | ]
50 |
51 | python = use_extension("@rules_python//python/extensions:python.bzl", "python")
52 |
53 | [
54 | python.toolchain(
55 | # Required to avoid an error when running as root in OSS-Fuzz.
56 | ignore_root_user_error = True,
57 | is_default = python_version == SUPPORTED_PYTHON_VERSIONS[-1],
58 | python_version = python_version,
59 | )
60 | for python_version in SUPPORTED_PYTHON_VERSIONS
61 | ]
62 |
63 | pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
64 |
65 | [
66 | pip.parse(
67 | extra_pip_args = ["--require-hashes"],
68 | hub_name = "rules_fuzzing_py_deps",
69 | python_version = python_version,
70 | requirements_lock = "//fuzzing:requirements.txt",
71 | )
72 | for python_version in SUPPORTED_PYTHON_VERSIONS
73 | ]
74 |
75 | use_repo(pip, fuzzing_py_deps = "rules_fuzzing_py_deps")
76 |
77 | java_toolchains = use_extension("@rules_java//java:extensions.bzl", "toolchains")
78 | use_repo(java_toolchains, "local_jdk")
79 |
--------------------------------------------------------------------------------
/WORKSPACE:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | workspace(name = "rules_fuzzing")
16 |
17 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
18 |
19 | # Load all external library dependencies.
20 |
21 | load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
22 |
23 | rules_fuzzing_dependencies()
24 |
25 | load("@rules_python//python:repositories.bzl", "py_repositories")
26 |
27 | py_repositories()
28 |
29 | load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
30 |
31 | rules_fuzzing_init()
32 |
33 | load("@fuzzing_py_deps//:requirements.bzl", "install_deps")
34 |
35 | install_deps()
36 |
37 | # The support for running the examples and unit tests.
38 |
39 | http_archive(
40 | name = "re2",
41 | sha256 = "f89c61410a072e5cbcf8c27e3a778da7d6fd2f2b5b1445cd4f4508bee946ab0f",
42 | strip_prefix = "re2-2022-06-01",
43 | url = "https://github.com/google/re2/archive/2022-06-01.tar.gz",
44 | )
45 |
46 | http_archive(
47 | name = "com_google_googletest",
48 | integrity = "sha256-itWYxzrXluDYKAsILOvYKmMNc+c808cAV5OKZQG7pdc=",
49 | strip_prefix = "googletest-1.14.0",
50 | urls = ["https://github.com/google/googletest/archive/refs/tags/v1.14.0.tar.gz"],
51 | )
52 |
53 | # Stardoc dependencies.
54 |
55 | http_archive(
56 | name = "io_bazel_stardoc",
57 | sha256 = "9b09b3ee6181aa4b56c8bc863b1f1c922725298047d243cf19bc69e455ffa7c3",
58 | strip_prefix = "stardoc-5986d24c478e81242627c6d688fdc547567bc93c",
59 | url = "https://github.com/bazelbuild/stardoc/archive/5986d24c478e81242627c6d688fdc547567bc93c.zip",
60 | )
61 |
62 | load("@io_bazel_stardoc//:setup.bzl", "stardoc_repositories")
63 |
64 | stardoc_repositories()
65 |
--------------------------------------------------------------------------------
/WORKSPACE.bzlmod:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Intentionally left blank as all deps are defined in MODULE.bazel.
16 | # By having this file exist, Bazel will not add the repositories defined in the implicit
17 | # "WORKSPACE suffix" with --enable_bzlmod.
18 |
--------------------------------------------------------------------------------
/docs/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Documentation files for the Bazel fuzzing rules.
16 | # To regenerate, run the 'update_docs.sh' script in the root directory.
17 |
18 | # Since the 'bzl_library' rule is currently used only for documentation
19 | # generation, we define all libraries here, to avoid introducing a Skylib
20 | # dependency on our users.
21 | load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
22 | load("@io_bazel_stardoc//stardoc:stardoc.bzl", "stardoc")
23 |
24 | bzl_library(
25 | name = "bazel_skylib",
26 | deps = [
27 | "@bazel_skylib//lib:dicts",
28 | "@bazel_skylib//lib:paths",
29 | "@bazel_skylib//rules:common_settings",
30 | ],
31 | )
32 |
33 | bzl_library(
34 | name = "fuzzing_rules",
35 | srcs = [
36 | "//fuzzing:cc_defs.bzl",
37 | "//fuzzing:instrum_opts.bzl",
38 | "//fuzzing:java_defs.bzl",
39 | "//fuzzing/private:binary.bzl",
40 | "//fuzzing/private:common.bzl",
41 | "//fuzzing/private:engine.bzl",
42 | "//fuzzing/private:fuzz_test.bzl",
43 | "//fuzzing/private:instrum_opts.bzl",
44 | "//fuzzing/private:java_utils.bzl",
45 | "//fuzzing/private:regression.bzl",
46 | "//fuzzing/private:util.bzl",
47 | "//fuzzing/private/oss_fuzz:package.bzl",
48 | "@rules_cc//cc:bzl_srcs",
49 | "@rules_fuzzing_oss_fuzz//:instrum.bzl",
50 | "@rules_java//java:rules",
51 | ],
52 | deps = [
53 | ":bazel_skylib",
54 | ],
55 | )
56 |
57 | stardoc(
58 | name = "cc_fuzzing_docs",
59 | out = "cc-fuzzing-rules.md",
60 | input = "//fuzzing:cc_defs.bzl",
61 | deps = [
62 | ":fuzzing_rules",
63 | ],
64 | )
65 |
66 | stardoc(
67 | name = "java_fuzzing_docs",
68 | out = "java-fuzzing-rules.md",
69 | input = "//fuzzing:java_defs.bzl",
70 | deps = [
71 | ":fuzzing_rules",
72 | ],
73 | )
74 |
--------------------------------------------------------------------------------
/docs/code-of-conduct.md:
--------------------------------------------------------------------------------
1 | # Google Open Source Community Guidelines
2 |
3 | At Google, we recognize and celebrate the creativity and collaboration of open
4 | source contributors and the diversity of skills, experiences, cultures, and
5 | opinions they bring to the projects and communities they participate in.
6 |
7 | Every one of Google's open source projects and communities are inclusive
8 | environments, based on treating all individuals respectfully, regardless of
9 | gender identity and expression, sexual orientation, disabilities,
10 | neurodiversity, physical appearance, body size, ethnicity, nationality, race,
11 | age, religion, or similar personal characteristic.
12 |
13 | We value diverse opinions, but we value respectful behavior more.
14 |
15 | Respectful behavior includes:
16 |
17 | * Being considerate, kind, constructive, and helpful.
18 | * Not engaging in demeaning, discriminatory, harassing, hateful, sexualized, or
19 | physically threatening behavior, speech, and imagery.
20 | * Not engaging in unwanted physical contact.
21 |
22 | Some Google open source projects [may adopt][] an explicit project code of
23 | conduct, which may have additional detailed expectations for participants. Most
24 | of those projects will use our [modified Contributor Covenant][].
25 |
26 | [may adopt]: https://opensource.google/docs/releasing/preparing/#conduct
27 | [modified Contributor Covenant]: https://opensource.google/docs/releasing/template/CODE_OF_CONDUCT/
28 |
29 | ## Resolve peacefully
30 |
31 | We do not believe that all conflict is necessarily bad; healthy debate and
32 | disagreement often yields positive results. However, it is never okay to be
33 | disrespectful.
34 |
35 | If you see someone behaving disrespectfully, you are encouraged to address the
36 | behavior directly with those involved. Many issues can be resolved quickly and
37 | easily, and this gives people more control over the outcome of their dispute.
38 | If you are unable to resolve the matter for any reason, or if the behavior is
39 | threatening or harassing, report it. We are dedicated to providing an
40 | environment where participants feel welcome and safe.
41 |
42 | ## Reporting problems
43 |
44 | Some Google open source projects may adopt a project-specific code of conduct.
45 | In those cases, a Google employee will be identified as the Project Steward,
46 | who will receive and handle reports of code of conduct violations. In the event
47 | that a project hasn’t identified a Project Steward, you can report problems by
48 | emailing opensource@google.com.
49 |
50 | We will investigate every complaint, but you may not receive a direct response.
51 | We will use our discretion in determining when and how to follow up on reported
52 | incidents, which may range from not taking action to permanent expulsion from
53 | the project and project-sponsored spaces. We will notify the accused of the
54 | report and provide them an opportunity to discuss it before any action is
55 | taken. The identity of the reporter will be omitted from the details of the
56 | report supplied to the accused. In potentially harmful situations, such as
57 | ongoing harassment or threats to anyone's safety, we may take action without
58 | notice.
59 |
60 | *This document was adapted from the [IndieWeb Code of Conduct][] and can also
61 | be found at .*
62 |
63 | [IndieWeb Code of Conduct]: https://indieweb.org/code-of-conduct
64 |
--------------------------------------------------------------------------------
/docs/contributing.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution;
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
24 |
25 | ## Community Guidelines
26 |
27 | This project follows [Google's Open Source Community
28 | Guidelines](https://opensource.google/conduct/).
29 |
--------------------------------------------------------------------------------
/examples/BUILD:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2020 Google LLC
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | # Simple fuzz targets that demonstrate the Bazel extension functionality and
17 | # serve as regression tests. Targets that are expected to crash or hang are
18 | # disabled in the OSS-Fuzz integration using the "no-oss-fuzz" tag.
19 |
20 | load("//fuzzing:cc_defs.bzl", "cc_fuzz_test")
21 |
22 | cc_fuzz_test(
23 | name = "empty_fuzz_test",
24 | size = "small",
25 | srcs = ["empty_fuzz_test.cc"],
26 | )
27 |
28 | filegroup(
29 | name = "corpus_filegroup",
30 | srcs = ["corpus_1.txt"] + glob(["corpus_dir/**"]),
31 | )
32 |
33 | # This target shows how to create a fuzz test target with corpus files.
34 | cc_fuzz_test(
35 | name = "empty_fuzz_test_with_corpus",
36 | timeout = "short",
37 | srcs = ["empty_fuzz_test.cc"],
38 | corpus = [
39 | "corpus_0.txt",
40 | ":corpus_filegroup",
41 | ] + glob(["test_corpus_dir/**"]),
42 | )
43 |
44 | # This target shows how to create a fuzz test target with dictionaries.
45 | cc_fuzz_test(
46 | name = "empty_fuzz_test_with_dict",
47 | srcs = ["empty_fuzz_test.cc"],
48 | corpus = [
49 | "corpus_0.txt",
50 | ":corpus_filegroup",
51 | ] + glob(["test_corpus_dir/**"]),
52 | dicts = [
53 | "dictionaries/valid_part1.dict",
54 | "dictionaries/valid_part2.dict",
55 | ],
56 | )
57 |
58 | cc_fuzz_test(
59 | name = "fuzzed_data_provider_fuzz_test",
60 | srcs = ["fuzzed_data_provider_fuzz_test.cc"],
61 | target_compatible_with = select({
62 | "//:clang": [],
63 | "//conditions:default": ["@platforms//:incompatible"],
64 | }),
65 | )
66 |
67 | cc_fuzz_test(
68 | name = "hang_fuzz_test",
69 | srcs = ["hang_fuzz_test.cc"],
70 | tags = [
71 | "manual",
72 | "no-oss-fuzz",
73 | ],
74 | )
75 |
76 | cc_fuzz_test(
77 | name = "input_buffer_overflow_fuzz_test",
78 | srcs = ["input_buffer_overflow_fuzz_test.cc"],
79 | tags = [
80 | "no-oss-fuzz",
81 | ],
82 | )
83 |
84 | # This test is designed to trigger an uninitialized memory issue.
85 | cc_fuzz_test(
86 | name = "msan_fuzz_test",
87 | srcs = ["msan_fuzz_test.cc"],
88 | copts = ["-Wno-uninitialized"],
89 | tags = [
90 | "no-oss-fuzz",
91 | ],
92 | )
93 |
94 | cc_fuzz_test(
95 | name = "new_buffer_overflow_fuzz_test",
96 | srcs = ["new_buffer_overflow_fuzz_test.cc"],
97 | tags = [
98 | "no-oss-fuzz",
99 | ],
100 | )
101 |
102 | cc_fuzz_test(
103 | name = "oom_fuzz_test",
104 | srcs = ["oom_fuzz_test.cc"],
105 | tags = [
106 | "manual",
107 | "no-oss-fuzz",
108 | ],
109 | )
110 |
111 | cc_fuzz_test(
112 | name = "re2_fuzz_test",
113 | srcs = ["re2_fuzz_test.cc"],
114 | deps = [
115 | "@re2",
116 | ],
117 | )
118 |
119 | cc_fuzz_test(
120 | name = "runfiles_fuzz_test",
121 | srcs = ["runfiles_fuzz_test.cc"],
122 | data = [
123 | ":corpus_0.txt",
124 | ],
125 | deps = [
126 | "@bazel_tools//tools/cpp/runfiles",
127 | ],
128 | )
129 |
130 | cc_fuzz_test(
131 | name = "ubsan_int_overflow_fuzz_test",
132 | srcs = ["ubsan_int_overflow_fuzz_test.cc"],
133 | tags = [
134 | "no-oss-fuzz",
135 | ],
136 | )
137 |
138 | cc_fuzz_test(
139 | name = "ubsan_function_ptr_fuzz_test",
140 | srcs = ["ubsan_function_ptr_fuzz_test.cc"],
141 | tags = [
142 | "no-oss-fuzz",
143 | ],
144 | )
145 |
--------------------------------------------------------------------------------
/examples/bzlmod/.bazelrc:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | common --repo_env=CC=clang
16 | common --@my_rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
17 | common --@my_rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
18 |
--------------------------------------------------------------------------------
/examples/bzlmod/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | load("@my_rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
16 | load("@my_rules_fuzzing//fuzzing:java_defs.bzl", "java_fuzz_test")
17 |
18 | cc_fuzz_test(
19 | name = "cc_fuzz_test",
20 | srcs = ["cc_fuzz_test.cc"],
21 | )
22 |
23 | java_fuzz_test(
24 | name = "java_fuzz_test",
25 | srcs = ["JavaFuzzTest.java"],
26 | target_class = "com.example.JavaFuzzTest",
27 | )
28 |
--------------------------------------------------------------------------------
/examples/bzlmod/JavaFuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A plain fuzz target that does nothing.
16 |
17 | package com.example;
18 |
19 | import com.code_intelligence.jazzer.api.FuzzedDataProvider;
20 |
21 | public class JavaFuzzTest {
22 | public static void fuzzerTestOneInput(FuzzedDataProvider data) {}
23 | }
24 |
--------------------------------------------------------------------------------
/examples/bzlmod/MODULE.bazel:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # We use a custom repo_name to verify that e.g. macros do not contain hard-coded
16 | # references to rules_fuzzing.
17 | bazel_dep(name = "rules_fuzzing", repo_name = "my_rules_fuzzing")
18 | local_path_override(
19 | module_name = "rules_fuzzing",
20 | path = "../..",
21 | )
22 |
--------------------------------------------------------------------------------
/examples/bzlmod/WORKSPACE.bzlmod:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Intentionally left blank as all deps are defined in MODULE.bazel.
16 | # By having this file exist, Bazel will not add the repositories defined in the implicit
17 | # "WORKSPACE suffix" with --enable_bzlmod.
18 |
--------------------------------------------------------------------------------
/examples/bzlmod/cc_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A plain fuzz target that does nothing (just returns).
16 |
17 | #include
18 | #include
19 |
20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
21 | return 0;
22 | }
23 |
--------------------------------------------------------------------------------
/examples/corpus_0.txt:
--------------------------------------------------------------------------------
1 | test
2 |
--------------------------------------------------------------------------------
/examples/corpus_1.txt:
--------------------------------------------------------------------------------
1 | hello
2 |
--------------------------------------------------------------------------------
/examples/corpus_dir/corpus_2.txt:
--------------------------------------------------------------------------------
1 | world
2 |
--------------------------------------------------------------------------------
/examples/corpus_dir/corpus_3.txt:
--------------------------------------------------------------------------------
1 | !
2 |
--------------------------------------------------------------------------------
/examples/corpus_dir/secondary_dir/corpus_4.txt:
--------------------------------------------------------------------------------
1 | Hello corpus!
2 |
--------------------------------------------------------------------------------
/examples/dictionaries/invalid.dict:
--------------------------------------------------------------------------------
1 | Invalid dictionary entries
2 | "
3 | "\A"
--------------------------------------------------------------------------------
/examples/dictionaries/valid_part1.dict:
--------------------------------------------------------------------------------
1 | # This is the first part of the example dictionary.
2 | # Lines starting with '#' and empty lines are ignored.
3 |
4 | # Adds "blah" (w/o quotes) to the dictionary.
5 | kw1="blah"
6 | # Use \\ for backslash and \" for quotes.
7 | kw2="\"ac\\dc\""
8 | # Use \xAB for hex values
9 | kw3="\xF7\xF8"
10 | # the name of the keyword followed by '=' may be omitted:
11 | "foo\x0Abar"
12 | "ab\""
13 |
--------------------------------------------------------------------------------
/examples/dictionaries/valid_part2.dict:
--------------------------------------------------------------------------------
1 | # This is the second part of the example dictionary.
2 | ":path"
3 | ":method"
4 | ":scheme"
5 | ":status"
6 | ":authority"
7 | "host"
8 | "keep-alive"
9 | ":protocol"
10 | "set-cookie"
11 | "upgrade"
12 | "via"
13 | "te"
14 | "user-agent"
15 | "content-length"
16 | "chunked"
17 | "transfer-encoding"
18 |
--------------------------------------------------------------------------------
/examples/empty_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A plain fuzz target that does nothing (just returns).
16 |
17 | #include
18 | #include
19 |
20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
21 | return 0;
22 | }
23 |
--------------------------------------------------------------------------------
/examples/fuzzed_data_provider_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that demonstrates the use of FuzzeddataProvider.
16 |
17 | #include
18 | #include
19 |
20 | // Workaround for
21 | // https://github.com/llvm/llvm-project/commit/0cccccf0d2cbd707503263785f9a0407d3e2bd5ea
22 | // causing missing symbol errors in the FuzzedDataProvider.h header with
23 | // clang 10.
24 | // FIXME: Remove once a clang release ships with this commit.
25 | #include
26 | #include // NOLINT
27 |
28 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29 | FuzzedDataProvider fuzzed_data(data, size);
30 |
31 | const auto first_part_size = fuzzed_data.ConsumeIntegral();
32 | std::vector first_part =
33 | fuzzed_data.ConsumeBytes(first_part_size);
34 | std::vector second_part =
35 | fuzzed_data.ConsumeRemainingBytes();
36 |
37 | return 0;
38 | }
39 |
--------------------------------------------------------------------------------
/examples/hang_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that hangs.
16 |
17 | #include
18 | #include
19 |
20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
21 | while (true) {}
22 |
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/examples/input_buffer_overflow_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | void TriggerBufferOverflow(const uint8_t *data, size_t size) {
20 | if (size >= 3 && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z' &&
21 | data[size] == 'Z') {
22 | fprintf(stderr, "BUFFER OVERFLOW!\n");
23 | }
24 | }
25 |
26 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
27 | TriggerBufferOverflow(data, size);
28 | return 0;
29 | }
30 |
--------------------------------------------------------------------------------
/examples/java/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Simple fuzz targets that demonstrate the Bazel extension functionality and
16 | # serve as regression tests. Targets that are expected to crash or hang are
17 | # disabled in the OSS-Fuzz integration using the "no-oss-fuzz" tag.
18 |
19 | load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
20 | load("@rules_cc//cc:cc_library.bzl", "cc_library")
21 | load("//fuzzing:java_defs.bzl", "java_fuzz_test")
22 |
23 | filegroup(
24 | name = "corpus",
25 | srcs = [
26 | "corpus_0.txt",
27 | "corpus_1.txt",
28 | ],
29 | )
30 |
31 | java_fuzz_test(
32 | name = "EmptyFuzzTest",
33 | size = "small",
34 | srcs = ["com/example/EmptyFuzzTest.java"],
35 | corpus = [
36 | "corpus_0.txt",
37 | ],
38 | )
39 |
40 | java_fuzz_test(
41 | name = "FuzzTest",
42 | timeout = "short",
43 | srcs = ["com/example/FuzzTest.java"],
44 | tags = [
45 | "no-oss-fuzz",
46 | ],
47 | )
48 |
49 | java_fuzz_test(
50 | name = "NativeFuzzTest",
51 | srcs = ["com/example/NativeFuzzTest.java"],
52 | corpus = [
53 | ":corpus",
54 | ],
55 | tags = [
56 | "no-oss-fuzz",
57 | ],
58 | # The JVM expects a native library on macOS to have the .dylib extension,
59 | # but due to a bug in Bazel the shared library extension defaults to .so
60 | # there. This can be worked around by specifying the desired extension in
61 | # the name of the rule and selecting the correct one based on the platform.
62 | # See https://github.com/bazelbuild/bazel/issues/11082.
63 | deps = select({
64 | "@platforms//os:macos": [":libnative.dylib"],
65 | "//conditions:default": [":native"],
66 | }),
67 | )
68 |
69 | # A Java fuzz test with a native library, both of which have declared data
70 | # dependencies that they can access at runtime.
71 | java_fuzz_test(
72 | name = "NativeRunfileFuzzTest",
73 | srcs = ["com/example/NativeRunfileFuzzTest.java"],
74 | data = [
75 | "corpus_0.txt",
76 | ],
77 | # See NativeFuzzTest for why this uses a select.
78 | deps = select({
79 | "@platforms//os:macos": [":libnative_runfile.dylib"],
80 | "//conditions:default": [":native_runfile"],
81 | }) + [
82 | "@bazel_tools//tools/java/runfiles",
83 | ],
84 | )
85 |
86 | # A Java fuzz test with a native library that calls a function through a pointer
87 | # of an incorrect type, which is detected by UBSan.
88 | java_fuzz_test(
89 | name = "NativeUbsanFuncPtrFuzzTest",
90 | srcs = ["com/example/NativeUbsanFuncPtrFuzzTest.java"],
91 | deps = select({
92 | "@platforms//os:macos": [":libnative_ubsan_func_ptr.dylib"],
93 | "//conditions:default": [":native_ubsan_func_ptr"],
94 | }),
95 | )
96 |
97 | # A native library that interfaces with Java through the JNI.
98 | # It contains an out-of-bounds read is detected by ASan.
99 | cc_binary(
100 | name = "native",
101 | # Build as a shared library that can be loaded by a Java application at
102 | # runtime via System.loadLibrary().
103 | linkshared = True,
104 | tags = ["manual"],
105 | deps = [
106 | ":native_lib",
107 | ],
108 | )
109 |
110 | # The same shared library as :native, but with the correct extension for macOS.
111 | # See the comment on :NativeFuzzTest for why this is needed.
112 | cc_binary(
113 | name = "libnative.dylib",
114 | linkshared = True,
115 | tags = ["manual"],
116 | deps = [
117 | ":native_lib",
118 | ],
119 | )
120 |
121 | # The implementation shared by :native and :libnative.dylib, which differ only
122 | # in the name of the resulting shared library.
123 | cc_library(
124 | name = "native_lib",
125 | srcs = [
126 | "com/example/NativeFuzzTest.cpp",
127 | "com/example/NativeFuzzTest.h",
128 | ],
129 | deps = [
130 | "@bazel_tools//tools/jdk:jni",
131 | ],
132 | # Required because :native and :libnative.dylib to not reference any symbols
133 | # of this library, which means that it wouldn't be linked at all without
134 | # this.
135 | alwayslink = True,
136 | )
137 |
138 | # A shared library that demonstrates that fuzz targets can find their Bazel
139 | # data dependencies at runtime, both from Java and native code.
140 | cc_binary(
141 | name = "native_runfile",
142 | linkshared = True,
143 | tags = ["manual"],
144 | deps = [
145 | ":native_runfile_lib",
146 | ],
147 | )
148 |
149 | # The same shared library as :native_runfile, but with the correct extension for
150 | # macOS. See the comment on :NativeFuzzTest for why this is needed.
151 | cc_binary(
152 | name = "libnative_runfile.dylib",
153 | linkshared = True,
154 | tags = ["manual"],
155 | deps = [
156 | ":native_runfile_lib",
157 | ],
158 | )
159 |
160 | cc_library(
161 | name = "native_runfile_lib",
162 | srcs = [
163 | "com/example/NativeRunfileFuzzTest.cpp",
164 | "com/example/NativeRunfileFuzzTest.h",
165 | ],
166 | data = [
167 | "corpus_1.txt",
168 | ],
169 | deps = [
170 | "@bazel_tools//tools/cpp/runfiles",
171 | "@bazel_tools//tools/jdk:jni",
172 | ],
173 | alwayslink = True,
174 | )
175 |
176 | cc_binary(
177 | name = "native_ubsan_func_ptr",
178 | linkshared = True,
179 | tags = ["manual"],
180 | deps = [
181 | ":native_ubsan_func_ptr_lib",
182 | ],
183 | )
184 |
185 | cc_binary(
186 | name = "libnative_ubsan_func_ptr.dylib",
187 | linkshared = True,
188 | tags = ["manual"],
189 | deps = [
190 | ":native_ubsan_func_ptr_lib",
191 | ],
192 | )
193 |
194 | cc_library(
195 | name = "native_ubsan_func_ptr_lib",
196 | srcs = [
197 | "com/example/NativeUbsanFuncPtrFuzzTest.cpp",
198 | "com/example/NativeUbsanFuncPtrFuzzTest.h",
199 | ],
200 | deps = [
201 | "@bazel_tools//tools/jdk:jni",
202 | ],
203 | alwayslink = True,
204 | )
205 |
--------------------------------------------------------------------------------
/examples/java/com/example/EmptyFuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example;
16 |
17 | public class EmptyFuzzTest {
18 | public static void fuzzerTestOneInput(byte[] input) {
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/java/com/example/FuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example;
16 |
17 | import com.code_intelligence.jazzer.api.FuzzedDataProvider;
18 | import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium;
19 |
20 | public class FuzzTest {
21 | public static void fuzzerInitialize() {
22 | // Optional initialization to be run before the first call to fuzzerTestOneInput.
23 | }
24 |
25 | public static void fuzzerTestOneInput(FuzzedDataProvider data) {
26 | String input = data.consumeRemainingAsString();
27 | if (input.startsWith("magicstring") && input.length() > 30
28 | && input.charAt(25) == 'C') {
29 | mustNeverBeCalled();
30 | }
31 | }
32 |
33 | private static void mustNeverBeCalled() {
34 | throw new FuzzerSecurityIssueMedium("mustNeverBeCalled has been called");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeFuzzTest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "NativeFuzzTest.h"
16 |
17 | #include
18 |
19 | __attribute__((optnone)) void parseInternal(const std::string &input) {
20 | if (input[0] == 'a' && input[1] == 'b' && input[5] == 'c') {
21 | if (input.find("secret_in_native_library") != std::string::npos) {
22 | // Read past null byte to trigger an OOB read.
23 | if (input[input.size() + 1] != 0x12) {
24 | return;
25 | }
26 | }
27 | }
28 | }
29 |
30 | JNIEXPORT jboolean JNICALL Java_com_example_NativeFuzzTest_parse(
31 | JNIEnv *env, jobject o, jstring bytes) {
32 | const char *input(env->GetStringUTFChars(bytes, nullptr));
33 | parseInternal(input);
34 | env->ReleaseStringUTFChars(bytes, input);
35 | return false;
36 | }
37 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeFuzzTest.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | /* Header for class com_example_NativeFuzzTest */
17 |
18 | #ifndef EXAMPLES_JAVA_COM_EXAMPLE_NATIVEFUZZTEST_H_
19 | #define EXAMPLES_JAVA_COM_EXAMPLE_NATIVEFUZZTEST_H_
20 | #ifdef __cplusplus
21 | extern "C" {
22 | #endif
23 | /*
24 | * Class: com_example_NativeFuzzTest
25 | * Method: parse
26 | * Signature: (Ljava/lang/String;)Z
27 | */
28 | JNIEXPORT jboolean JNICALL
29 | Java_com_example_NativeFuzzTest_parse(JNIEnv *, jobject, jstring);
30 |
31 | #ifdef __cplusplus
32 | }
33 | #endif
34 | #endif // EXAMPLES_JAVA_COM_EXAMPLE_NATIVEFUZZTEST_H_
35 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeFuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example;
16 |
17 | import com.code_intelligence.jazzer.api.FuzzedDataProvider;
18 |
19 | public class NativeFuzzTest {
20 | static {
21 | System.loadLibrary("native");
22 | }
23 |
24 | public static void fuzzerTestOneInput(FuzzedDataProvider data) {
25 | int val = data.consumeInt();
26 | String stringData = data.consumeRemainingAsString();
27 | if (val == 17759716 && stringData.length() > 10 && stringData.contains("jazzer")) {
28 | // call native function which contains a crash
29 | new com.example.NativeFuzzTest().parse(stringData);
30 | }
31 | }
32 |
33 | private native boolean parse(String bytes);
34 | }
35 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeRunfileFuzzTest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "NativeRunfileFuzzTest.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "tools/cpp/runfiles/runfiles.h"
23 |
24 | JNIEXPORT void JNICALL
25 | Java_com_example_NativeRunfileFuzzTest_loadCppRunfile(JNIEnv *env,
26 | jobject o) {
27 | using ::bazel::tools::cpp::runfiles::Runfiles;
28 | std::string error;
29 | auto runfiles = std::unique_ptr(Runfiles::Create("", &error));
30 | if (runfiles == nullptr) {
31 | std::cerr << error;
32 | abort();
33 | }
34 | std::string path =
35 | runfiles->Rlocation("rules_fuzzing/examples/java/corpus_1.txt");
36 | if (path.empty()) abort();
37 | std::ifstream in(path);
38 | if (!in.good()) abort();
39 | }
40 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeRunfileFuzzTest.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | /* Header for class com_example_NativeRunfileFuzzTest */
17 |
18 | #ifndef EXAMPLES_JAVA_COM_EXAMPLE_NATIVERUNFILEFUZZTEST_H_
19 | #define EXAMPLES_JAVA_COM_EXAMPLE_NATIVERUNFILEFUZZTEST_H_
20 | #ifdef __cplusplus
21 | extern "C" {
22 | #endif
23 | /*
24 | * Class: com_example_NativeRunfileFuzzTest
25 | * Method: loadCppRunfile
26 | * Signature: ()V
27 | */
28 | JNIEXPORT void JNICALL
29 | Java_com_example_NativeRunfileFuzzTest_loadCppRunfile(JNIEnv *, jobject);
30 |
31 | #ifdef __cplusplus
32 | }
33 | #endif
34 | #endif // EXAMPLES_JAVA_COM_EXAMPLE_NATIVERUNFILEFUZZTEST_H_
35 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeRunfileFuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example;
16 |
17 | import com.code_intelligence.jazzer.api.FuzzedDataProvider;
18 | import com.google.devtools.build.runfiles.Runfiles;
19 |
20 | import java.io.IOException;
21 | import java.io.File;
22 |
23 | public class NativeRunfileFuzzTest {
24 |
25 | static {
26 | System.loadLibrary("native_runfile");
27 | }
28 |
29 | public static void fuzzerTestOneInput(FuzzedDataProvider data) throws IOException {
30 | if (data.consumeBoolean()) {
31 | loadJavaRunfile();
32 | } else {
33 | loadCppRunfile();
34 | }
35 | }
36 |
37 | private static void loadJavaRunfile() throws IOException {
38 | Runfiles runfiles = Runfiles.create();
39 | String path = runfiles.rlocation("rules_fuzzing/examples/java/corpus_0.txt");
40 | File runfile = new File(path);
41 | if (!runfile.exists()) {
42 | throw new IOException("Java runfile not found");
43 | }
44 | }
45 |
46 | private static native void loadCppRunfile();
47 | }
48 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeUbsanFuncPtrFuzzTest.cpp:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // parse calls a function through a pointer of a mismatched type. This is
16 | // detected by UBSAN's function check.
17 |
18 | #include "NativeUbsanFuncPtrFuzzTest.h"
19 |
20 | #include
21 | #include
22 |
23 | int parse_data(const uint16_t *data) {
24 | return data[0] + data[1];
25 | }
26 |
27 | int (*mistyped_function_pointer)(const char *data);
28 |
29 | JNIEXPORT int JNICALL Java_com_example_NativeUbsanFuncPtrFuzzTest_parse(
30 | JNIEnv *env, jobject o, jstring bytes) {
31 | const char *input(env->GetStringUTFChars(bytes, nullptr));
32 | mistyped_function_pointer =
33 | reinterpret_cast(&parse_data);
34 | int result = mistyped_function_pointer(input);
35 | env->ReleaseStringUTFChars(bytes, input);
36 | return result;
37 | }
38 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeUbsanFuncPtrFuzzTest.h:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | /* Header for class com_example_NativeUbsanFuncPtrFuzzTest */
17 |
18 | #ifndef EXAMPLES_JAVA_COM_EXAMPLE_NATIVEUBSANFUNCPTRFUZZTEST_H_
19 | #define EXAMPLES_JAVA_COM_EXAMPLE_NATIVEUBSANFUNCPTRFUZZTEST_H_
20 | #ifdef __cplusplus
21 | extern "C" {
22 | #endif
23 | /*
24 | * Class: com_example_NativeUbsanFuncPtrFuzzTest
25 | * Method: parse
26 | * Signature: (Ljava/lang/String;)I
27 | */
28 | JNIEXPORT int JNICALL
29 | Java_com_example_NativeUbsanFuncPtrFuzzTest_parse(JNIEnv *, jobject, jstring);
30 |
31 | #ifdef __cplusplus
32 | }
33 | #endif
34 | #endif // EXAMPLES_JAVA_COM_EXAMPLE_NATIVEUBSANFUNCPTRFUZZTEST_H_
35 |
--------------------------------------------------------------------------------
/examples/java/com/example/NativeUbsanFuncPtrFuzzTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | package com.example;
16 |
17 | import com.code_intelligence.jazzer.api.FuzzedDataProvider;
18 |
19 | // The native function parse calls a function through a pointer of a mismatched
20 | // type. This is detected by UBSAN's function check.
21 | public class NativeUbsanFuncPtrFuzzTest {
22 |
23 | static {
24 | System.loadLibrary("native_ubsan_func_ptr");
25 | }
26 |
27 | public static void fuzzerTestOneInput(FuzzedDataProvider data) {
28 | String stringData = data.consumeRemainingAsString();
29 | if (stringData.length() > 10) {
30 | parse(stringData);
31 | }
32 | }
33 |
34 | private static native void parse(String data);
35 | }
36 |
--------------------------------------------------------------------------------
/examples/java/corpus_0.txt:
--------------------------------------------------------------------------------
1 | hello
2 |
--------------------------------------------------------------------------------
/examples/java/corpus_1.txt:
--------------------------------------------------------------------------------
1 | java
2 |
--------------------------------------------------------------------------------
/examples/msan_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that causes an MSAN error (e.g., uninitialized variables).
16 |
17 | #include
18 | #include
19 |
20 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
21 | int a;
22 | if (a) ++a;
23 | return 0;
24 | }
25 |
--------------------------------------------------------------------------------
/examples/new_buffer_overflow_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | void TriggerBufferOverflow(const uint8_t *data, size_t size) {
21 | if (size >= 3 && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z' &&
22 | data[size] == 'Z') {
23 | fprintf(stderr, "BUFFER OVERFLOW!\n");
24 | }
25 | }
26 |
27 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
28 | uint8_t *data_copy = new uint8_t[size];
29 | memcpy(data_copy, data, size);
30 | TriggerBufferOverflow(data_copy, size);
31 | delete[] data_copy;
32 | return 0;
33 | }
34 |
--------------------------------------------------------------------------------
/examples/oom_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that creates a memory leak and causes OOM errors.
16 |
17 | #include
18 | #include
19 |
20 | void LeakMemory() {
21 | int* zombie_ptr = new int(100);
22 | zombie_ptr[0] = 0;
23 | }
24 |
25 | void TriggerOomError() {
26 | for (size_t i = 0; i < (1 << 30); ++i) {
27 | LeakMemory();
28 | }
29 | }
30 |
31 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
32 | TriggerOomError();
33 | return 0;
34 | }
35 |
--------------------------------------------------------------------------------
/examples/re2_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // This is a very basic fuzz test for RE2, for illustrative purposes.
16 | // See RE2's own fuzz tests for real-world examples that follow best practices,
17 | // e.g.: https://github.com/google/re2/blob/master/re2/fuzzing/re2_fuzzer.cc
18 |
19 | #include
20 | #include
21 | #include
22 |
23 | #include "re2/re2.h"
24 |
25 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
26 | RE2 re(std::string(reinterpret_cast(data), size), RE2::Quiet);
27 | return 0;
28 | }
29 |
--------------------------------------------------------------------------------
/examples/runfiles_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that exits if it doesn't find a declared runfile.
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 |
24 | #include "tools/cpp/runfiles/runfiles.h"
25 |
26 | using ::bazel::tools::cpp::runfiles::Runfiles;
27 |
28 | namespace {
29 | Runfiles *runfiles = nullptr;
30 | }
31 |
32 | extern "C" void LLVMFuzzerInitialize(int *argc, char ***argv) {
33 | std::string error;
34 | runfiles = Runfiles::Create((*argv)[0], &error);
35 | if (runfiles == nullptr) {
36 | std::cerr << error;
37 | abort();
38 | }
39 | }
40 |
41 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
42 | std::string path = runfiles->Rlocation("rules_fuzzing/examples/corpus_0.txt");
43 | if (path.empty()) abort();
44 | std::ifstream in(path);
45 | if (!in.good()) abort();
46 | return 0;
47 | }
48 |
--------------------------------------------------------------------------------
/examples/test_corpus_dir/corpus_0.txt:
--------------------------------------------------------------------------------
1 | Another corpus
2 |
--------------------------------------------------------------------------------
/examples/ubsan_function_ptr_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that calls a function through a pointer of a mismatched type.
16 | // This is detected by UBSAN's function check and requires the UBSAN C++
17 | // runtime.
18 |
19 | #include
20 | #include
21 |
22 | int parse_data(const uint16_t *data) {
23 | return data[0] + data[1];
24 | }
25 |
26 | int (*mistyped_function_pointer)(const uint8_t *data);
27 |
28 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
29 | if (size < 2) {
30 | return 0;
31 | }
32 | mistyped_function_pointer =
33 | reinterpret_cast(parse_data);
34 | mistyped_function_pointer(data);
35 | return 0;
36 | }
37 |
--------------------------------------------------------------------------------
/examples/ubsan_int_overflow_fuzz_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // A fuzz target that triggers a signed integer overflow, which is undefined
16 | // behavior and detected by UBSAN's signed-integer-overflow check.
17 |
18 | #include
19 | #include
20 |
21 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
22 | if (size == 0) {
23 | return 0;
24 | }
25 | int k = 0x7fffffff;
26 | k += data[0];
27 | // Use k.
28 | return k & 0;
29 | }
30 |
--------------------------------------------------------------------------------
/fuzzing/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
16 |
17 | label_flag(
18 | name = "cc_engine",
19 | build_setting_default = "//fuzzing/engines:replay",
20 | visibility = ["//visibility:public"],
21 | )
22 |
23 | label_flag(
24 | name = "java_engine",
25 | build_setting_default = "//fuzzing/engines:jazzer",
26 | visibility = ["//visibility:public"],
27 | )
28 |
29 | string_flag(
30 | name = "cc_engine_instrumentation",
31 | build_setting_default = "none",
32 | values = [
33 | "none",
34 | "libfuzzer",
35 | "jazzer",
36 | "honggfuzz",
37 | "oss-fuzz",
38 | ],
39 | visibility = ["//visibility:public"],
40 | )
41 |
42 | string_flag(
43 | name = "cc_engine_sanitizer",
44 | build_setting_default = "none",
45 | values = [
46 | # No sanitizer instrumentation.
47 | "none",
48 | # Address sanitizer (ASAN).
49 | # See https://clang.llvm.org/docs/AddressSanitizer.html
50 | "asan",
51 | # Memory sanitizer (MSAN).
52 | # See https://clang.llvm.org/docs/MemorySanitizer.html
53 | "msan",
54 | # MSAN + origin tracking enabled.
55 | # Useful for debugging crash reproducers, 1.5-2x slower.
56 | "msan-origin-tracking",
57 | # Undefined Behavior sanitizer (UBSAN).
58 | # See https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
59 | "ubsan",
60 | # ASAN + UBSAN in a single build.
61 | "asan-ubsan",
62 | ],
63 | visibility = ["//visibility:public"],
64 | )
65 |
66 | # If set, define the FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION macro
67 | # during compilation.
68 | #
69 | # See https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode
70 | bool_flag(
71 | name = "cc_fuzzing_build_mode",
72 | build_setting_default = True,
73 | visibility = ["//visibility:public"],
74 | )
75 |
76 | exports_files([
77 | "cc_defs.bzl",
78 | "java_defs.bzl",
79 | "instrum_opts.bzl",
80 | ])
81 |
--------------------------------------------------------------------------------
/fuzzing/cc_defs.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Public definitions for fuzzing rules.
16 |
17 | Definitions outside this file are private unless otherwise noted, and may
18 | change without notice.
19 | """
20 |
21 | load(
22 | "//fuzzing/private:engine.bzl",
23 | _FuzzingEngineInfo = "FuzzingEngineInfo",
24 | _cc_fuzzing_engine = "cc_fuzzing_engine",
25 | )
26 | load(
27 | "//fuzzing/private:fuzz_test.bzl",
28 | _cc_fuzz_test = "cc_fuzz_test",
29 | _fuzzing_decoration = "fuzzing_decoration",
30 | )
31 |
32 | cc_fuzz_test = _cc_fuzz_test
33 | cc_fuzzing_engine = _cc_fuzzing_engine
34 |
35 | fuzzing_decoration = _fuzzing_decoration
36 |
37 | FuzzingEngineInfo = _FuzzingEngineInfo
38 |
--------------------------------------------------------------------------------
/fuzzing/engines/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | load("@rules_cc//cc:cc_library.bzl", "cc_library")
16 | load("@rules_java//java:java_library.bzl", "java_library")
17 | load("//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
18 | load("//fuzzing:java_defs.bzl", "java_fuzzing_engine")
19 |
20 | # libFuzzer specification.
21 | ##########################
22 |
23 | cc_fuzzing_engine(
24 | name = "libfuzzer",
25 | display_name = "libFuzzer",
26 | launcher = "libfuzzer_launcher.sh",
27 | library = ":libfuzzer_stub",
28 | visibility = ["//visibility:public"],
29 | )
30 |
31 | cc_library(
32 | name = "libfuzzer_stub",
33 | linkopts = [
34 | # We add the linker options to the library, so only the fuzz test binary
35 | # is linked with libfuzzer.
36 | "-fsanitize=fuzzer",
37 | ],
38 | )
39 |
40 | # Honggfuzz specification.
41 | ##########################
42 |
43 | cc_fuzzing_engine(
44 | name = "honggfuzz",
45 | display_name = "Honggfuzz",
46 | launcher = "honggfuzz_launcher.sh",
47 | launcher_data = {
48 | "@honggfuzz//:honggfuzz": "HONGGFUZZ_PATH",
49 | },
50 | library = "@honggfuzz//:honggfuzz_engine",
51 | visibility = ["//visibility:public"],
52 | )
53 |
54 | # The replay engine specification.
55 | ##################################
56 |
57 | cc_fuzzing_engine(
58 | name = "replay",
59 | display_name = "Replay",
60 | launcher = "replay_launcher.sh",
61 | library = "//fuzzing/replay:replay_main",
62 | visibility = ["//visibility:public"],
63 | )
64 |
65 | # Jazzer specification.
66 | #################################
67 |
68 | java_fuzzing_engine(
69 | name = "jazzer",
70 | display_name = "Jazzer",
71 | launcher = "jazzer_launcher.sh",
72 | library = ":jazzer_stub",
73 | visibility = ["//visibility:public"],
74 | )
75 |
76 | # This wrapper target is needed as Jazzer consists of two separate Java targets,
77 | # but java_fuzzing_engine's library attribute only accepts a single target.
78 | java_library(
79 | name = "jazzer_stub",
80 | exports = [
81 | "@rules_fuzzing_jazzer//jar",
82 | "@rules_fuzzing_jazzer_api//jar",
83 | ],
84 | )
85 |
86 | # OSS-Fuzz specification.
87 | #########################
88 |
89 | alias(
90 | name = "oss_fuzz",
91 | actual = "@rules_fuzzing_oss_fuzz//:oss_fuzz_engine",
92 | visibility = ["//visibility:public"],
93 | )
94 |
95 | alias(
96 | name = "oss_fuzz_java",
97 | actual = "@rules_fuzzing_oss_fuzz//:oss_fuzz_java_engine",
98 | visibility = ["//visibility:public"],
99 | )
100 |
--------------------------------------------------------------------------------
/fuzzing/engines/honggfuzz_launcher.sh:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | command_line="$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${HONGGFUZZ_PATH})"
16 | command_line+=("--workspace=${FUZZER_OUTPUT_ROOT}")
17 |
18 | if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
19 | command_line+=("--input=${FUZZER_SEED_CORPUS_DIR}")
20 | command_line+=("--output=${FUZZER_OUTPUT_CORPUS_DIR}")
21 | else
22 | command_line+=("--input=${FUZZER_OUTPUT_CORPUS_DIR}")
23 | fi
24 | if (( FUZZER_IS_REGRESSION )); then
25 | # Dry-run-only mode - see https://github.com/google/honggfuzz/issues/296.
26 | command_line+=("--mutations_per_run=0")
27 | command_line+=("--verifier")
28 | # Make the output more suitable for debugging.
29 | command_line+=("--verbose")
30 | command_line+=("--keep_output")
31 | fi
32 |
33 | command_line+=("--crashdir=${FUZZER_ARTIFACTS_DIR}")
34 |
35 | if [[ "${FUZZER_TIMEOUT_SECS}" -gt 0 ]]; then
36 | command_line+=("--run_time=${FUZZER_TIMEOUT_SECS}")
37 | fi
38 |
39 | if [[ -n "${FUZZER_DICTIONARY_PATH}" ]]; then
40 | command_line+=("--dict=${FUZZER_DICTIONARY_PATH}")
41 | fi
42 | command_line+=("--" "${FUZZER_BINARY}")
43 |
44 | exec "${command_line[@]}" "$@"
45 |
--------------------------------------------------------------------------------
/fuzzing/engines/jazzer_launcher.sh:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # The command line arguments for launching fuzz tests run with the Jazzer
16 | # engine. The launch configuration is supplied by the launcher script through
17 | # environment variables.
18 |
19 | command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
20 |
21 | # libFuzzer flags (compatible with Jazzer).
22 |
23 | if [[ -n "${FUZZER_DICTIONARY_PATH}" ]]; then
24 | command_line+=("-dict=${FUZZER_DICTIONARY_PATH}")
25 | fi
26 | command_line+=("-artifact_prefix=${FUZZER_ARTIFACTS_DIR}/")
27 | if [[ "${FUZZER_TIMEOUT_SECS}" -gt 0 ]]; then
28 | command_line+=("-max_total_time=${FUZZER_TIMEOUT_SECS}")
29 | fi
30 | if (( FUZZER_IS_REGRESSION )); then
31 | command_line+=("-runs=0")
32 | else
33 | command_line+=("${FUZZER_OUTPUT_CORPUS_DIR}")
34 | fi
35 |
36 | # Jazzer flags.
37 | command_line+=("--reproducer_path=${FUZZER_ARTIFACTS_DIR}")
38 |
39 | # Corpus sources.
40 |
41 | if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
42 | command_line+=("${FUZZER_SEED_CORPUS_DIR}")
43 | fi
44 |
45 | exec "${command_line[@]}" "$@"
46 |
--------------------------------------------------------------------------------
/fuzzing/engines/libfuzzer_launcher.sh:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # The command line arguments for launching fuzz tests linked with the
16 | # libFuzzer engine. The launch configuration is supplied by the launcher
17 | # script through environment variables.
18 |
19 | command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
20 |
21 | # libFuzzer flags.
22 |
23 | if [[ -n "${FUZZER_DICTIONARY_PATH}" ]]; then
24 | command_line+=("-dict=${FUZZER_DICTIONARY_PATH}")
25 | fi
26 | command_line+=("-artifact_prefix=${FUZZER_ARTIFACTS_DIR}/")
27 | if [[ "${FUZZER_TIMEOUT_SECS}" -gt 0 ]]; then
28 | command_line+=("-max_total_time=${FUZZER_TIMEOUT_SECS}")
29 | fi
30 | if (( FUZZER_IS_REGRESSION )); then
31 | command_line+=("-runs=0")
32 | else
33 | command_line+=("${FUZZER_OUTPUT_CORPUS_DIR}")
34 | fi
35 |
36 | # Corpus sources.
37 |
38 | if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
39 | command_line+=("${FUZZER_SEED_CORPUS_DIR}")
40 | fi
41 |
42 | exec "${command_line[@]}" "$@"
43 |
--------------------------------------------------------------------------------
/fuzzing/engines/replay_launcher.sh:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | if (( ! FUZZER_IS_REGRESSION )); then
16 | echo "NOTE: Non-regression mode is not supported by the replay engine."
17 | fi
18 |
19 | command_line=("$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${FUZZER_BINARY})")
20 | if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
21 | command_line+=("${FUZZER_SEED_CORPUS_DIR}")
22 | fi
23 |
24 | exec "${command_line[@]}" "$@"
25 |
--------------------------------------------------------------------------------
/fuzzing/init.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Dependency initialization utilities."""
16 |
17 | load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
18 | load("@rules_python//python:pip.bzl", "pip_parse")
19 |
20 | def rules_fuzzing_init():
21 | pip_parse(
22 | name = "fuzzing_py_deps",
23 | extra_pip_args = ["--require-hashes"],
24 | requirements_lock = "@rules_fuzzing//fuzzing:requirements.txt",
25 | )
26 | bazel_skylib_workspace()
27 |
--------------------------------------------------------------------------------
/fuzzing/instrum_opts.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Fuzz test instrumentation options.
16 |
17 | Each fuzzing engine or sanitizer instrumentation recognized by the
18 | //fuzzing:cc_engine_instrumentation and //fuzzing:cc_engine_sanitizer
19 | configuration flag should be defined here.
20 | """
21 |
22 | load(
23 | "@rules_fuzzing//fuzzing/private:instrum_opts.bzl",
24 | "instrum_defaults",
25 | "instrum_opts",
26 | )
27 | load(
28 | "@rules_fuzzing_oss_fuzz//:instrum.bzl",
29 | "oss_fuzz_opts",
30 | )
31 |
32 | # Fuzz test binary instrumentation configurations.
33 | instrum_configs = {
34 | "none": instrum_opts.make(),
35 | "libfuzzer": instrum_defaults.libfuzzer,
36 | "jazzer": instrum_defaults.jazzer,
37 | "honggfuzz": instrum_defaults.honggfuzz,
38 | "oss-fuzz": oss_fuzz_opts,
39 | }
40 |
41 | # Sanitizer configurations.
42 | sanitizer_configs = {
43 | "none": instrum_opts.make(),
44 | "asan": instrum_defaults.asan,
45 | "msan": instrum_defaults.msan,
46 | "msan-origin-tracking": instrum_defaults.msan_origin_tracking,
47 | "ubsan": instrum_defaults.ubsan,
48 | "asan-ubsan": instrum_opts.merge(instrum_defaults.asan, instrum_defaults.ubsan),
49 | }
50 |
--------------------------------------------------------------------------------
/fuzzing/java_defs.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2021 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Public definitions for fuzzing rules.
16 |
17 | Definitions outside this file are private unless otherwise noted, and may
18 | change without notice.
19 | """
20 |
21 | load(
22 | "//fuzzing/private:engine.bzl",
23 | _FuzzingEngineInfo = "FuzzingEngineInfo",
24 | _java_fuzzing_engine = "java_fuzzing_engine",
25 | )
26 | load(
27 | "//fuzzing/private:fuzz_test.bzl",
28 | _fuzzing_decoration = "fuzzing_decoration",
29 | _java_fuzz_test = "java_fuzz_test",
30 | )
31 |
32 | java_fuzz_test = _java_fuzz_test
33 | java_fuzzing_engine = _java_fuzzing_engine
34 |
35 | fuzzing_decoration = _fuzzing_decoration
36 |
37 | FuzzingEngineInfo = _FuzzingEngineInfo
38 |
--------------------------------------------------------------------------------
/fuzzing/private/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | load(":engine_test.bzl", "engine_test_suite")
16 |
17 | engine_test_suite(
18 | name = "engine_test",
19 | )
20 |
21 | exports_files([
22 | "binary.bzl",
23 | "common.bzl",
24 | "engine.bzl",
25 | "fuzz_test.bzl",
26 | "instrum_opts.bzl",
27 | "java_utils.bzl",
28 | "regression.bzl",
29 | "util.bzl",
30 | ])
31 |
32 | config_setting(
33 | name = "is_oss_fuzz",
34 | flag_values = {
35 | "@rules_fuzzing//fuzzing:cc_engine": "@rules_fuzzing_oss_fuzz//:oss_fuzz_engine",
36 | },
37 | visibility = ["//visibility:public"],
38 | )
39 |
40 | config_setting(
41 | name = "use_asan",
42 | flag_values = {
43 | "@rules_fuzzing//fuzzing:cc_engine_sanitizer": "asan",
44 | },
45 | visibility = ["//visibility:public"],
46 | )
47 |
48 | config_setting(
49 | name = "use_ubsan",
50 | flag_values = {
51 | "@rules_fuzzing//fuzzing:cc_engine_sanitizer": "ubsan",
52 | },
53 | visibility = ["//visibility:public"],
54 | )
55 |
56 | exports_files([
57 | "local_jazzer_sanitizer_options.sh",
58 | "oss_fuzz_jazzer_sanitizer_options.sh",
59 | ])
60 |
--------------------------------------------------------------------------------
/fuzzing/private/common.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Common building blocks for fuzz test definitions."""
16 |
17 | load("//fuzzing/private:binary.bzl", "FuzzingBinaryInfo")
18 |
19 | def _fuzzing_launcher_script(ctx):
20 | binary_info = ctx.attr.binary[FuzzingBinaryInfo]
21 | script = ctx.actions.declare_file(ctx.label.name)
22 |
23 | script_template = """
24 | {environment}
25 | echo "Launching {binary_path} as a {engine_name} fuzz test..."
26 | RUNFILES_DIR="$0.runfiles" \
27 | exec "{launcher}" \
28 | --engine_launcher="{engine_launcher}" \
29 | --binary_path="{binary_path}" \
30 | --corpus_dir="{corpus_dir}" \
31 | --dictionary_path="{dictionary_path}" \
32 | "$@"
33 | """
34 | script_content = script_template.format(
35 | environment = "\n".join([
36 | "export %s='%s'" % (var, file.short_path)
37 | for var, file in binary_info.engine_info.launcher_environment.items()
38 | ]),
39 | launcher = ctx.executable._launcher.short_path,
40 | binary_path = ctx.executable.binary.short_path,
41 | engine_launcher = binary_info.engine_info.launcher.short_path,
42 | engine_name = binary_info.engine_info.display_name,
43 | corpus_dir = binary_info.corpus_dir.short_path if binary_info.corpus_dir else "",
44 | dictionary_path = binary_info.dictionary_file.short_path if binary_info.dictionary_file else "",
45 | )
46 | ctx.actions.write(script, script_content, is_executable = True)
47 | return script
48 |
49 | def _fuzzing_launcher_impl(ctx):
50 | script = _fuzzing_launcher_script(ctx)
51 |
52 | binary_info = ctx.attr.binary[FuzzingBinaryInfo]
53 | runfiles = ctx.runfiles()
54 | runfiles = runfiles.merge(binary_info.engine_info.launcher_runfiles)
55 | runfiles = runfiles.merge(ctx.attr._launcher[DefaultInfo].default_runfiles)
56 | runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles)
57 | return [DefaultInfo(executable = script, runfiles = runfiles)]
58 |
59 | fuzzing_launcher = rule(
60 | implementation = _fuzzing_launcher_impl,
61 | doc = """
62 | Rule for creating a script to run the fuzzing test.
63 | """,
64 | attrs = {
65 | "_launcher": attr.label(
66 | default = Label("//fuzzing/tools:launcher"),
67 | doc = "The launcher script to start the fuzzing test.",
68 | executable = True,
69 | cfg = "exec",
70 | ),
71 | "binary": attr.label(
72 | executable = True,
73 | doc = "The executable of the fuzz test to run.",
74 | providers = [FuzzingBinaryInfo],
75 | cfg = "target",
76 | mandatory = True,
77 | ),
78 | },
79 | executable = True,
80 | )
81 |
82 | def _fuzzing_corpus_impl(ctx):
83 | corpus_list_file_args = ctx.actions.args()
84 | corpus_list_file_args.set_param_file_format("multiline")
85 | corpus_list_file_args.use_param_file("--corpus_list_file=%s", use_always = True)
86 | corpus_list_file_args.add_all(ctx.files.srcs)
87 |
88 | corpus_dir = ctx.actions.declare_directory(ctx.attr.name)
89 | cp_args = ctx.actions.args()
90 | cp_args.add("--output_dir=" + corpus_dir.path)
91 |
92 | ctx.actions.run(
93 | inputs = ctx.files.srcs,
94 | outputs = [corpus_dir],
95 | arguments = [cp_args, corpus_list_file_args],
96 | executable = ctx.executable._corpus_tool,
97 | # Use the default rather than an empty environment so that PATH is
98 | # set and python can be found.
99 | use_default_shell_env = True,
100 | )
101 |
102 | return [DefaultInfo(
103 | runfiles = ctx.runfiles(files = [corpus_dir]),
104 | files = depset([corpus_dir]),
105 | )]
106 |
107 | fuzzing_corpus = rule(
108 | implementation = _fuzzing_corpus_impl,
109 | doc = """
110 | This rule provides a _corpus directory collecting all the corpora files
111 | specified in the srcs attribute.
112 | """,
113 | attrs = {
114 | "_corpus_tool": attr.label(
115 | default = Label("//fuzzing/tools:make_corpus_dir"),
116 | doc = "The tool script to copy and rename the corpus.",
117 | executable = True,
118 | cfg = "exec",
119 | ),
120 | "srcs": attr.label_list(
121 | doc = "The corpus files for the fuzzing test.",
122 | allow_files = True,
123 | ),
124 | },
125 | )
126 |
127 | def _fuzzing_dictionary_impl(ctx):
128 | output_dict = ctx.actions.declare_file(ctx.attr.output)
129 | args = ctx.actions.args()
130 | args.add_joined("--dict_list", ctx.files.dicts, join_with = ",")
131 | args.add("--output_file=" + output_dict.path)
132 |
133 | ctx.actions.run(
134 | inputs = ctx.files.dicts,
135 | outputs = [output_dict],
136 | arguments = [args],
137 | executable = ctx.executable._validation_tool,
138 | # Use the default rather than an empty environment so that PATH is
139 | # set and python can be found.
140 | use_default_shell_env = True,
141 | )
142 |
143 | runfiles = ctx.runfiles(files = [output_dict])
144 |
145 | return [DefaultInfo(
146 | runfiles = runfiles,
147 | files = depset([output_dict]),
148 | )]
149 |
150 | fuzzing_dictionary = rule(
151 | implementation = _fuzzing_dictionary_impl,
152 | doc = """
153 | Rule to validate the fuzzing dictionaries and output a merged dictionary.
154 | """,
155 | attrs = {
156 | "_validation_tool": attr.label(
157 | default = Label("//fuzzing/tools:validate_dict"),
158 | doc = "The tool script to validate and merge the dictionaries.",
159 | executable = True,
160 | cfg = "exec",
161 | ),
162 | "dicts": attr.label_list(
163 | doc = "The fuzzing dictionaries.",
164 | allow_files = True,
165 | mandatory = True,
166 | ),
167 | "output": attr.string(
168 | doc = "The name of the merged dictionary.",
169 | mandatory = True,
170 | ),
171 | },
172 | )
173 |
--------------------------------------------------------------------------------
/fuzzing/private/engine.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """The implementation of the {cc, java}_fuzzing_engine rules."""
16 |
17 | load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
18 | load("@rules_java//java/common:java_info.bzl", "JavaInfo")
19 |
20 | FuzzingEngineInfo = provider(
21 | doc = """
22 | Provider for storing the language-independent part of the specification of a fuzzing engine.
23 | """,
24 | fields = {
25 | "display_name": "A string representing the human-readable name of the fuzzing engine.",
26 | "launcher": "A file representing the shell script that launches the fuzz target.",
27 | "launcher_runfiles": "The runfiles needed by the launcher script on the fuzzing engine side, such as helper tools and their data dependencies.",
28 | "launcher_environment": "A dictionary from environment variables to files used by the launcher script.",
29 | },
30 | )
31 |
32 | def _make_fuzzing_engine_info(ctx):
33 | if not ctx.attr.display_name:
34 | fail("The display_name attribute of the rule must not be empty.")
35 |
36 | launcher_runfiles = ctx.runfiles(files = [ctx.file.launcher])
37 | env_vars = {}
38 | for data_label, data_env_var in ctx.attr.launcher_data.items():
39 | data_files = data_label.files.to_list()
40 | if data_env_var:
41 | if data_env_var in env_vars:
42 | fail("Multiple data dependencies map to variable '%s'." % data_env_var)
43 | if len(data_files) != 1:
44 | fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
45 | env_vars[data_env_var] = data_files[0]
46 | launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
47 | launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)
48 |
49 | return FuzzingEngineInfo(
50 | display_name = ctx.attr.display_name,
51 | launcher = ctx.file.launcher,
52 | launcher_runfiles = launcher_runfiles,
53 | launcher_environment = env_vars,
54 | )
55 |
56 | def _cc_fuzzing_engine_impl(ctx):
57 | return [
58 | _make_fuzzing_engine_info(ctx),
59 | ctx.attr.library[DefaultInfo],
60 | ctx.attr.library[CcInfo],
61 | ]
62 |
63 | cc_fuzzing_engine = rule(
64 | implementation = _cc_fuzzing_engine_impl,
65 | doc = """
66 | Specifies a fuzzing engine that can be used to run C++ fuzz targets.
67 | """,
68 | attrs = {
69 | "display_name": attr.string(
70 | doc = "The name of the fuzzing engine, as it should be rendered " +
71 | "in human-readable output.",
72 | mandatory = True,
73 | ),
74 | "library": attr.label(
75 | doc = "A cc_library target that implements the fuzzing engine " +
76 | "entry point.",
77 | mandatory = True,
78 | providers = [CcInfo],
79 | ),
80 | "launcher": attr.label(
81 | doc = "A shell script that knows how to launch the fuzzing " +
82 | "executable based on configuration specified in the environment.",
83 | mandatory = True,
84 | allow_single_file = True,
85 | ),
86 | "launcher_data": attr.label_keyed_string_dict(
87 | doc = "A dict mapping additional runtime dependencies needed by " +
88 | "the fuzzing engine to environment variables that will be " +
89 | "available inside the launcher, holding the runtime path " +
90 | "to the dependency.",
91 | allow_files = True,
92 | ),
93 | },
94 | provides = [CcInfo, FuzzingEngineInfo],
95 | )
96 |
97 | def _java_fuzzing_engine_impl(ctx):
98 | return [
99 | _make_fuzzing_engine_info(ctx),
100 | ctx.attr.library[DefaultInfo],
101 | ctx.attr.library[JavaInfo],
102 | ]
103 |
104 | java_fuzzing_engine = rule(
105 | implementation = _java_fuzzing_engine_impl,
106 | doc = """
107 | Specifies a fuzzing engine that can be used to run Java fuzz targets.
108 | """,
109 | attrs = {
110 | "display_name": attr.string(
111 | doc = "The name of the fuzzing engine, as it should be rendered " +
112 | "in human-readable output.",
113 | mandatory = True,
114 | ),
115 | "library": attr.label(
116 | doc = "A java_library target that is made available to all Java " +
117 | "fuzz tests.",
118 | providers = [JavaInfo],
119 | ),
120 | "launcher": attr.label(
121 | doc = "A shell script that knows how to launch the fuzzing " +
122 | "executable based on configuration specified in the environment.",
123 | mandatory = True,
124 | allow_single_file = True,
125 | ),
126 | "launcher_data": attr.label_keyed_string_dict(
127 | doc = "A dict mapping additional runtime dependencies needed by " +
128 | "the fuzzing engine to environment variables that will be " +
129 | "available inside the launcher, holding the runtime path " +
130 | "to the dependency.",
131 | allow_files = True,
132 | ),
133 | },
134 | provides = [FuzzingEngineInfo, JavaInfo],
135 | )
136 |
--------------------------------------------------------------------------------
/fuzzing/private/engine_test.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Unit tests for the fuzzing engine rules and providers."""
16 |
17 | load("@bazel_skylib//lib:new_sets.bzl", "sets")
18 | load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
19 | load("@rules_cc//cc:cc_library.bzl", "cc_library")
20 | load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
21 | load(":engine.bzl", "FuzzingEngineInfo", "cc_fuzzing_engine")
22 | load(":util.bzl", "generate_file")
23 |
24 | # Shared fixtures.
25 |
26 | def _setup_common_stubs():
27 | cc_library(
28 | name = "library_stub",
29 | srcs = [],
30 | testonly = 1,
31 | )
32 |
33 | generate_file(
34 | name = "launcher_stub",
35 | output = "launcher_stub.sh",
36 | contents = "echo 'Launcher stub'",
37 | testonly = 1,
38 | )
39 |
40 | generate_file(
41 | name = "data_stub",
42 | output = "data.txt",
43 | contents = "Test data stub.",
44 | testonly = 1,
45 | )
46 |
47 | generate_file(
48 | name = "anon_data_stub",
49 | output = "anon_data.txt",
50 | contents = "Data stub with no environment variable.",
51 | testonly = 1,
52 | )
53 |
54 | # Test that the FuzzingEngineInfo provider is populated correctly
55 | # (`provider_contents` stem).
56 |
57 | def _provider_contents_test_impl(ctx):
58 | env = analysistest.begin(ctx)
59 | target_under_test = analysistest.target_under_test(env)
60 | asserts.true(
61 | env,
62 | CcInfo in target_under_test,
63 | )
64 | asserts.equals(
65 | env,
66 | "Provider Contents",
67 | target_under_test[FuzzingEngineInfo].display_name,
68 | )
69 | asserts.equals(
70 | env,
71 | "fuzzing/private/launcher_stub.sh",
72 | target_under_test[FuzzingEngineInfo].launcher.short_path,
73 | )
74 | asserts.set_equals(
75 | env,
76 | sets.make([
77 | "fuzzing/private/launcher_stub.sh",
78 | "fuzzing/private/data.txt",
79 | "fuzzing/private/anon_data.txt",
80 | ]),
81 | sets.make([
82 | file.short_path
83 | for file in target_under_test[FuzzingEngineInfo].launcher_runfiles.files.to_list()
84 | ]),
85 | )
86 | asserts.set_equals(
87 | env,
88 | sets.make([
89 | ("DATA_STUB_FILE", "fuzzing/private/data.txt"),
90 | ]),
91 | sets.make([
92 | (env_var, file.short_path)
93 | for env_var, file in target_under_test[FuzzingEngineInfo].launcher_environment.items()
94 | ]),
95 | )
96 | return analysistest.end(env)
97 |
98 | provider_contents_test = analysistest.make(_provider_contents_test_impl)
99 |
100 | def _test_provider_contents():
101 | cc_fuzzing_engine(
102 | name = "provider_contents",
103 | tags = ["manual"],
104 | display_name = "Provider Contents",
105 | library = ":library_stub",
106 | launcher = ":launcher_stub",
107 | launcher_data = {
108 | ":data_stub": "DATA_STUB_FILE",
109 | ":anon_data_stub": "",
110 | },
111 | testonly = 1,
112 | )
113 |
114 | provider_contents_test(
115 | name = "provider_contents_test",
116 | target_under_test = ":provider_contents",
117 | )
118 |
119 | # Test that an empty engine name causes a failure
120 | # (`engine_empty_name` stem).
121 |
122 | def _engine_empty_name_test_impl(ctx):
123 | env = analysistest.begin(ctx)
124 | asserts.expect_failure(
125 | env,
126 | "The display_name attribute of the rule must not be empty",
127 | )
128 | return analysistest.end(env)
129 |
130 | engine_empty_name_test = analysistest.make(
131 | _engine_empty_name_test_impl,
132 | expect_failure = True,
133 | )
134 |
135 | def _test_engine_name_empty():
136 | cc_fuzzing_engine(
137 | name = "engine_empty_name",
138 | tags = ["manual"],
139 | display_name = "",
140 | library = ":library_stub",
141 | launcher = ":launcher_stub",
142 | testonly = 1,
143 | )
144 |
145 | engine_empty_name_test(
146 | name = "engine_empty_name_test",
147 | target_under_test = ":engine_empty_name",
148 | )
149 |
150 | # The entire test suite.
151 |
152 | def engine_test_suite(name):
153 | _setup_common_stubs()
154 | _test_engine_name_empty()
155 | _test_provider_contents()
156 |
157 | native.test_suite(
158 | name = name,
159 | tests = [
160 | ":engine_empty_name_test",
161 | ":provider_contents_test",
162 | ],
163 | )
164 |
--------------------------------------------------------------------------------
/fuzzing/private/extensions.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2024 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Internal dependencies that are not Bazel modules."""
16 |
17 | load("@bazel_features//:features.bzl", "bazel_features")
18 | load("//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
19 |
20 | def _non_module_dependencies(mctx):
21 | rules_fuzzing_dependencies()
22 |
23 | if bazel_features.external_deps.extension_metadata_has_reproducible:
24 | return mctx.extension_metadata(reproducible = True)
25 |
26 | return None
27 |
28 | non_module_dependencies = module_extension(_non_module_dependencies)
29 |
--------------------------------------------------------------------------------
/fuzzing/private/instrum_opts.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """A representation for instrumentation options, along with operations."""
16 |
17 | def _is_string_list(value):
18 | if type(value) != type([]):
19 | return False
20 | if any([type(element) != type("") for element in value]):
21 | return False
22 | return True
23 |
24 | def _make_opts(
25 | copts = [],
26 | conlyopts = [],
27 | cxxopts = [],
28 | linkopts = []):
29 | """Creates new instrumentation options.
30 |
31 | The struct fields mirror the argument names of this function.
32 |
33 | Args:
34 | copts: A list of C/C++ compilation options passed as `--copt`
35 | configuration flags.
36 | conlyopts: A list of C-only compilation options passed as `--conlyopt`
37 | configuration flags.
38 | cxxopts: A list of C++-only compilation options passed as `--cxxopts`
39 | configuration flags.
40 | linkopts: A list of linker options to pass as `--linkopt`
41 | configuration flags.
42 | Returns:
43 | A struct with the given instrumentation options.
44 | """
45 | if not _is_string_list(copts):
46 | fail("copts should be a list of strings")
47 | if not _is_string_list(conlyopts):
48 | fail("conlyopts should be a list of strings")
49 | if not _is_string_list(cxxopts):
50 | fail("cxxopts should be a list of strings")
51 | if not _is_string_list(linkopts):
52 | fail("linkopts should be a list of strings")
53 | return struct(
54 | copts = copts,
55 | conlyopts = conlyopts,
56 | cxxopts = cxxopts,
57 | linkopts = linkopts,
58 | )
59 |
60 | def _merge_opts(left_opts, right_opts):
61 | return _make_opts(
62 | copts = left_opts.copts + right_opts.copts,
63 | conlyopts = left_opts.conlyopts + right_opts.conlyopts,
64 | cxxopts = left_opts.cxxopts + right_opts.cxxopts,
65 | linkopts = left_opts.linkopts + right_opts.linkopts,
66 | )
67 |
68 | instrum_opts = struct(
69 | make = _make_opts,
70 | merge = _merge_opts,
71 | )
72 |
73 | instrum_defaults = struct(
74 | # Instrumentation applied to all fuzz test executables when built in fuzzing
75 | # mode. This mode is controlled by the `//fuzzing:cc_fuzzing_build_mode`
76 | # config flag.
77 | fuzzing_build = _make_opts(
78 | copts = ["-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"],
79 | ),
80 | libfuzzer = _make_opts(
81 | copts = ["-fsanitize=fuzzer-no-link"],
82 | ),
83 | # Jazzer is based on libFuzzer and hence generally requires the same
84 | # instrumentation for native code. Since it does not support
85 | # LeakSanitizer, the corresponding instrumentation can be disabled.
86 | jazzer = _make_opts(
87 | copts = [
88 | "-fsanitize=fuzzer-no-link",
89 | "-fno-sanitize=leak",
90 | ],
91 | ),
92 | # Reflects the set of options at
93 | # https://github.com/google/honggfuzz/blob/master/hfuzz_cc/hfuzz-cc.c
94 | honggfuzz = _make_opts(
95 | copts = [
96 | "-mllvm",
97 | "-inline-threshold=2000",
98 | "-fno-builtin",
99 | "-fno-omit-frame-pointer",
100 | "-D__NO_STRING_INLINES",
101 | "-fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,indirect-calls",
102 | "-fno-sanitize=fuzzer",
103 | ],
104 | linkopts = [
105 | "-fno-sanitize=fuzzer",
106 | ],
107 | ),
108 | asan = _make_opts(
109 | copts = ["-fsanitize=address"],
110 | linkopts = ["-fsanitize=address"],
111 | ),
112 | msan = _make_opts(
113 | copts = ["-fsanitize=memory"],
114 | linkopts = ["-fsanitize=memory"],
115 | ),
116 | msan_origin_tracking = _make_opts(
117 | copts = [
118 | "-fsanitize=memory",
119 | "-fsanitize-memory-track-origins=2",
120 | ],
121 | linkopts = ["-fsanitize=memory"],
122 | ),
123 | ubsan = _make_opts(
124 | copts = [
125 | "-fsanitize=undefined",
126 | ],
127 | linkopts = [
128 | "-fsanitize=undefined",
129 | # Bazel uses clang, not clang++, as the linker, which does not link
130 | # the C++ UBSan runtime library by default, but can be instructed to
131 | # do so with a flag.
132 | # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-896613570
133 | "-fsanitize-link-c++-runtime",
134 | ],
135 | ),
136 | )
137 |
--------------------------------------------------------------------------------
/fuzzing/private/local_jazzer_sanitizer_options.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright 2021 Google LLC
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | exports_files([
16 | "package.bzl",
17 | ])
18 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz/BUILD.tpl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
16 | load("@rules_fuzzing//fuzzing:java_defs.bzl", "java_fuzzing_engine")
17 |
18 | cc_fuzzing_engine(
19 | name = "oss_fuzz_engine",
20 | display_name = "OSS-Fuzz",
21 | launcher = "oss_fuzz_launcher.sh",
22 | library = ":oss_fuzz_stub",
23 | visibility = ["//visibility:public"],
24 | )
25 |
26 | cc_library(
27 | name = "oss_fuzz_stub",
28 | srcs = [%{stub_srcs}],
29 | linkopts = [%{stub_linkopts}],
30 | )
31 |
32 | java_fuzzing_engine(
33 | name = "oss_fuzz_java_engine",
34 | display_name = "OSS-Fuzz (Java)",
35 | launcher = "oss_fuzz_launcher.sh",
36 | library = ":oss_fuzz_java_stub",
37 | visibility = ["//visibility:public"],
38 | )
39 |
40 | java_import(
41 | name = "oss_fuzz_java_stub",
42 | jars = [%{jazzer_jars}],
43 | )
44 |
45 |
46 | exports_files(["instrum.bzl"])
47 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz/instrum.bzl.tpl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Instrumentation options for OSS-Fuzz."""
16 |
17 | load("@rules_fuzzing//fuzzing/private:instrum_opts.bzl", "instrum_opts")
18 |
19 | oss_fuzz_opts = instrum_opts.make(
20 | conlyopts = [%{conlyopts}],
21 | cxxopts = [%{cxxopts}],
22 | )
23 |
24 | native_library_sanitizer = "%{sanitizer}"
25 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz/package.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Rule for packaging fuzz tests in the expected OSS-Fuzz format."""
16 |
17 | load("//fuzzing/private:binary.bzl", "FuzzingBinaryInfo")
18 | load("//fuzzing/private:util.bzl", "runfile_path")
19 |
20 | def _oss_fuzz_package_impl(ctx):
21 | output_archive = ctx.actions.declare_file(ctx.label.name + ".tar")
22 | binary_info = ctx.attr.binary[FuzzingBinaryInfo]
23 |
24 | binary_runfiles = binary_info.binary_runfiles.files.to_list()
25 | archive_inputs = binary_runfiles
26 |
27 | runfiles_manifest = ctx.actions.declare_file(ctx.label.name + "_runfiles")
28 | local_jdk_prefix = Label("@local_jdk//:unused").workspace_name + "/"
29 | runfiles_manifest_content = "".join([
30 | "{runfile_path} {real_path}\n".format(
31 | real_path = runfile.path,
32 | runfile_path = runfile_path(ctx, runfile),
33 | )
34 | # In order not to duplicate the fuzz test binary, it is excluded from
35 | # the runfiles here. This deviates from the usual Bazel runfiles layout,
36 | # but is required since ClusterFuzz executes fuzz targets in
37 | # subdirectories and would thus duplicate every C++ fuzz target.
38 | # We also exclude the local JDK as OSS-Fuzz provides one.
39 | for runfile in binary_runfiles
40 | if runfile != binary_info.binary_file and not runfile_path(ctx, runfile).startswith(local_jdk_prefix)
41 | ])
42 | ctx.actions.write(runfiles_manifest, runfiles_manifest_content, False)
43 | archive_inputs.append(runfiles_manifest)
44 |
45 | if binary_info.binary_repo_mapping_manifest:
46 | archive_inputs.append(binary_info.binary_repo_mapping_manifest)
47 | if binary_info.corpus_dir:
48 | archive_inputs.append(binary_info.corpus_dir)
49 | if binary_info.dictionary_file:
50 | archive_inputs.append(binary_info.dictionary_file)
51 | ctx.actions.run_shell(
52 | outputs = [output_archive],
53 | inputs = archive_inputs,
54 | command = """
55 | set -e
56 | declare -r STAGING_DIR="$(mktemp --directory -t oss-fuzz-pkg.XXXXXXXXXX)"
57 | function cleanup() {{
58 | rm -rf "$STAGING_DIR"
59 | }}
60 | trap cleanup EXIT
61 | ln -s "$(pwd)/{binary_path}" "$STAGING_DIR/{base_name}"
62 | while IFS= read -r line; do
63 | IFS=' ' read -r link target <<< "$line"
64 | mkdir -p "$(dirname "$STAGING_DIR/{binary_runfiles_dir}/$link")"
65 | ln -s "$(pwd)/$target" "$STAGING_DIR/{binary_runfiles_dir}/$link"
66 | done <{runfiles_manifest_path}
67 | if [[ -n "{binary_repo_mapping_manifest}" ]]; then
68 | mkdir -p "$STAGING_DIR/{binary_runfiles_dir}"
69 | ln -s "$(pwd)/{binary_repo_mapping_manifest}" "$STAGING_DIR/{binary_runfiles_dir}/_repo_mapping"
70 | fi
71 | if [[ -n "{corpus_dir}" ]]; then
72 | pushd "{corpus_dir}" >/dev/null
73 | zip --quiet -r "$STAGING_DIR/{base_name}_seed_corpus.zip" ./*
74 | popd >/dev/null
75 | fi
76 | if [[ -n "{dictionary_path}" ]]; then
77 | ln -s "$(pwd)/{dictionary_path}" "$STAGING_DIR/{base_name}.dict"
78 | fi
79 | if [[ -n "{options_path}" ]]; then
80 | ln -s "$(pwd)/{options_path}" "$STAGING_DIR/{base_name}.options"
81 | fi
82 | tar -chf "{output}" -C "$STAGING_DIR" .
83 | """.format(
84 | base_name = ctx.attr.base_name,
85 | binary_path = binary_info.binary_file.path,
86 | binary_runfiles_dir = ctx.attr.base_name + ".runfiles",
87 | binary_repo_mapping_manifest = binary_info.binary_repo_mapping_manifest.path if binary_info.binary_repo_mapping_manifest else "",
88 | corpus_dir = binary_info.corpus_dir.path if binary_info.corpus_dir else "",
89 | dictionary_path = binary_info.dictionary_file.path if binary_info.dictionary_file else "",
90 | options_path = binary_info.options_file.path if binary_info.options_file else "",
91 | output = output_archive.path,
92 | runfiles_manifest_path = runfiles_manifest.path,
93 | ),
94 | )
95 | return [DefaultInfo(files = depset([output_archive]))]
96 |
97 | oss_fuzz_package = rule(
98 | implementation = _oss_fuzz_package_impl,
99 | doc = """
100 | Packages a fuzz test in a TAR archive compatible with the OSS-Fuzz format.
101 | """,
102 | attrs = {
103 | "binary": attr.label(
104 | executable = True,
105 | doc = "The fuzz test executable.",
106 | providers = [FuzzingBinaryInfo],
107 | mandatory = True,
108 | cfg = "target",
109 | ),
110 | "base_name": attr.string(
111 | doc = "The base name of the fuzz test used to form the file names " +
112 | "in the OSS-Fuzz output.",
113 | mandatory = True,
114 | ),
115 | },
116 | )
117 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz/repository.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Repository rule for configuring the OSS-Fuzz engine and instrumentation."""
16 |
17 | def _to_list_repr(elements):
18 | return ", ".join([repr(element) for element in elements])
19 |
20 | def _extract_build_params(
21 | repository_ctx,
22 | fuzzing_engine_library,
23 | sanitizer,
24 | cflags,
25 | cxxflags):
26 | stub_srcs = []
27 | stub_linkopts = []
28 | instrum_conlyopts = []
29 | instrum_cxxopts = []
30 |
31 | if sanitizer == "undefined":
32 | # Bazel uses clang, not clang++, as the linker, which does not link the
33 | # C++ UBSan runtime library by default, but can be instructed to do so
34 | # with a flag.
35 | # https://github.com/bazelbuild/bazel/issues/11122#issuecomment-896613570
36 | stub_linkopts.append("-fsanitize-link-c++-runtime")
37 |
38 | if fuzzing_engine_library:
39 | if fuzzing_engine_library.startswith("-"):
40 | # This is actually a flag, add it to the linker flags.
41 | stub_linkopts.append(fuzzing_engine_library)
42 | elif fuzzing_engine_library.endswith(".a"):
43 | repository_ctx.symlink(
44 | repository_ctx.path(fuzzing_engine_library),
45 | "oss_fuzz_engine.a",
46 | )
47 | stub_srcs.append("oss_fuzz_engine.a")
48 | else:
49 | fail("Unsupported $LIB_FUZZING_ENGINE value '%s'" % fuzzing_engine_library)
50 |
51 | for cflag in cflags:
52 | # Skip the fuzzing build more flag, since it is separately controlled
53 | # by the --//fuzzing:cc_fuzzing_build_mode configuration flag.
54 | if cflag == "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION":
55 | continue
56 | instrum_conlyopts.append(cflag)
57 | if cflag not in stub_linkopts:
58 | stub_linkopts.append(cflag)
59 | for cxxflag in cxxflags:
60 | if cxxflag == "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION":
61 | continue
62 | instrum_cxxopts.append(cxxflag)
63 | if cxxflag not in stub_linkopts:
64 | stub_linkopts.append(cxxflag)
65 |
66 | return struct(
67 | stub_srcs = stub_srcs,
68 | stub_linkopts = stub_linkopts,
69 | instrum_conlyopts = instrum_conlyopts,
70 | instrum_cxxopts = instrum_cxxopts,
71 | )
72 |
73 | _JAZZER_JAR = "jazzer_agent_deploy.jar"
74 |
75 | def _link_jazzer_jars(repository_ctx, out_path):
76 | if out_path == None:
77 | return []
78 | repository_ctx.symlink(out_path + "/" + _JAZZER_JAR, _JAZZER_JAR)
79 | return [_JAZZER_JAR]
80 |
81 | def _oss_fuzz_repository(repository_ctx):
82 | environ = repository_ctx.os.environ
83 | fuzzing_engine_library = environ.get("LIB_FUZZING_ENGINE")
84 | sanitizer = environ.get("SANITIZER")
85 | cflags = environ.get("FUZZING_CFLAGS") or environ.get("CFLAGS", "")
86 | cxxflags = environ.get("FUZZING_CXXFLAGS") or environ.get("CXXFLAGS", "")
87 | out_path = environ.get("OUT")
88 |
89 | build_params = _extract_build_params(
90 | repository_ctx,
91 | fuzzing_engine_library,
92 | sanitizer,
93 | cflags.split(" "),
94 | cxxflags.split(" "),
95 | )
96 |
97 | repository_ctx.template(
98 | "BUILD",
99 | repository_ctx.path(Label("@rules_fuzzing//fuzzing/private/oss_fuzz:BUILD.tpl")),
100 | {
101 | "%{stub_srcs}": _to_list_repr(build_params.stub_srcs),
102 | "%{stub_linkopts}": _to_list_repr(build_params.stub_linkopts),
103 | "%{jazzer_jars}": _to_list_repr(_link_jazzer_jars(repository_ctx, out_path)),
104 | },
105 | )
106 | repository_ctx.template(
107 | "instrum.bzl",
108 | repository_ctx.path(Label("@rules_fuzzing//fuzzing/private/oss_fuzz:instrum.bzl.tpl")),
109 | {
110 | "%{conlyopts}": _to_list_repr(build_params.instrum_conlyopts),
111 | "%{cxxopts}": _to_list_repr(build_params.instrum_cxxopts),
112 | "%{sanitizer}": {
113 | "address": "asan",
114 | "undefined": "ubsan",
115 | }.get(sanitizer, "none"),
116 | },
117 | )
118 | repository_ctx.file(
119 | "oss_fuzz_launcher.sh",
120 | "echo 'The OSS-Fuzz engine is not meant to be executed.'; exit 1",
121 | )
122 |
123 | oss_fuzz_repository = repository_rule(
124 | implementation = _oss_fuzz_repository,
125 | environ = [
126 | "LIB_FUZZING_ENGINE",
127 | "FUZZING_CFLAGS",
128 | "FUZZING_CXXFLAGS",
129 | "CFLAGS",
130 | "CXXFLAGS",
131 | "SANITIZER",
132 | "OUT",
133 | ],
134 | local = True,
135 | doc = """
136 | Generates a repository containing an OSS-Fuzz fuzzing engine defintion.
137 |
138 | The fuzzing engine library path is extracted from the `$LIB_FUZZING_ENGINE`
139 | environment variable. The instrumentation flags are taken from `$FUZZING_CFLAGS`
140 | and `$FUZZING_CXXFLAGS`, falling back to `$CFLAGS`/`$CXXFLAGS` if the former are
141 | not defined.
142 |
143 | The fuzzing engine is available as the `//:oss_fuzz_engine` target.
144 | """,
145 | )
146 |
--------------------------------------------------------------------------------
/fuzzing/private/oss_fuzz_jazzer_sanitizer_options.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright 2021 Google LLC
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | # llvm-symbolizer is a sibling of the wrapper script that sources the current
17 | # script.
18 | declare -r this_dir=$(dirname "${BASH_SOURCE}")
19 | COMMON_SANITIZER_OPTIONS=symbolize=1:external_symbolizer_path=$this_dir/llvm-symbolizer:detect_leaks=0:handle_segv=1
20 |
21 | export ASAN_OPTIONS=${ASAN_OPTIONS:+${ASAN_OPTIONS}:}$COMMON_SANITIZER_OPTIONS:allow_user_segv_handler=1
22 | export UBSAN_OPTIONS=${UBSAN_OPTIONS:+${UBSAN_OPTIONS}:}$COMMON_SANITIZER_OPTIONS
23 |
--------------------------------------------------------------------------------
/fuzzing/private/regression.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Regression testing rule for fuzz tests."""
16 |
17 | load("//fuzzing/private:binary.bzl", "FuzzingBinaryInfo")
18 |
19 | def _fuzzing_regression_test_impl(ctx):
20 | binary_info = ctx.attr.binary[FuzzingBinaryInfo]
21 | script = ctx.actions.declare_file(ctx.label.name)
22 | script_template = """
23 | export FUZZER_OUTPUT_CORPUS_DIR="$TEST_TMPDIR/corpus"
24 | export FUZZER_ARTIFACTS_DIR="$TEST_TMPDIR/artifacts"
25 | export FUZZER_BINARY='{fuzzer_binary}'
26 | export FUZZER_SEED_CORPUS_DIR='{seed_corpus_dir}'
27 | export FUZZER_IS_REGRESSION=1
28 | {engine_launcher_environment}
29 |
30 | mkdir -p "$FUZZER_OUTPUT_CORPUS_DIR"
31 | mkdir -p "$FUZZER_ARTIFACTS_DIR"
32 |
33 | exec '{engine_launcher}'
34 | """
35 | script_content = script_template.format(
36 | fuzzer_binary = ctx.executable.binary.short_path,
37 | seed_corpus_dir = binary_info.corpus_dir.short_path,
38 | engine_launcher_environment = "\n".join([
39 | "export %s='%s'" % (var, file.short_path)
40 | for var, file in binary_info.engine_info.launcher_environment.items()
41 | ]),
42 | engine_launcher = binary_info.engine_info.launcher.short_path,
43 | )
44 | ctx.actions.write(script, script_content, is_executable = True)
45 |
46 | runfiles = ctx.runfiles()
47 | runfiles = runfiles.merge(ctx.attr.binary[DefaultInfo].default_runfiles)
48 | runfiles = runfiles.merge(binary_info.engine_info.launcher_runfiles)
49 |
50 | return [
51 | DefaultInfo(executable = script, runfiles = runfiles),
52 | coverage_common.instrumented_files_info(
53 | ctx,
54 | dependency_attributes = ["binary"],
55 | ),
56 | ]
57 |
58 | fuzzing_regression_test = rule(
59 | implementation = _fuzzing_regression_test_impl,
60 | doc = """
61 | Executes a fuzz test on its seed corpus.
62 | """,
63 | attrs = {
64 | "binary": attr.label(
65 | executable = True,
66 | doc = "The instrumented executable of the fuzz test to run.",
67 | providers = [FuzzingBinaryInfo],
68 | cfg = "target",
69 | mandatory = True,
70 | ),
71 | "_lcov_merger": attr.label(
72 | # As of Bazel 5.1.0, the following would work instead of the alias used below:
73 | # default = configuration_field(fragment = "coverage", name = "output_generator")
74 | default = "//fuzzing/tools:lcov_merger",
75 | executable = True,
76 | # This needs to be built in the target configuration so that the alias it points to can
77 | # select on the value of --collect_code_coverage, which is disabled in the exec
78 | # configuration. Since target and exec platform usually coincide for test execution,
79 | # this should not cause any problems.
80 | cfg = "target",
81 | ),
82 | "_collect_cc_coverage": attr.label(
83 | # This target is just a shell script and can thus be depended on unconditionally
84 | # without any effect on build times.
85 | default = "@bazel_tools//tools/test:collect_cc_coverage",
86 | executable = True,
87 | cfg = "target",
88 | ),
89 | },
90 | test = True,
91 | )
92 |
--------------------------------------------------------------------------------
/fuzzing/private/runtime/BUILD:
--------------------------------------------------------------------------------
1 | load(":clang_runtime_lib.bzl", "clang_runtime_lib")
2 |
3 | alias(
4 | name = "asan",
5 | actual = select({
6 | "@platforms//os:linux": ":asan_linux",
7 | "@platforms//os:macos": ":asan_macos",
8 | }),
9 | visibility = ["//visibility:public"],
10 | )
11 |
12 | alias(
13 | name = "ubsan",
14 | actual = select({
15 | "@platforms//os:linux": ":ubsan_linux",
16 | "@platforms//os:macos": ":ubsan_macos",
17 | }),
18 | visibility = ["//visibility:public"],
19 | )
20 |
21 | clang_runtime_lib(
22 | name = "asan_linux",
23 | basenames = [
24 | # LLVM 15+
25 | "libclang_rt.asan.so",
26 | # LLVM 14 and earlier
27 | "libclang_rt.asan-x86_64.so",
28 | ],
29 | tags = ["manual"],
30 | )
31 |
32 | clang_runtime_lib(
33 | name = "asan_macos",
34 | basenames = ["libclang_rt.asan_osx_dynamic.dylib"],
35 | tags = ["manual"],
36 | )
37 |
38 | clang_runtime_lib(
39 | name = "ubsan_linux",
40 | basenames = [
41 | # LLVM 15+
42 | "libclang_rt.ubsan_standalone.so",
43 | # LLVM 14 and earlier
44 | "libclang_rt.ubsan_standalone-x86_64.so",
45 | ],
46 | tags = ["manual"],
47 | )
48 |
49 | clang_runtime_lib(
50 | name = "ubsan_macos",
51 | basenames = ["libclang_rt.ubsan_osx_dynamic.dylib"],
52 | tags = ["manual"],
53 | )
54 |
--------------------------------------------------------------------------------
/fuzzing/private/runtime/clang_runtime_lib.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2023 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Macro that extracts clang runtime libraries from the current cc_toolchain."""
16 |
17 | def clang_runtime_lib(*, name, basenames, **kwargs):
18 | """Provide the first available clang runtime library with any of the given basenames as output.
19 |
20 | The basename of the output file is always the first of the given basenames.
21 | """
22 | native.genrule(
23 | name = name,
24 | outs = basenames[:1],
25 | cmd = "\n".join(["""cp -f "$$($(CC) --print-file-name {})" $@ 2> /dev/null || true""".format(basename) for basename in basenames]),
26 | toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
27 | tools = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
28 | **kwargs
29 | )
30 |
--------------------------------------------------------------------------------
/fuzzing/private/util.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Miscellaneous utilities."""
16 |
17 | load("@bazel_skylib//lib:paths.bzl", "paths")
18 |
19 | def _generate_file_impl(ctx):
20 | ctx.actions.write(ctx.outputs.output, ctx.attr.contents)
21 |
22 | generate_file = rule(
23 | implementation = _generate_file_impl,
24 | doc = """
25 | Generates a file with a specified content string.
26 | """,
27 | attrs = {
28 | "contents": attr.string(
29 | doc = "The file contents.",
30 | mandatory = True,
31 | ),
32 | "output": attr.output(
33 | doc = "The output file to write.",
34 | mandatory = True,
35 | ),
36 | },
37 | )
38 |
39 | # Returns the path of a runfile that can be used to look up its absolute path
40 | # via the rlocation function provided by Bazel's runfiles libraries.
41 | def runfile_path(ctx, runfile):
42 | return paths.normalize(ctx.workspace_name + "/" + runfile.short_path)
43 |
--------------------------------------------------------------------------------
/fuzzing/replay/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Tools for replaying test files.
16 |
17 | load("@rules_cc//cc:cc_library.bzl", "cc_library")
18 | load("@rules_cc//cc:cc_test.bzl", "cc_test")
19 |
20 | package(default_visibility = ["//fuzzing:__subpackages__"])
21 |
22 | # Libraries.
23 | ############
24 |
25 | cc_library(
26 | name = "file_util",
27 | srcs = ["file_util.cc"],
28 | hdrs = ["file_util.h"],
29 | deps = [
30 | ":status_util",
31 | "@com_google_absl//absl/functional:function_ref",
32 | "@com_google_absl//absl/status",
33 | "@com_google_absl//absl/strings",
34 | ],
35 | )
36 |
37 | WEAK_LLVM_FUZZER_INITIALIZE = select({
38 | "@platforms//os:osx": ["-Wl,-U,_LLVMFuzzerInitialize"],
39 | "//conditions:default": [],
40 | })
41 |
42 | cc_library(
43 | name = "replay_main",
44 | srcs = ["replay_main.cc"],
45 | linkopts = WEAK_LLVM_FUZZER_INITIALIZE,
46 | deps = [
47 | ":test_replayer",
48 | "@com_google_absl//absl/status",
49 | "@com_google_absl//absl/strings",
50 | "@com_google_absl//absl/strings:str_format",
51 | ],
52 | alwayslink = True,
53 | )
54 |
55 | cc_library(
56 | name = "status_util",
57 | srcs = ["status_util.cc"],
58 | hdrs = ["status_util.h"],
59 | deps = [
60 | "@com_google_absl//absl/status",
61 | "@com_google_absl//absl/strings",
62 | ],
63 | )
64 |
65 | cc_library(
66 | name = "test_file_buffer",
67 | srcs = ["test_file_buffer.cc"],
68 | hdrs = ["test_file_buffer.h"],
69 | deps = [
70 | ":status_util",
71 | "@com_google_absl//absl/status",
72 | "@com_google_absl//absl/strings",
73 | ],
74 | )
75 |
76 | cc_library(
77 | name = "test_replayer",
78 | srcs = ["test_replayer.cc"],
79 | hdrs = ["test_replayer.h"],
80 | deps = [
81 | ":file_util",
82 | ":test_file_buffer",
83 | "@com_google_absl//absl/status",
84 | "@com_google_absl//absl/strings",
85 | "@com_google_absl//absl/strings:str_format",
86 | ],
87 | )
88 |
89 | # Tests.
90 | ########
91 |
92 | cc_test(
93 | name = "file_util_test",
94 | size = "small",
95 | srcs = ["file_util_test.cc"],
96 | deps = [
97 | ":file_util",
98 | "@com_google_absl//absl/strings",
99 | "@com_google_absl//absl/strings:str_format",
100 | "@com_google_googletest//:gtest",
101 | "@com_google_googletest//:gtest_main",
102 | ],
103 | )
104 |
105 | cc_test(
106 | name = "status_util_test",
107 | size = "small",
108 | srcs = ["status_util_test.cc"],
109 | deps = [
110 | ":status_util",
111 | "@com_google_googletest//:gtest",
112 | "@com_google_googletest//:gtest_main",
113 | ],
114 | )
115 |
116 | cc_test(
117 | name = "test_file_buffer_test",
118 | size = "small",
119 | srcs = ["test_file_buffer_test.cc"],
120 | deps = [
121 | ":file_util",
122 | ":test_file_buffer",
123 | "@com_google_absl//absl/strings",
124 | "@com_google_googletest//:gtest",
125 | "@com_google_googletest//:gtest_main",
126 | ],
127 | )
128 |
129 | cc_test(
130 | name = "test_replayer_test",
131 | size = "small",
132 | srcs = ["test_replayer_test.cc"],
133 | deps = [
134 | ":file_util",
135 | ":test_replayer",
136 | "@com_google_absl//absl/strings",
137 | "@com_google_googletest//:gtest",
138 | "@com_google_googletest//:gtest_main",
139 | ],
140 | )
141 |
--------------------------------------------------------------------------------
/fuzzing/replay/file_util.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/file_util.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 | #include
25 |
26 | #include "absl/functional/function_ref.h"
27 | #include "absl/status/status.h"
28 | #include "absl/strings/match.h"
29 | #include "absl/strings/str_cat.h"
30 | #include "absl/strings/string_view.h"
31 | #include "fuzzing/replay/status_util.h"
32 |
33 | namespace fuzzing {
34 |
35 | namespace {
36 |
37 | absl::Status TraverseDirectory(
38 | absl::string_view path,
39 | absl::FunctionRef callback) {
40 | DIR* dir = opendir(std::string(path).c_str());
41 | if (!dir) {
42 | return ErrnoStatus(absl::StrCat("could not open directory ", path), errno);
43 | }
44 | absl::Status status = absl::OkStatus();
45 | while (true) {
46 | errno = 0;
47 | struct dirent* entry = readdir(dir);
48 | if (!entry) {
49 | if (errno) {
50 | status.Update(ErrnoStatus(
51 | absl::StrCat("could not complete directory traversal for ", path),
52 | errno));
53 | }
54 | break;
55 | }
56 | auto entry_name = absl::string_view(entry->d_name);
57 | if (entry_name == "." || entry_name == "..") {
58 | continue;
59 | }
60 | const std::string entry_path = absl::StrCat(path, "/", entry_name);
61 | status.Update(YieldFiles(entry_path, callback));
62 | }
63 | closedir(dir);
64 | return status;
65 | }
66 |
67 | } // namespace
68 |
69 | absl::Status YieldFiles(
70 | absl::string_view path,
71 | absl::FunctionRef callback) {
72 | struct stat path_stat;
73 | if (stat(std::string(path).c_str(), &path_stat) < 0) {
74 | return ErrnoStatus(absl::StrCat("could not stat ", path), errno);
75 | }
76 | if (S_ISDIR(path_stat.st_mode)) {
77 | return TraverseDirectory(path, callback);
78 | }
79 | callback(path, path_stat);
80 | return absl::OkStatus();
81 | }
82 |
83 | absl::Status SetFileContents(absl::string_view path,
84 | absl::string_view contents) {
85 | FILE* f = fopen(std::string(path).c_str(), "w");
86 | if (!f) {
87 | return ErrnoStatus("could not open file", errno);
88 | }
89 | const size_t result = fwrite(contents.data(), 1, contents.size(), f);
90 | fclose(f);
91 | if (result < contents.size()) {
92 | return absl::UnknownError("could not write file contents");
93 | }
94 | return absl::OkStatus();
95 | }
96 |
97 | } // namespace fuzzing
98 |
--------------------------------------------------------------------------------
/fuzzing/replay/file_util.h:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Utilities for working with files and filesystems.
16 |
17 | #ifndef FUZZING_REPLAY_FILE_UTIL_H_
18 | #define FUZZING_REPLAY_FILE_UTIL_H_
19 |
20 | #include
21 |
22 | #include "absl/functional/function_ref.h"
23 | #include "absl/status/status.h"
24 | #include "absl/strings/string_view.h"
25 |
26 | namespace fuzzing {
27 |
28 | // Recursively traverses the directory at `path` and calls the provided
29 | // `callback` for each file encountered. The callback receives the file path and
30 | // its stat structure as arguments. Returns OK if the entire directory tree was
31 | // traversed successfully, or an error status if some parts could not be
32 | // traversed. If `path` refers to a file, the callback will be called once and
33 | // the function returns OK.
34 | absl::Status YieldFiles(
35 | absl::string_view path,
36 | absl::FunctionRef callback);
37 |
38 | // Opens the given `path` for writing and sets the file contents to `contents`.
39 | absl::Status SetFileContents(absl::string_view path,
40 | absl::string_view contents);
41 |
42 | } // namespace fuzzing
43 |
44 | #endif // FUZZING_REPLAY_FILE_UTIL_H_
45 |
--------------------------------------------------------------------------------
/fuzzing/replay/file_util_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/file_util.h"
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "absl/strings/str_cat.h"
26 | #include "absl/strings/str_format.h"
27 | #include "absl/strings/string_view.h"
28 | #include "gmock/gmock.h"
29 | #include "gtest/gtest.h"
30 |
31 | namespace fuzzing {
32 |
33 | namespace {
34 |
35 | std::function CollectPathsCallback(
36 | std::vector* collected_paths) {
37 | return [collected_paths](absl::string_view path, const struct stat&) {
38 | absl::FPrintF(stderr, "Collected path: %s\n", path);
39 | collected_paths->push_back(std::string(path));
40 | };
41 | }
42 |
43 | TEST(YieldFilesTest, ReturnsEmptyResultsOnEmptyDir) {
44 | const std::string root_dir =
45 | absl::StrCat(getenv("TEST_TMPDIR"), "/empty-root");
46 | ASSERT_EQ(mkdir(root_dir.c_str(), 0755), 0);
47 |
48 | std::vector collected_paths;
49 | const absl::Status status =
50 | YieldFiles(root_dir, CollectPathsCallback(&collected_paths));
51 | EXPECT_TRUE(status.ok());
52 | EXPECT_THAT(collected_paths, testing::IsEmpty());
53 | }
54 |
55 | TEST(YieldFilesTest, ReturnsErrorOnMissingDir) {
56 | const std::string missing_dir =
57 | absl::StrCat(getenv("TEST_TMPDIR"), "/missing");
58 | std::vector collected_paths;
59 | const absl::Status status =
60 | YieldFiles(missing_dir, CollectPathsCallback(&collected_paths));
61 | EXPECT_FALSE(status.ok());
62 | EXPECT_THAT(status.message(), testing::HasSubstr("could not stat"));
63 | }
64 |
65 | TEST(YieldFilesTest, YieldsTopLevelFiles) {
66 | const std::string root_dir =
67 | absl::StrCat(getenv("TEST_TMPDIR"), "/top-level-root");
68 | ASSERT_EQ(mkdir(root_dir.c_str(), 0755), 0);
69 | ASSERT_TRUE(SetFileContents(absl::StrCat(root_dir, "/a"), "foo").ok());
70 | ASSERT_TRUE(SetFileContents(absl::StrCat(root_dir, "/b"), "bar").ok());
71 | ASSERT_TRUE(SetFileContents(absl::StrCat(root_dir, "/c"), "baz").ok());
72 |
73 | std::vector collected_paths;
74 | const absl::Status status =
75 | YieldFiles(root_dir, CollectPathsCallback(&collected_paths));
76 | EXPECT_TRUE(status.ok());
77 | EXPECT_THAT(collected_paths, testing::SizeIs(3));
78 | }
79 |
80 | TEST(YieldFilesTest, YieldsDeepFiles) {
81 | const std::string root_dir =
82 | absl::StrCat(getenv("TEST_TMPDIR"), "/deep-root");
83 | ASSERT_EQ(mkdir(root_dir.c_str(), 0755), 0);
84 | const std::string child_dir = absl::StrCat(root_dir, "/child");
85 | ASSERT_EQ(mkdir(child_dir.c_str(), 0755), 0);
86 | const std::string leaf_dir = absl::StrCat(child_dir, "/leaf");
87 | ASSERT_EQ(mkdir(leaf_dir.c_str(), 0755), 0);
88 | ASSERT_TRUE(SetFileContents(absl::StrCat(root_dir, "/a"), "foo").ok());
89 | ASSERT_TRUE(SetFileContents(absl::StrCat(child_dir, "/b"), "bar").ok());
90 | ASSERT_TRUE(SetFileContents(absl::StrCat(leaf_dir, "/c"), "baz").ok());
91 | ASSERT_TRUE(SetFileContents(absl::StrCat(leaf_dir, "/d"), "boo").ok());
92 |
93 | std::vector collected_paths;
94 | const absl::Status status =
95 | YieldFiles(root_dir, CollectPathsCallback(&collected_paths));
96 | EXPECT_TRUE(status.ok());
97 | EXPECT_THAT(collected_paths, testing::SizeIs(4));
98 | }
99 |
100 | TEST(YieldFilesTest, YieldsHiddenFilesAndDirs) {
101 | const std::string root_dir =
102 | absl::StrCat(getenv("TEST_TMPDIR"), "/dir-with-hidden");
103 | ASSERT_EQ(mkdir(root_dir.c_str(), 0755), 0);
104 | ASSERT_TRUE(SetFileContents(absl::StrCat(root_dir, "/.a"), "foo").ok());
105 | const std::string child_dir = absl::StrCat(root_dir, "/.hidden");
106 | ASSERT_EQ(mkdir(child_dir.c_str(), 0755), 0);
107 | ASSERT_TRUE(SetFileContents(absl::StrCat(child_dir, "/b"), "bar").ok());
108 |
109 | std::vector collected_paths;
110 | const absl::Status status =
111 | YieldFiles(root_dir, CollectPathsCallback(&collected_paths));
112 | EXPECT_TRUE(status.ok());
113 | EXPECT_THAT(collected_paths, testing::SizeIs(2));
114 | }
115 |
116 | } // namespace
117 |
118 | } // namespace fuzzing
119 |
--------------------------------------------------------------------------------
/fuzzing/replay/replay_main.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #include "absl/status/status.h"
20 | #include "absl/strings/str_format.h"
21 | #include "fuzzing/replay/test_replayer.h"
22 |
23 | extern "C" {
24 | int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
25 | int LLVMFuzzerInitialize(int* argc, char*** argv) __attribute__((weak));
26 | }
27 |
28 | namespace {
29 |
30 | constexpr size_t kMaxTestFileSize = 4 * 1024 * 1024;
31 |
32 | } // namespace
33 |
34 | int main(int argc, char** argv) {
35 | if (LLVMFuzzerInitialize) {
36 | LLVMFuzzerInitialize(&argc, &argv);
37 | }
38 |
39 | absl::Status overall_status = absl::OkStatus();
40 | fuzzing::TestReplayer replayer(&LLVMFuzzerTestOneInput, kMaxTestFileSize);
41 | for (int i = 1; i < argc; ++i) {
42 | const absl::Status status = replayer.ReplayTests(argv[i]);
43 | if (!status.ok()) {
44 | absl::FPrintF(stderr, "** Errors encountered when replaying '%s': %s\n",
45 | argv[i], status.ToString());
46 | }
47 | overall_status.Update(status);
48 | }
49 | return overall_status.ok() ? EXIT_SUCCESS : EXIT_FAILURE;
50 | }
51 |
--------------------------------------------------------------------------------
/fuzzing/replay/status_util.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/status_util.h"
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "absl/status/status.h"
23 | #include "absl/strings/str_cat.h"
24 |
25 | namespace fuzzing {
26 |
27 | namespace {
28 |
29 | constexpr size_t kMaxErrorStringSize = 128;
30 |
31 | // Borrowed from absl/base/internal/strerror.cc
32 | const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
33 | #if defined(_WIN32)
34 | int rc = strerror_s(buf, buflen, errnum);
35 | buf[buflen - 1] = '\0'; // guarantee NUL termination
36 | if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
37 | return buf;
38 | #else
39 | // The type of `ret` is platform-specific; both of these branches must compile
40 | // either way but only one will execute on any given platform:
41 | auto ret = strerror_r(errnum, buf, buflen);
42 | if (std::is_same::value) {
43 | // XSI `strerror_r`; `ret` is `int`:
44 | if (ret) *buf = '\0';
45 | return buf;
46 | } else {
47 | // GNU `strerror_r`; `ret` is `char *`:
48 | return reinterpret_cast(ret);
49 | }
50 | #endif
51 | }
52 |
53 | // Borrowed from absl/base/internal/strerror.cc
54 | std::string StrErrorInternal(int errnum) {
55 | char buf[kMaxErrorStringSize];
56 | const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
57 | if (*str == '\0') {
58 | snprintf(buf, sizeof buf, "Unknown error %d", errnum);
59 | str = buf;
60 | }
61 | return str;
62 | }
63 |
64 | } // namespace
65 |
66 | absl::Status ErrnoStatus(absl::string_view message, int errno_value) {
67 | if (errno_value == 0) {
68 | return absl::OkStatus();
69 | } else {
70 | return absl::UnknownError(
71 | absl::StrCat(message, " (", StrErrorInternal(errno_value), ")"));
72 | }
73 | }
74 |
75 | } // namespace fuzzing
76 |
--------------------------------------------------------------------------------
/fuzzing/replay/status_util.h:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // Utilities for working with absl::Status values.
16 |
17 | #ifndef FUZZING_REPLAY_STATUS_UTIL_H_
18 | #define FUZZING_REPLAY_STATUS_UTIL_H_
19 |
20 | #include "absl/status/status.h"
21 | #include "absl/strings/string_view.h"
22 |
23 | namespace fuzzing {
24 |
25 | // Creates an error status value that includes the given `message` and a
26 | // description of the `errno_value`. Returns OK if `errno_value` is zero.
27 | absl::Status ErrnoStatus(absl::string_view message, int errno_value);
28 |
29 | } // namespace fuzzing
30 |
31 | #endif // FUZZING_REPLAY_STATUS_UTIL_H_
32 |
--------------------------------------------------------------------------------
/fuzzing/replay/status_util_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/status_util.h"
16 |
17 | #include
18 |
19 | #include "gmock/gmock.h"
20 | #include "gtest/gtest.h"
21 |
22 | namespace fuzzing {
23 |
24 | namespace {
25 |
26 | using ::testing::StrEq;
27 |
28 | TEST(StatusUtilTest, EmptyMessage) {
29 | const absl::Status status = ErrnoStatus("", ENOENT);
30 | EXPECT_EQ(status.code(), absl::StatusCode::kUnknown);
31 | EXPECT_THAT(status.message(), StrEq(" (No such file or directory)"));
32 | }
33 |
34 | TEST(StatusUtilTest, NonemptyMessage) {
35 | const absl::Status status = ErrnoStatus("could not open file", ENOENT);
36 | EXPECT_EQ(status.code(), absl::StatusCode::kUnknown);
37 | EXPECT_THAT(status.message(),
38 | StrEq("could not open file (No such file or directory)"));
39 | }
40 |
41 | TEST(StatusUtilTest, SuccessfulErrno) {
42 | const absl::Status status = ErrnoStatus("no error", 0);
43 | EXPECT_TRUE(status.ok());
44 | }
45 |
46 | TEST(StatusUtilTest, UnknownErrno) {
47 | const absl::Status status = ErrnoStatus("some error", 123456);
48 | EXPECT_EQ(status.code(), absl::StatusCode::kUnknown);
49 | EXPECT_THAT(status.message(), StrEq("some error (Unknown error 123456)"));
50 | }
51 |
52 | } // namespace
53 |
54 | } // namespace fuzzing
55 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_file_buffer.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/test_file_buffer.h"
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include "absl/status/status.h"
22 | #include "absl/strings/str_cat.h"
23 | #include "fuzzing/replay/status_util.h"
24 |
25 | namespace fuzzing {
26 |
27 | TestFileBuffer::TestFileBuffer(size_t max_size)
28 | : max_size_(max_size), last_size_(0) {
29 | assert(max_size > 0 && "max_size must be positive");
30 | buffer_.reset(new char[max_size]);
31 | }
32 |
33 | absl::Status TestFileBuffer::ReadFile(absl::string_view path) {
34 | FILE* f = fopen(std::string(path).c_str(), "r");
35 | if (!f) {
36 | last_size_ = 0;
37 | return ErrnoStatus(absl::StrCat("could not open test file ", path), errno);
38 | }
39 | last_size_ = fread(buffer_.get(), 1, max_size_, f);
40 | absl::Status status = absl::OkStatus();
41 | if (ferror(f)) {
42 | status =
43 | ErrnoStatus(absl::StrCat("could not read test file ", path), errno);
44 | } else if (!feof(f)) {
45 | status = absl::ResourceExhaustedError(
46 | absl::StrCat("file too large (max size ", max_size_, ")"));
47 | }
48 | fclose(f);
49 | return status;
50 | }
51 |
52 | } // namespace fuzzing
53 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_file_buffer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef FUZZING_REPLAY_TEST_FILE_BUFFER_H_
16 | #define FUZZING_REPLAY_TEST_FILE_BUFFER_H_
17 |
18 | #include
19 | #include
20 |
21 | #include "absl/status/status.h"
22 | #include "absl/strings/string_view.h"
23 |
24 | namespace fuzzing {
25 |
26 | // A memory buffer for reading and storing test data from files.
27 | //
28 | // This class permits the use of a single buffer to store the data from multiple
29 | // test files read sequentially, resulting in reduced memory churn for large
30 | // corpora consisting of multiple files.
31 | class TestFileBuffer {
32 | public:
33 | // Creates a new buffer holding up to `max_size` bytes.
34 | explicit TestFileBuffer(size_t max_size);
35 |
36 | TestFileBuffer(const TestFileBuffer&) = delete;
37 | TestFileBuffer& operator=(const TestFileBuffer&) = delete;
38 |
39 | // Attempts to read the contents of the file at `path`.
40 | //
41 | // Possible returned statuses:
42 | // * OK, if the entire file was read successfully.
43 | // * RESOURCE_EXHAUSTED, if the buffer could not fit the entire file. In
44 | // that case, only `max_size` bytes are read from the file.
45 | // * other error status, if for some reason the file could not be read.
46 | //
47 | // The (possibly partial or truncated) contents read from the file are
48 | // available through the `last_test()` accessor until the next invocation of
49 | // this method.
50 | absl::Status ReadFile(absl::string_view path);
51 |
52 | // Returns the file contents read from the last invocation of `ReadFile`, or
53 | // an empty string if the buffer has not been used.
54 | absl::string_view last_test() const {
55 | return absl::string_view(buffer_.get(), last_size_);
56 | }
57 |
58 | private:
59 | const size_t max_size_;
60 | size_t last_size_;
61 | std::unique_ptr buffer_;
62 | };
63 |
64 | } // namespace fuzzing
65 |
66 | #endif // FUZZING_REPLAY_TEST_FILE_BUFFER_H_
67 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_file_buffer_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/test_file_buffer.h"
16 |
17 | #include
18 | #include
19 |
20 | #include "absl/strings/str_cat.h"
21 | #include "fuzzing/replay/file_util.h"
22 | #include "gmock/gmock.h"
23 | #include "gtest/gtest.h"
24 |
25 | namespace fuzzing {
26 |
27 | namespace {
28 |
29 | TEST(TestFileBufferTest, EmptyBuffer) {
30 | TestFileBuffer buffer(1024);
31 | EXPECT_THAT(buffer.last_test(), testing::IsEmpty());
32 | }
33 |
34 | TEST(TestFileBufferTest, ReadsFileSuccessfully) {
35 | const std::string test_file =
36 | absl::StrCat(getenv("TEST_TMPDIR"), "/successful_test.txt");
37 | ASSERT_TRUE(SetFileContents(test_file, "123456789").ok());
38 |
39 | TestFileBuffer buffer(1024);
40 | const absl::Status status = buffer.ReadFile(test_file);
41 | EXPECT_TRUE(status.ok());
42 | EXPECT_EQ(buffer.last_test(), "123456789");
43 | }
44 |
45 | TEST(TestFileBufferTest, FailsOnMissingFile) {
46 | TestFileBuffer buffer(1024);
47 | const absl::Status status = buffer.ReadFile("missing_path");
48 | EXPECT_FALSE(status.ok());
49 | EXPECT_THAT(buffer.last_test(), testing::IsEmpty());
50 | }
51 |
52 | TEST(TestFileBufferTest, TruncatesTooLargeFile) {
53 | const std::string test_file =
54 | absl::StrCat(getenv("TEST_TMPDIR"), "/truncated_test.txt");
55 | ASSERT_TRUE(SetFileContents(test_file, "123456789").ok());
56 |
57 | TestFileBuffer buffer(4);
58 | const absl::Status status = buffer.ReadFile(test_file);
59 | EXPECT_EQ(status.code(), absl::StatusCode::kResourceExhausted);
60 | EXPECT_EQ(buffer.last_test(), "1234");
61 | }
62 |
63 | TEST(TestFileBufferTest, OverridesLastTest) {
64 | const std::string first_test_file =
65 | absl::StrCat(getenv("TEST_TMPDIR"), "/override_test_first.txt");
66 | ASSERT_TRUE(SetFileContents(first_test_file, "123456789").ok());
67 | const std::string second_test_file =
68 | absl::StrCat(getenv("TEST_TMPDIR"), "/override_test_second.txt");
69 | ASSERT_TRUE(SetFileContents(second_test_file, "ABCDEF").ok());
70 |
71 | TestFileBuffer buffer(1024);
72 | EXPECT_TRUE(buffer.ReadFile(first_test_file).ok());
73 | EXPECT_EQ(buffer.last_test(), "123456789");
74 | EXPECT_TRUE(buffer.ReadFile(second_test_file).ok());
75 | EXPECT_EQ(buffer.last_test(), "ABCDEF");
76 | EXPECT_FALSE(buffer.ReadFile("third_test_file_missing").ok());
77 | EXPECT_THAT(buffer.last_test(), testing::IsEmpty());
78 | }
79 |
80 | } // namespace
81 |
82 | } // namespace fuzzing
83 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_replayer.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/test_replayer.h"
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 |
23 | #include "absl/strings/str_cat.h"
24 | #include "absl/strings/str_format.h"
25 | #include "fuzzing/replay/file_util.h"
26 |
27 | namespace fuzzing {
28 |
29 | absl::Status TestReplayer::ReplayTestData(absl::string_view test) {
30 | std::unique_ptr test_copy(new uint8_t[test.size()]);
31 | memcpy(test_copy.get(), test.data(), test.size());
32 | const int result = callback_(test_copy.get(), test.size());
33 | if (result == 0) {
34 | return absl::OkStatus();
35 | } else {
36 | return absl::InternalError(absl::StrCat("LLVMFuzzerTestOneInput returned ",
37 | result, " instead of 0"));
38 | }
39 | }
40 |
41 | absl::Status TestReplayer::ReplayTestFile(absl::string_view path) {
42 | absl::Status status = test_file_buffer_.ReadFile(path);
43 | status.Update(ReplayTestData(test_file_buffer_.last_test()));
44 | return status;
45 | }
46 |
47 | absl::Status TestReplayer::ReplayTests(absl::string_view path) {
48 | absl::Status replay_status;
49 | const absl::Status yield_status =
50 | YieldFiles(path, [this, &replay_status](absl::string_view file_path,
51 | const struct stat& file_stat) {
52 | if (S_ISREG(file_stat.st_mode)) {
53 | const absl::Status status = ReplayTestFile(std::string(file_path));
54 | absl::FPrintF(stderr, "Replaying '%s' (%zd bytes): %s\n", file_path,
55 | file_stat.st_size, status.ToString());
56 | replay_status.Update(status);
57 | } else {
58 | absl::FPrintF(stderr, "Replaying '%s': SKIPPED (not a file)\n",
59 | file_path);
60 | }
61 | });
62 | replay_status.Update(yield_status);
63 | return replay_status;
64 | }
65 |
66 | } // namespace fuzzing
67 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_replayer.h:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef FUZZING_REPLAY_TEST_REPLAYER_H_
16 | #define FUZZING_REPLAY_TEST_REPLAYER_H_
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 |
24 | #include "absl/status/status.h"
25 | #include "absl/strings/string_view.h"
26 | #include "fuzzing/replay/test_file_buffer.h"
27 |
28 | namespace fuzzing {
29 |
30 | // Replays in sequence a collection of test files by calling a callback function
31 | // on the contents of each test file.
32 | class TestReplayer {
33 | public:
34 | // Creates a new test replayer instance configured to invoke `callback` for
35 | // each test file being replayed. The callback has the signature and expected
36 | // semantics of the standard `LLVMFuzzerTestOneInput` entry point.
37 | // `max_test_file_size` specifies the maximum test size allowed.
38 | TestReplayer(std::function callback,
39 | size_t max_test_file_size)
40 | : callback_(std::move(callback)), test_file_buffer_(max_test_file_size) {}
41 |
42 | TestReplayer(const TestReplayer&) = delete;
43 | TestReplayer& operator=(const TestReplayer&) = delete;
44 |
45 | // Replays all the test files found under `path`. The path may point to a file
46 | // or a directory. Directories are traversed recursively and all files
47 | // encountered are replayed. The contents of each test file are read in memory
48 | // and passed to the callback for execution.
49 | //
50 | // The files traversed and the result of each replay is printed to stderr.
51 | //
52 | // Returns OK if all files were traversed and replayed successfully, or an
53 | // error status if an error was encountered. The traversal is best-effort and
54 | // does not stop at the first error encountered.
55 | absl::Status ReplayTests(absl::string_view path);
56 |
57 | private:
58 | absl::Status ReplayTestData(absl::string_view test);
59 | absl::Status ReplayTestFile(absl::string_view path);
60 | absl::Status ReplayTestDirectory(absl::string_view path);
61 |
62 | const std::function callback_;
63 | TestFileBuffer test_file_buffer_;
64 | };
65 |
66 | } // namespace fuzzing
67 |
68 | #endif // FUZZING_REPLAY_TEST_REPLAYER_H_
69 |
--------------------------------------------------------------------------------
/fuzzing/replay/test_replayer_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "fuzzing/replay/test_replayer.h"
16 |
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 |
23 | #include "absl/strings/str_cat.h"
24 | #include "fuzzing/replay/file_util.h"
25 | #include "gmock/gmock.h"
26 | #include "gtest/gtest.h"
27 |
28 | namespace fuzzing {
29 |
30 | namespace {
31 |
32 | std::function CollectTestsCallback(
33 | std::vector* collected_tests) {
34 | return [collected_tests](const uint8_t* data, size_t size) {
35 | collected_tests->push_back(
36 | std::string(reinterpret_cast(data), size));
37 | return 0;
38 | };
39 | }
40 |
41 | TEST(TestReplayerTest, ReplaysFileSuccessfully) {
42 | const std::string test_file =
43 | absl::StrCat(getenv("TEST_TMPDIR"), "/single-test-file");
44 | ASSERT_TRUE(SetFileContents(test_file, "foo").ok());
45 |
46 | std::vector collected_tests;
47 | TestReplayer test_replayer(CollectTestsCallback(&collected_tests),
48 | /*max_test_file_size=*/1024);
49 | EXPECT_TRUE(test_replayer.ReplayTests(test_file).ok());
50 | EXPECT_THAT(collected_tests, testing::UnorderedElementsAre("foo"));
51 | }
52 |
53 | TEST(TestReplayerTest, ReplaysEmptyDirectorySuccessfully) {
54 | const std::string test_dir =
55 | absl::StrCat(getenv("TEST_TMPDIR"), "/empty-dir");
56 | ASSERT_EQ(mkdir(test_dir.c_str(), 0755), 0);
57 |
58 | std::vector collected_tests;
59 | TestReplayer test_replayer(CollectTestsCallback(&collected_tests),
60 | /*max_test_file_size=*/1024);
61 | EXPECT_TRUE(test_replayer.ReplayTests(test_dir).ok());
62 | EXPECT_THAT(collected_tests, testing::IsEmpty());
63 | }
64 |
65 | TEST(TestReplayerTest, ReplaysNonEmptyDirectorySuccessfully) {
66 | const std::string test_dir =
67 | absl::StrCat(getenv("TEST_TMPDIR"), "/non-empty-dir");
68 | ASSERT_EQ(mkdir(test_dir.c_str(), 0755), 0);
69 | const std::string child_dir = absl::StrCat(test_dir, "/child");
70 | ASSERT_EQ(mkdir(child_dir.c_str(), 0755), 0);
71 | const std::string leaf_dir = absl::StrCat(child_dir, "/leaf");
72 | ASSERT_EQ(mkdir(leaf_dir.c_str(), 0755), 0);
73 | ASSERT_TRUE(SetFileContents(absl::StrCat(test_dir, "/a"), "foo").ok());
74 | ASSERT_TRUE(SetFileContents(absl::StrCat(child_dir, "/b"), "bar").ok());
75 | ASSERT_TRUE(SetFileContents(absl::StrCat(leaf_dir, "/c"), "baz").ok());
76 | ASSERT_TRUE(SetFileContents(absl::StrCat(leaf_dir, "/d"), "boo").ok());
77 |
78 | std::vector collected_tests;
79 | TestReplayer test_replayer(CollectTestsCallback(&collected_tests),
80 | /*max_test_file_size=*/1024);
81 | EXPECT_TRUE(test_replayer.ReplayTests(test_dir).ok());
82 | EXPECT_THAT(collected_tests,
83 | testing::UnorderedElementsAre("foo", "bar", "baz", "boo"));
84 | }
85 |
86 | TEST(TestReplayerTest, FailsOnMissingFile) {
87 | std::vector collected_tests;
88 | TestReplayer test_replayer(CollectTestsCallback(&collected_tests),
89 | /*max_test_file_size=*/1024);
90 | EXPECT_FALSE(test_replayer.ReplayTests("missing_path").ok());
91 | EXPECT_THAT(collected_tests, testing::IsEmpty());
92 | }
93 |
94 | } // namespace
95 |
96 | } // namespace fuzzing
97 |
--------------------------------------------------------------------------------
/fuzzing/repositories.bzl:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Contains the external dependencies."""
16 |
17 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_jar")
18 | load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
19 | load("//fuzzing/private/oss_fuzz:repository.bzl", "oss_fuzz_repository")
20 |
21 | def rules_fuzzing_dependencies(oss_fuzz = True, honggfuzz = True, jazzer = True):
22 | """Instantiates the dependencies of the fuzzing rules.
23 |
24 | Args:
25 | oss_fuzz: Include OSS-Fuzz dependencies.
26 | honggfuzz: Include Honggfuzz dependencies.
27 | jazzer: Include Jazzer dependencies.
28 | """
29 |
30 | maybe(
31 | http_archive,
32 | name = "platforms",
33 | urls = [
34 | "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
35 | "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz",
36 | ],
37 | sha256 = "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74",
38 | )
39 | maybe(
40 | http_archive,
41 | name = "rules_python",
42 | sha256 = "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8",
43 | strip_prefix = "rules_python-0.28.0",
44 | url = "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz",
45 | )
46 | maybe(
47 | http_archive,
48 | name = "bazel_skylib",
49 | sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
50 | urls = [
51 | "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
52 | "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz",
53 | ],
54 | )
55 | maybe(
56 | http_archive,
57 | name = "com_google_absl",
58 | urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip"],
59 | strip_prefix = "abseil-cpp-20240116.1",
60 | integrity = "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk=",
61 | )
62 |
63 | if oss_fuzz:
64 | maybe(
65 | oss_fuzz_repository,
66 | name = "rules_fuzzing_oss_fuzz",
67 | )
68 |
69 | if honggfuzz:
70 | maybe(
71 | http_archive,
72 | name = "honggfuzz",
73 | build_file = "@rules_fuzzing//:honggfuzz.BUILD",
74 | sha256 = "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e",
75 | url = "https://github.com/google/honggfuzz/archive/2.5.zip",
76 | strip_prefix = "honggfuzz-2.5",
77 | )
78 |
79 | if jazzer:
80 | maybe(
81 | http_jar,
82 | name = "rules_fuzzing_jazzer",
83 | integrity = "sha256-WwSnW/097dHvODZlYdAYLmz7m/Su0t09yBH6aSLdyLs=",
84 | url = "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.24.0/jazzer-0.24.0.jar",
85 | )
86 |
87 | maybe(
88 | http_jar,
89 | name = "rules_fuzzing_jazzer_api",
90 | integrity = "sha256-cfhJJDSmErtNa+JrH81AjShCBGN9+N1VcIBfykiWjaQ=",
91 | url = "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.24.0/jazzer-api-0.24.0.jar",
92 | )
93 |
--------------------------------------------------------------------------------
/fuzzing/requirements.txt:
--------------------------------------------------------------------------------
1 | # Python requirements for the tools supporting the fuzzing rules. These are
2 | # installed automatically through the WORKSPACE configuration.
3 |
4 | absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3
5 | six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
6 |
--------------------------------------------------------------------------------
/fuzzing/tools/BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # This package contains tool scripts
16 |
17 | load("@fuzzing_py_deps//:requirements.bzl", "requirement")
18 | load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
19 | load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
20 |
21 | # Tools.
22 | ########
23 |
24 | py_binary(
25 | name = "launcher",
26 | srcs = ["launcher.py"],
27 | python_version = "PY3",
28 | visibility = ["//visibility:public"],
29 | deps = [requirement("absl-py")],
30 | )
31 |
32 | py_binary(
33 | name = "make_corpus_dir",
34 | srcs = ["make_corpus_dir.py"],
35 | python_version = "PY3",
36 | visibility = ["//visibility:public"],
37 | deps = [requirement("absl-py")],
38 | )
39 |
40 | py_binary(
41 | name = "validate_dict",
42 | srcs = ["validate_dict.py"],
43 | python_version = "PY3",
44 | visibility = ["//visibility:public"],
45 | deps = [
46 | ":dict_validation",
47 | requirement("absl-py"),
48 | ],
49 | )
50 |
51 | sh_binary(
52 | name = "noop_lcov_merger",
53 | srcs = ["noop_lcov_merger.sh"],
54 | )
55 |
56 | config_setting(
57 | name = "is_collecting_code_coverage",
58 | values = {"collect_code_coverage": "true"},
59 | )
60 |
61 | alias(
62 | name = "lcov_merger",
63 | actual = select({
64 | ":is_collecting_code_coverage": "@bazel_tools//tools/test:lcov_merger",
65 | "//conditions:default": ":noop_lcov_merger",
66 | }),
67 | visibility = ["//visibility:public"],
68 | )
69 |
70 | # Libraries.
71 | ############
72 |
73 | py_library(
74 | name = "dict_validation",
75 | srcs = ["dict_validation.py"],
76 | )
77 |
78 | # Tests.
79 | ########
80 |
81 | py_test(
82 | name = "dict_validation_test",
83 | srcs = ["dict_validation_test.py"],
84 | deps = [":dict_validation"],
85 | )
86 |
--------------------------------------------------------------------------------
/fuzzing/tools/dict_validation.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Lint as: python3
16 | """
17 | Validates the fuzzing dictionary.
18 | """
19 |
20 | import re
21 |
22 | _DICTIONARY_LINE_RE = re.compile(
23 | r'''[^"]* # Skip an arbitrary prefix (not used by libFuzzer).
24 | " # Must be enclosed in quotes.
25 | ( # A space or printable character in "C" locale except `\`...
26 | ((?!\\)[\f\r\t\v\x20-\x7e])
27 | |
28 | \\( # ...or an escape sequence...
29 | [\\\"] # ...consisting of either `\` or `"`...
30 | |
31 | x[0-9a-f]{2} # ...or a hexa number, e.g. '\x0f'
32 | )
33 | )+
34 | "
35 | \s* # Skip any space after the entry.''',
36 | flags=re.IGNORECASE | re.VERBOSE)
37 |
38 | def validate_line(line):
39 | """Validates a single line in the fuzzing dictionary entry.
40 |
41 | Args:
42 | line: a string containing a single line in the fuzzing dictionary.
43 |
44 | Returns:
45 | True if the argument is allowed to exist in a fuzzing dictionary,
46 | otherwise False.
47 | """
48 | line = line.strip()
49 | if not line or line.startswith('#'):
50 | return True
51 | else:
52 | return re.fullmatch(_DICTIONARY_LINE_RE, line) is not None
53 |
--------------------------------------------------------------------------------
/fuzzing/tools/dict_validation_test.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Lint as: python3
16 | """
17 | Unit tests for dict_validator.py
18 | """
19 |
20 | import unittest
21 | from fuzzing.tools.dict_validation import validate_line
22 |
23 |
24 | class DictValidatorTest(unittest.TestCase):
25 |
26 | def test_plain_entries(self):
27 | self.assertTrue(validate_line('kw1="blah"'))
28 | self.assertTrue(validate_line('"0123456789"'))
29 | self.assertTrue(validate_line('"abcdefghijklmnopqrstuvwxyz"'))
30 | self.assertTrue(validate_line('"ABCDEFGHIJKLMNOPQRSTUVWXYZ"'))
31 | self.assertTrue(validate_line('"!"#$%&\'()*+,-./:;<=>?@[]^_`{|}~ "'))
32 | self.assertTrue(validate_line('"\t\r\f\v"'))
33 |
34 | def test_bad_chars(self):
35 | self.assertFalse(validate_line('"\x07"'))
36 | self.assertFalse(validate_line('"Ā"'))
37 | self.assertFalse(validate_line('"😀"'))
38 |
39 | def test_escaped_words(self):
40 | self.assertTrue(validate_line('kw2="\\"ac\\\\dc\\""'))
41 | self.assertTrue(validate_line('kw3="\\xF7\\xF8"'))
42 | self.assertTrue(validate_line('"foo\\x0Abar"'))
43 |
44 | def test_invalid_escaped_words(self):
45 | self.assertFalse(validate_line('"\\A"'))
46 |
47 | def test_unfinished_escape(self):
48 | self.assertFalse(validate_line('"\\"'))
49 | self.assertFalse(validate_line('"\\x"'))
50 | self.assertFalse(validate_line('"\\x1"'))
51 |
52 | def test_comment(self):
53 | self.assertTrue(validate_line('# valid dictionary entries'))
54 |
55 | def test_space_after_entry(self):
56 | self.assertTrue(validate_line('"entry" \t\r\f'))
57 |
58 | def test_nonspace_after_entry(self):
59 | self.assertFalse(validate_line('"entry"suffix'))
60 |
61 | def test_empty_entry(self):
62 | self.assertFalse(validate_line('""'))
63 |
64 | def test_empty_string(self):
65 | self.assertTrue(validate_line(''))
66 |
67 | def test_spaces(self):
68 | self.assertTrue(validate_line(' '))
69 |
70 | def test_plain_words(self):
71 | self.assertFalse(validate_line('Invalid dictionary entries'))
72 |
73 | def test_single_quote(self):
74 | self.assertFalse(validate_line('"'))
75 |
76 |
77 | if __name__ == '__main__':
78 | unittest.main()
79 |
--------------------------------------------------------------------------------
/fuzzing/tools/launcher.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Lint as: python3
16 | """
17 | Wrapper tool providing a uniform flag interface for launching fuzz tests.
18 |
19 | This tool acts as a frontend to fuzz test launching. It receives fuzz test
20 | execution parameters as a set of user-provided flags and relays the
21 | configuration to a pluggable backend launcher script via environment
22 | variables. The backend launcher implements the engine-specific logic of
23 | translating the environment variables into the final command that launches
24 | the fuzzer executable.
25 | """
26 |
27 | import os
28 | import shutil
29 | import sys
30 |
31 | from absl import app
32 | from absl import flags
33 |
34 | FLAGS = flags.FLAGS
35 |
36 | flags.DEFINE_string(
37 | "engine_launcher", None,
38 | "Path to a shell script that launches the fuzzing engine executable with the appropriate command line arguments."
39 | )
40 |
41 | flags.DEFINE_string("binary_path", None, "Path to the fuzz test binary.")
42 |
43 | flags.DEFINE_bool(
44 | "regression", False,
45 | "If set True, the script will trigger the target as a regression test.")
46 |
47 | flags.DEFINE_integer(
48 | "timeout_secs",
49 | 0,
50 | "The maximum duration, in seconds, of the fuzzer run launched.",
51 | lower_bound=0)
52 |
53 | flags.DEFINE_string(
54 | "corpus_dir", None,
55 | "If non-empty, a directory that will be used as a seed corpus for the fuzzer."
56 | )
57 |
58 | flags.DEFINE_string("dictionary_path", None,
59 | "If non-empty, a dictionary file of input keywords.")
60 |
61 | flags.DEFINE_string(
62 | "fuzzing_output_root", "/tmp/fuzzing",
63 | "The root directory for storing all generated artifacts during fuzzing.")
64 |
65 | flags.DEFINE_bool(
66 | "clean", False,
67 | "If set, cleans up the output directory of the target before fuzzing.")
68 |
69 | flags.mark_flag_as_required("engine_launcher")
70 | flags.mark_flag_as_required("binary_path")
71 |
72 |
73 | def main(argv):
74 | # TODO(sbucur): Obtain a target-specific path here.
75 | target_output_root = os.path.join(FLAGS.fuzzing_output_root)
76 | print("Using test output root: %s" % target_output_root, file=sys.stderr)
77 | if FLAGS.clean:
78 | print("Cleaning up the test output root before starting fuzzing...",
79 | file=sys.stderr)
80 | try:
81 | shutil.rmtree(target_output_root)
82 | except FileNotFoundError:
83 | pass
84 | os.makedirs(target_output_root, exist_ok=True)
85 |
86 | corpus_output_path = os.path.join(target_output_root, 'corpus')
87 | print('Writing new corpus elements at: %s' % corpus_output_path,
88 | file=sys.stderr)
89 | os.makedirs(corpus_output_path, exist_ok=True)
90 |
91 | artifacts_output_path = os.path.join(target_output_root, 'artifacts')
92 | print('Writing new artifacts at: %s' % artifacts_output_path)
93 | os.makedirs(artifacts_output_path, exist_ok=True)
94 |
95 | os.environ["FUZZER_BINARY"] = FLAGS.binary_path
96 | os.environ["FUZZER_TIMEOUT_SECS"] = str(FLAGS.timeout_secs)
97 | os.environ["FUZZER_IS_REGRESSION"] = "1" if FLAGS.regression else "0"
98 | os.environ["FUZZER_OUTPUT_ROOT"] = target_output_root
99 | os.environ["FUZZER_OUTPUT_CORPUS_DIR"] = corpus_output_path
100 | os.environ["FUZZER_ARTIFACTS_DIR"] = artifacts_output_path
101 | if FLAGS.dictionary_path:
102 | os.environ["FUZZER_DICTIONARY_PATH"] = FLAGS.dictionary_path
103 | if FLAGS.corpus_dir:
104 | os.environ["FUZZER_SEED_CORPUS_DIR"] = FLAGS.corpus_dir
105 | os.execv("/bin/bash", ["/bin/bash", FLAGS.engine_launcher] + argv[1:])
106 |
107 |
108 | if __name__ == "__main__":
109 | app.run(main)
110 |
--------------------------------------------------------------------------------
/fuzzing/tools/make_corpus_dir.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Lint as: python3
16 | """
17 | Copies and renames a set of corpus files into a given directory.
18 | """
19 |
20 | from absl import app
21 | from absl import flags
22 | from sys import stderr
23 | import glob
24 | import os
25 | import shutil
26 |
27 | FLAGS = flags.FLAGS
28 |
29 | flags.DEFINE_list("corpus_list", [],
30 | "Each element in the list stands for a corpus file")
31 |
32 | flags.DEFINE_string("corpus_list_file", None,
33 | "An optional file that lists corpus paths by lines")
34 |
35 | flags.DEFINE_string("output_dir", None, "The path of the output directory")
36 |
37 | flags.mark_flag_as_required("output_dir")
38 |
39 | def expand_corpus_to_file_list(corpus, file_list):
40 | if not os.path.exists(corpus):
41 | raise FileNotFoundError("file " + corpus + " doesn't exist")
42 | if os.path.isdir(corpus):
43 | # The first element in glob("dir/**") is "dir/", which needs to be excluded
44 | file_list.extend(glob.glob(os.path.join(corpus, "**"), recursive=True)[1:])
45 | else:
46 | file_list.append(corpus)
47 |
48 | def main(argv):
49 | if not os.path.exists(FLAGS.output_dir):
50 | os.makedirs(FLAGS.output_dir)
51 |
52 | expanded_file_list = []
53 | for corpus in FLAGS.corpus_list:
54 | expand_corpus_to_file_list(corpus, expanded_file_list)
55 | if FLAGS.corpus_list_file:
56 | with open(FLAGS.corpus_list_file) as corpus_list_file:
57 | for corpus_line in corpus_list_file:
58 | expand_corpus_to_file_list(
59 | corpus_line.rstrip("\n"), expanded_file_list)
60 |
61 | if expanded_file_list:
62 | for corpus in expanded_file_list:
63 | dest = os.path.join(FLAGS.output_dir, corpus.replace("/", "-"))
64 | # Whatever the separator we choose, there is an chance that
65 | # the dest name conflicts with another file
66 | if os.path.exists(dest):
67 | print("ERROR: file " + dest + " existed.", file=stderr)
68 | return -1
69 | shutil.copy(corpus, dest)
70 | else:
71 | open(os.path.join(FLAGS.output_dir, "empty_test"), "a").close()
72 | return 0
73 |
74 |
75 | if __name__ == '__main__':
76 | app.run(main)
77 |
--------------------------------------------------------------------------------
/fuzzing/tools/noop_lcov_merger.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | # This script is a trivial to build replacement for the LCOV coverage merge tool
3 | # shipped with Bazel in situations where code coverage is not being collected.
4 | # It prevents the build time overhead and Java toolchain requirement incurred by
5 | # the real tool when it is not needed.
6 | exit 0
7 |
--------------------------------------------------------------------------------
/fuzzing/tools/validate_dict.py:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Lint as: python3
16 | """
17 | Validates and merges a set of fuzzing dictionary files into a single output.
18 | """
19 |
20 | from absl import app
21 | from absl import flags
22 | from fuzzing.tools.dict_validation import validate_line
23 | from sys import stderr
24 |
25 | FLAGS = flags.FLAGS
26 |
27 | flags.DEFINE_list("dict_list", [],
28 | "Each element in the list stands for a dictionary file")
29 |
30 | flags.DEFINE_string("output_file", "",
31 | "The name of the output merged dictionary file")
32 |
33 |
34 | def validate_dict(dict_path, output_stream):
35 | with open(dict_path, 'r') as dict:
36 | for index, line in enumerate(dict.readlines()):
37 | line = line.strip()
38 | if not validate_line(line):
39 | print("ERROR: invalid dictionary entry '%s' in %s:%d" %
40 | (line, dict_path, index + 1),
41 | file=stderr)
42 | return False
43 | if output_stream:
44 | output_stream.write(line + "\n")
45 | return True
46 |
47 |
48 | def main(argv):
49 | output = open(FLAGS.output_file, 'w') if FLAGS.output_file else None
50 | try:
51 | for dict_path in FLAGS.dict_list:
52 | if not validate_dict(dict_path, output):
53 | return -1
54 | finally:
55 | if output:
56 | output.close()
57 | return 0
58 |
59 |
60 | if __name__ == '__main__':
61 | app.run(main)
62 |
--------------------------------------------------------------------------------
/honggfuzz.BUILD:
--------------------------------------------------------------------------------
1 | # Copyright 2020 Google LLC
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # https://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # Bazel rules for building the Honggfuzz binary and the library linked with the
16 | # fuzz test executables.
17 | #
18 | # To use Honggfuzz, the following OS packages need to be installed:
19 | # * libunwind-dev
20 | # * libblocksruntime-dev
21 |
22 | # Disable the layering check for including the external headers.
23 | package(features = ["-layering_check"])
24 |
25 | HF_ARCH = select({
26 | "@platforms//os:osx": ["-D_HF_ARCH_DARWIN"],
27 | "//conditions:default": ["-D_HF_ARCH_LINUX"],
28 | })
29 |
30 | COMMON_COPTS = [
31 | "-D_GNU_SOURCE",
32 | ] + HF_ARCH + [
33 | "-fPIC",
34 | "-Wall",
35 | "-Wextra",
36 | "-Werror",
37 | "-Wno-override-init",
38 | "-Wno-initializer-overrides",
39 | "-Wno-gnu-empty-initializer",
40 | "-Wno-format-pedantic",
41 | "-Wno-gnu-statement-expression",
42 | "-mllvm",
43 | "-inline-threshold=2000",
44 | "-fblocks",
45 |
46 | # Do not instrument Honggfuzz itself, in order to avoid recursive
47 | # instrumentation calls that would crash the fuzz test binary.
48 | "-fsanitize-coverage=0",
49 | "-fno-sanitize=all",
50 | ]
51 |
52 | LIBRARY_COPTS = [
53 | "-fno-stack-protector",
54 | "-U_FORTIFY_SOURCE",
55 | "-D_FORTIFY_SOURCE=0",
56 | ]
57 |
58 | # Linker options for intercepting common memory operations. Should stay in sync
59 | # with https://github.com/google/honggfuzz/blob/master/hfuzz_cc/hfuzz-cc.c
60 | SYMBOL_WRAP_LINKOPTS = select({
61 | "@platforms//os:osx": [],
62 | "//conditions:default": [
63 | # Intercept common *cmp functions.
64 | "-Wl,--wrap=strcmp",
65 | "-Wl,--wrap=strcasecmp",
66 | "-Wl,--wrap=stricmp",
67 | "-Wl,--wrap=strncmp",
68 | "-Wl,--wrap=strncasecmp",
69 | "-Wl,--wrap=strnicmp",
70 | "-Wl,--wrap=strstr",
71 | "-Wl,--wrap=strcasestr",
72 | "-Wl,--wrap=memcmp",
73 | "-Wl,--wrap=bcmp",
74 | "-Wl,--wrap=memmem",
75 | "-Wl,--wrap=strcpy",
76 | # Apache httpd
77 | "-Wl,--wrap=ap_cstr_casecmp",
78 | "-Wl,--wrap=ap_cstr_casecmpn",
79 | "-Wl,--wrap=ap_strcasestr",
80 | "-Wl,--wrap=apr_cstr_casecmp",
81 | "-Wl,--wrap=apr_cstr_casecmpn",
82 | # *SSL
83 | "-Wl,--wrap=CRYPTO_memcmp",
84 | "-Wl,--wrap=OPENSSL_memcmp",
85 | "-Wl,--wrap=OPENSSL_strcasecmp",
86 | "-Wl,--wrap=OPENSSL_strncasecmp",
87 | "-Wl,--wrap=memcmpct",
88 | # libXML2
89 | "-Wl,--wrap=xmlStrncmp",
90 | "-Wl,--wrap=xmlStrcmp",
91 | "-Wl,--wrap=xmlStrEqual",
92 | "-Wl,--wrap=xmlStrcasecmp",
93 | "-Wl,--wrap=xmlStrncasecmp",
94 | "-Wl,--wrap=xmlStrstr",
95 | "-Wl,--wrap=xmlStrcasestr",
96 | # Samba
97 | "-Wl,--wrap=memcmp_const_time",
98 | "-Wl,--wrap=strcsequal",
99 | # LittleCMS
100 | "-Wl,--wrap=cmsstrcasecmp",
101 | # GLib
102 | "-Wl,--wrap=g_strcmp0",
103 | "-Wl,--wrap=g_strcasecmp",
104 | "-Wl,--wrap=g_strncasecmp",
105 | "-Wl,--wrap=g_strstr_len",
106 | "-Wl,--wrap=g_ascii_strcasecmp",
107 | "-Wl,--wrap=g_ascii_strncasecmp",
108 | "-Wl,--wrap=g_str_has_prefix",
109 | "-Wl,--wrap=g_str_has_suffix",
110 | # CUrl
111 | "-Wl,--wrap=Curl_strcasecompare",
112 | "-Wl,--wrap=curl_strequal",
113 | "-Wl,--wrap=Curl_safe_strcasecompare",
114 | "-Wl,--wrap=Curl_strncasecompare",
115 | "-Wl,--wrap=curl_strnequal",
116 | ],
117 | })
118 |
119 | cc_library(
120 | name = "honggfuzz_common",
121 | srcs = glob(["libhfcommon/*.c"]),
122 | hdrs = glob(["libhfcommon/*.h"]),
123 | copts = COMMON_COPTS + LIBRARY_COPTS,
124 | )
125 |
126 | LIB_RT = select({
127 | "@platforms//os:osx": [],
128 | "//conditions:default": ["-lrt"],
129 | })
130 |
131 | cc_library(
132 | name = "honggfuzz_engine",
133 | srcs = glob([
134 | "libhfuzz/*.c",
135 | "libhfuzz/*.h",
136 | "*.h",
137 | ]),
138 | copts = COMMON_COPTS + LIBRARY_COPTS,
139 | linkopts = SYMBOL_WRAP_LINKOPTS + [
140 | "-ldl",
141 | "-lpthread",
142 | ] + LIB_RT,
143 | visibility = ["//visibility:public"],
144 | deps = [
145 | ":honggfuzz_common",
146 | ],
147 | alwayslink = 1,
148 | )
149 |
150 | cc_binary(
151 | name = "honggfuzz",
152 | srcs = glob([
153 | "*.c",
154 | "*.h",
155 | ]) + glob([
156 | "linux/*.c",
157 | "linux/*.h",
158 | ]),
159 | copts = COMMON_COPTS + [
160 | "-D_HF_LINUX_NO_BFD",
161 | ],
162 | includes = [
163 | ".",
164 | "linux",
165 | ],
166 | # Consider linking statically with
167 | # -l:libunwind-ptrace.a and -l:libunwind-generic.a.
168 | linkopts = [
169 | "-lpthread",
170 | "-lunwind-ptrace",
171 | "-lunwind-generic",
172 | "-lunwind",
173 | ] + LIB_RT + [
174 | "-llzma",
175 | "-Wl,-Bstatic",
176 | "-lBlocksRuntime",
177 | "-Wl,-Bdynamic",
178 | ],
179 | linkstatic = 1,
180 | visibility = ["//visibility:public"],
181 | deps = [
182 | ":honggfuzz_common",
183 | ],
184 | )
185 |
--------------------------------------------------------------------------------
/update_docs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright 2020 Google LLC
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | set -euo pipefail
17 |
18 | bazel build //docs:cc_fuzzing_docs //docs:java_fuzzing_docs
19 | cp bazel-bin/docs/cc-fuzzing-rules.md bazel-bin/docs/java-fuzzing-rules.md docs/
20 |
--------------------------------------------------------------------------------