├── .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 | --------------------------------------------------------------------------------