• 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    "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