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