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 "doc_resources/pw_fuzzer_coverage_guided.png", 57 "examples/fuzztest/BUILD.gn", 58 "examples/fuzztest/BUILD.bazel", 59 "examples/fuzztest/CMakeLists.txt", 60 "examples/fuzztest/metrics.h", 61 "examples/fuzztest/metrics_unittest.cc", 62 "examples/fuzztest/metrics_fuzztest.cc", 63 ] 64} 65 66pw_test_group("tests") { 67 group_deps = [ 68 ":fuzztest_tests", 69 "examples/fuzztest:tests", 70 "examples/libfuzzer:tests", 71 ] 72} 73 74pw_source_set("asan_default_options") { 75 sources = [ "asan_default_options.c" ] 76} 77 78################################################################################ 79# FuzzTest support 80# 81# Create FuzzTest-style fuzzers by adding a dep on dir_pw_fuzzer:fuzztest 82 83group("fuzztest") { 84 if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { 85 public_deps = [ ":fuzztest.enabled" ] 86 } else { 87 public_deps = [ ":fuzztest.disabled" ] 88 } 89} 90 91# Used by fuzzable unit tests when fuzzing is enabled. Includes headers and deps 92# that provide a Pigweed-compatible subset of FuzzTest, as well as extensions to 93# support common Pigweed types. 94if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { 95 pw_source_set("fuzztest.enabled") { 96 public = [ 97 "private/pw_fuzzer/internal/fuzztest.h", 98 "public/pw_fuzzer/fuzztest.h", 99 ] 100 public_configs = [ 101 ":public_include_path", 102 ":private_include_path", 103 ] 104 public_deps = [ 105 "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_core", 106 dir_pw_containers, 107 dir_pw_result, 108 dir_pw_status, 109 dir_pw_string, 110 ] 111 } 112} 113 114# Used by fuzzable unit tests when fuzzing is disabled. Includes stubs of the 115# Pigweed-compatible subset of FuzzTest's interface, as well as extensions to 116# support common Pigweed types. 117pw_source_set("fuzztest.disabled") { 118 public = [ 119 "private_overrides/pw_fuzzer/internal/fuzztest.h", 120 "public/pw_fuzzer/fuzztest.h", 121 "public_overrides/fuzztest/fuzztest.h", 122 ] 123 public_configs = [ 124 ":public_include_path", 125 ":overrides_include_path", 126 ] 127 public_deps = [ 128 dir_pw_containers, 129 dir_pw_result, 130 dir_pw_status, 131 dir_pw_string, 132 ] 133} 134 135pw_test("fuzztest_tests") { 136 sources = [ "domain_test.cc" ] 137 deps = [ ":fuzztest" ] 138} 139 140# This target should only be used when defining a fuzzing toolchain, e.g. to set 141# `pw_unit_test_BACKEND = "$dir_pw_fuzzer:gtest" 142# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. 143if (dir_pw_third_party_googletest == "") { 144 pw_error("gtest") { 145 message_lines = [ 146 "pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ", 147 "but dir_pw_third_party_googletest is not set.", 148 ] 149 } 150} else if (!pw_toolchain_FUZZING_ENABLED) { 151 pw_error("gtest") { 152 message_lines = [ 153 "pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ", 154 "but $current_toolchain does not support fuzzing.", 155 ] 156 } 157} else { 158 group("gtest") { 159 if (pw_toolchain_OSS_FUZZ_ENABLED) { 160 public_deps = [ "$dir_pw_unit_test:light" ] 161 } else { 162 public_deps = [ "$dir_pw_unit_test:googletest" ] 163 } 164 } 165} 166 167# This target should only be used when defining a fuzzing toolchain, e.g. to set 168# `pw_unit_test_MAIN = "$dir_pw_fuzzer:fuzztest_main" 169# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. 170if (dir_pw_third_party_fuzztest == "") { 171 pw_error("fuzztest_main") { 172 message_lines = [ 173 "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", 174 "but dir_pw_third_party_fuzztest is not set.", 175 ] 176 } 177} else if (!pw_toolchain_FUZZING_ENABLED) { 178 pw_error("fuzztest_main") { 179 message_lines = [ 180 "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", 181 "but $current_toolchain does not support fuzzing.", 182 ] 183 } 184} else { 185 group("fuzztest_main") { 186 if (pw_toolchain_OSS_FUZZ_ENABLED) { 187 deps = [ "$dir_pw_unit_test:simple_printing_main" ] 188 } else { 189 deps = [ 190 ":asan_default_options", 191 "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_gtest_main", 192 ] 193 } 194 } 195} 196 197################################################################################ 198# libFuzzer support 199# 200# Create libFuzzer-style fuzzers by using the `pw_fuzzer` template from 201# fuzzer.gni. 202 203# Add flags for linking against compiler-rt's libFuzzer. This is added 204# automatically by `pw_fuzzer`. 205config("libfuzzer_config") { 206 ldflags = [ "-fsanitize=fuzzer" ] 207} 208 209# Includes wrapper's for LLVM's libFuzzer compiler runtime library. 210pw_source_set("libfuzzer") { 211 public = [ 212 "public/pw_fuzzer/asan_interface.h", 213 "public/pw_fuzzer/fuzzed_data_provider.h", 214 ] 215 public_configs = [ ":public_include_path" ] 216 public_deps = [ dir_pw_log ] 217} 218 219# This can be linked against fuzz target functions to create unit tests for 220# them. 221pw_source_set("libfuzzer_test") { 222 testonly = pw_unit_test_TESTONLY 223 sources = [ "pw_fuzzer_disabled.cc" ] 224 public_deps = [ ":libfuzzer" ] 225 deps = [ dir_pw_unit_test ] 226} 227 228# libFuzzer-based fuzzers have a distinct dep graph. 229group("fuzzers") { 230 deps = [ "examples/libfuzzer:fuzzers" ] 231} 232 233################################################################################ 234# Local fuzzing support 235 236# Add flags for adding LLVM sanitizer coverage for fuzzing. This is added by 237# the host_clang_fuzz toolchains. 238config("instrumentation") { 239 cflags = [ "-fsanitize=fuzzer-no-link" ] 240} 241 242################################################################################ 243# OSS-Fuzz support 244# 245# OSS-Fuzz manipulates compiler and linker flags directly. See 246# google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements. 247# 248# WARNING: This is not hermetic by design. It never can be, and never will be. 249 250config("oss_fuzz_instrumentation") { 251 cflags_c = string_split(getenv("CFLAGS")) 252 cflags_cc = string_split(getenv("CXXFLAGS")) 253 254 # OSS-Fuzz sets "-stdlib=libc++", which conflicts with the "-nostdinc++" set 255 # by `pw_minimal_cpp_stdlib`. 256 if (cflags_cc + [ "-stdlib=libc++" ] - [ "-stdlib=libc++" ] != cflags_cc) { 257 cflags_cc += [ "-Wno-unused-command-line-argument" ] 258 } 259 260 # Disable UBSan vptr when the target is built with -fno-rtti. 261 if (cflags_cc + [ "-fno-rtti" ] - [ "-fno-rtti" ] != cflags_cc) { 262 cflags_cc += [ " -fno-sanitize=vptr" ] 263 } 264 cflags_cc += [ "-fcoverage-compilation-dir=" + getenv("PW_ROOT") ] 265 266 ldflags = cflags_cc + [ "-fuse-ld=lld" ] 267} 268 269config("libfuzzer_oss_fuzz_config") { 270 engine = getenv("LIB_FUZZING_ENGINE") 271 if (engine == "") { 272 engine = "-fsanitize=fuzzer" 273 } 274 ldflags = [ engine ] 275} 276