1# Copyright 2020 The Pigweed Authors 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# 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, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14 15import("//build_overrides/pigweed.gni") 16 17import("$dir_pw_build/error.gni") 18import("$dir_pw_build/target_types.gni") 19import("$dir_pw_docgen/docs.gni") 20import("$dir_pw_third_party/fuzztest/fuzztest.gni") 21import("$dir_pw_unit_test/test.gni") 22 23config("public_include_path") { 24 include_dirs = [ "public" ] 25 visibility = [ ":*" ] 26} 27 28config("private_include_path") { 29 include_dirs = [ "private" ] 30 visibility = [ ":*" ] 31} 32 33config("overrides_include_path") { 34 include_dirs = [ 35 "public_overrides", 36 "private_overrides", 37 ] 38 visibility = [ ":*" ] 39} 40 41# See https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode 42config("fuzzing_build_mode_unsafe_for_production") { 43 defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ] 44} 45 46pw_doc_group("docs") { 47 sources = [ 48 "concepts.rst", 49 "docs.rst", 50 "guides/fuzztest.rst", 51 "guides/index.rst", 52 "guides/libfuzzer.rst", 53 "guides/reproducing_oss_fuzz_bugs.rst", 54 ] 55 inputs = [ 56 "examples/fuzztest/BUILD.gn", 57 "examples/fuzztest/BUILD.bazel", 58 "examples/fuzztest/CMakeLists.txt", 59 "examples/fuzztest/metrics.h", 60 "examples/fuzztest/metrics_unittest.cc", 61 "examples/fuzztest/metrics_fuzztest.cc", 62 ] 63} 64 65pw_test_group("tests") { 66 group_deps = [ 67 ":fuzztest_tests", 68 "examples/fuzztest:tests", 69 "examples/libfuzzer:tests", 70 ] 71} 72 73pw_source_set("asan_default_options") { 74 sources = [ "asan_default_options.c" ] 75} 76 77################################################################################ 78# FuzzTest support 79# 80# Create FuzzTest-style fuzzers by adding a dep on dir_pw_fuzzer:fuzztest 81 82group("fuzztest") { 83 if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { 84 public_deps = [ ":fuzztest.enabled" ] 85 } else { 86 public_deps = [ ":fuzztest.disabled" ] 87 } 88} 89 90# Used by fuzzable unit tests when fuzzing is enabled. Includes headers and deps 91# that provide a Pigweed-compatible subset of FuzzTest, as well as extensions to 92# support common Pigweed types. 93if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { 94 pw_source_set("fuzztest.enabled") { 95 public = [ 96 "private/pw_fuzzer/internal/fuzztest.h", 97 "public/pw_fuzzer/fuzztest.h", 98 ] 99 public_configs = [ 100 ":public_include_path", 101 ":private_include_path", 102 ] 103 public_deps = [ 104 "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_core", 105 dir_pw_containers, 106 dir_pw_result, 107 dir_pw_status, 108 dir_pw_string, 109 ] 110 } 111} 112 113# Used by fuzzable unit tests when fuzzing is disabled. Includes stubs of the 114# Pigweed-compatible subset of FuzzTest's interface, as well as extensions to 115# support common Pigweed types. 116pw_source_set("fuzztest.disabled") { 117 public = [ 118 "private_overrides/pw_fuzzer/internal/fuzztest.h", 119 "public/pw_fuzzer/fuzztest.h", 120 "public_overrides/fuzztest/fuzztest.h", 121 ] 122 public_configs = [ 123 ":public_include_path", 124 ":overrides_include_path", 125 ] 126 public_deps = [ 127 dir_pw_containers, 128 dir_pw_result, 129 dir_pw_status, 130 dir_pw_string, 131 ] 132} 133 134pw_test("fuzztest_tests") { 135 sources = [ "domain_test.cc" ] 136 deps = [ ":fuzztest" ] 137} 138 139# This target should only be used when defining a fuzzing toolchain, e.g. to set 140# `pw_unit_test_BACKEND = "$dir_pw_fuzzer:gtest" 141# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. 142if (dir_pw_third_party_googletest == "") { 143 pw_error("gtest") { 144 message_lines = [ 145 "pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ", 146 "but dir_pw_third_party_googletest is not set.", 147 ] 148 } 149} else if (!pw_toolchain_FUZZING_ENABLED) { 150 pw_error("gtest") { 151 message_lines = [ 152 "pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ", 153 "but $current_toolchain does not support fuzzing.", 154 ] 155 } 156} else { 157 group("gtest") { 158 if (pw_toolchain_OSS_FUZZ_ENABLED) { 159 public_deps = [ "$dir_pw_unit_test:light" ] 160 } else { 161 public_deps = [ "$dir_pw_unit_test:googletest" ] 162 } 163 } 164} 165 166# This target should only be used when defining a fuzzing toolchain, e.g. to set 167# `pw_unit_test_MAIN = "$dir_pw_fuzzer:fuzztest_main" 168# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. 169if (dir_pw_third_party_fuzztest == "") { 170 pw_error("fuzztest_main") { 171 message_lines = [ 172 "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", 173 "but dir_pw_third_party_fuzztest is not set.", 174 ] 175 } 176} else if (!pw_toolchain_FUZZING_ENABLED) { 177 pw_error("fuzztest_main") { 178 message_lines = [ 179 "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", 180 "but $current_toolchain does not support fuzzing.", 181 ] 182 } 183} else { 184 group("fuzztest_main") { 185 if (pw_toolchain_OSS_FUZZ_ENABLED) { 186 deps = [ "$dir_pw_unit_test:simple_printing_main" ] 187 } else { 188 deps = [ 189 ":asan_default_options", 190 "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_gtest_main", 191 ] 192 } 193 } 194} 195 196################################################################################ 197# libFuzzer support 198# 199# Create libFuzzer-style fuzzers by using the `pw_fuzzer` template from 200# fuzzer.gni. 201 202# Add flags for linking against compiler-rt's libFuzzer. This is added 203# automatically by `pw_fuzzer`. 204config("libfuzzer_config") { 205 ldflags = [ "-fsanitize=fuzzer" ] 206} 207 208# Includes wrapper's for LLVM's libFuzzer compiler runtime library. 209pw_source_set("libfuzzer") { 210 public = [ 211 "public/pw_fuzzer/asan_interface.h", 212 "public/pw_fuzzer/fuzzed_data_provider.h", 213 ] 214 public_configs = [ ":public_include_path" ] 215 public_deps = [ dir_pw_log ] 216} 217 218# This can be linked against fuzz target functions to create unit tests for 219# them. 220pw_source_set("libfuzzer_test") { 221 testonly = pw_unit_test_TESTONLY 222 sources = [ "pw_fuzzer_disabled.cc" ] 223 public_deps = [ ":libfuzzer" ] 224 deps = [ dir_pw_unit_test ] 225} 226 227# libFuzzer-based fuzzers have a distinct dep graph. 228group("fuzzers") { 229 deps = [ "examples/libfuzzer:fuzzers" ] 230} 231 232################################################################################ 233# Local fuzzing support 234 235# Add flags for adding LLVM sanitizer coverage for fuzzing. This is added by 236# the host_clang_fuzz toolchains. 237config("instrumentation") { 238 cflags = [ "-fsanitize=fuzzer-no-link" ] 239} 240 241################################################################################ 242# OSS-Fuzz support 243# 244# OSS-Fuzz manipulates compiler and linker flags directly. See 245# google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements. 246# 247# WARNING: This is not hermetic by design. It never can be, and never will be. 248 249config("oss_fuzz_instrumentation") { 250 cflags_c = string_split(getenv("CFLAGS")) 251 cflags_cc = string_split(getenv("CXXFLAGS")) 252 253 # OSS-Fuzz sets "-stdlib=libc++", which conflicts with the "-nostdinc++" set 254 # by `pw_minimal_cpp_stdlib`. 255 if (cflags_cc + [ "-stdlib=libc++" ] - [ "-stdlib=libc++" ] != cflags_cc) { 256 cflags_cc += [ "-Wno-unused-command-line-argument" ] 257 } 258 259 # Disable UBSan vptr when the target is built with -fno-rtti. 260 if (cflags_cc + [ "-fno-rtti" ] - [ "-fno-rtti" ] != cflags_cc) { 261 cflags_cc += [ " -fno-sanitize=vptr" ] 262 } 263 cflags_cc += [ "-fcoverage-compilation-dir=" + getenv("PW_ROOT") ] 264 265 ldflags = cflags_cc + [ "-fuse-ld=lld" ] 266} 267 268config("libfuzzer_oss_fuzz_config") { 269 engine = getenv("LIB_FUZZING_ENGINE") 270 if (engine == "") { 271 engine = "-fsanitize=fuzzer" 272 } 273 ldflags = [ engine ] 274} 275