xref: /aosp_15_r20/external/pigweed/pw_fuzzer/BUILD.gn (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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