diff options
Diffstat (limited to 'pw_fuzzer/BUILD.gn')
-rw-r--r-- | pw_fuzzer/BUILD.gn | 276 |
1 files changed, 224 insertions, 52 deletions
diff --git a/pw_fuzzer/BUILD.gn b/pw_fuzzer/BUILD.gn index 142b7617d..5a1e49f97 100644 --- a/pw_fuzzer/BUILD.gn +++ b/pw_fuzzer/BUILD.gn @@ -14,89 +14,261 @@ import("//build_overrides/pigweed.gni") +import("$dir_pw_build/error.gni") import("$dir_pw_build/target_types.gni") import("$dir_pw_docgen/docs.gni") -import("$dir_pw_fuzzer/fuzzer.gni") +import("$dir_pw_third_party/fuzztest/fuzztest.gni") +import("$dir_pw_unit_test/test.gni") config("public_include_path") { include_dirs = [ "public" ] visibility = [ ":*" ] } -# Add flags for adding LLVM sanitizer coverage for fuzzing. This is added by -# the host_clang_fuzz toolchains. -config("instrumentation") { - if (pw_toolchain_OSS_FUZZ_ENABLED) { - # OSS-Fuzz manipulates compiler flags directly. See - # google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements. - cflags_c = string_split(getenv("CFLAGS")) - cflags_cc = string_split(getenv("CXXFLAGS")) - - # OSS-Fuzz sets "-stdlib=libc++", which conflicts with the "-nostdinc++" set - # by `pw_minimal_cpp_stdlib`. - cflags_cc += [ "-Wno-unused-command-line-argument" ] +config("private_include_path") { + include_dirs = [ "private" ] + visibility = [ ":*" ] +} + +config("overrides_include_path") { + include_dirs = [ + "public_overrides", + "private_overrides", + ] + visibility = [ ":*" ] +} + +# See https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode +config("fuzzing_build_mode_unsafe_for_production") { + defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ] +} + +pw_doc_group("docs") { + sources = [ + "concepts.rst", + "docs.rst", + "guides/fuzztest.rst", + "guides/index.rst", + "guides/libfuzzer.rst", + "guides/reproducing_oss_fuzz_bugs.rst", + ] + inputs = [ + "doc_resources/pw_fuzzer_coverage_guided.png", + "examples/fuzztest/BUILD.gn", + "examples/fuzztest/BUILD.bazel", + "examples/fuzztest/CMakeLists.txt", + "examples/fuzztest/metrics.h", + "examples/fuzztest/metrics_unittest.cc", + "examples/fuzztest/metrics_fuzztest.cc", + ] +} + +pw_test_group("tests") { + group_deps = [ + ":fuzztest_tests", + "examples/fuzztest:tests", + "examples/libfuzzer:tests", + ] +} + +################################################################################ +# FuzzTest support +# +# Create FuzzTest-style fuzzers by adding a dep on dir_pw_fuzzer:fuzztest + +group("fuzztest") { + if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { + public_deps = [ ":fuzztest.enabled" ] } else { - cflags = [ "-fsanitize=fuzzer-no-link" ] + public_deps = [ ":fuzztest.disabled" ] } } -# Add flags for linking against compiler-rt's libFuzzer. This is added -# automatically by `pw_fuzzer`. -config("engine") { - if (pw_toolchain_OSS_FUZZ_ENABLED) { - # OSS-Fuzz manipulates linker flags directly. See - # google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements. - ldflags = string_split(getenv("LDFLAGS")) + [ getenv("LIB_FUZZING_ENGINE") ] - } else { - ldflags = [ "-fsanitize=fuzzer" ] +# Used by fuzzable unit tests when fuzzing is enabled. Includes headers and deps +# that provide a Pigweed-compatible subset of FuzzTest, as well as extensions to +# support common Pigweed types. +if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) { + pw_source_set("fuzztest.enabled") { + public = [ + "private/pw_fuzzer/internal/fuzztest.h", + "public/pw_fuzzer/fuzztest.h", + ] + public_configs = [ + ":public_include_path", + ":private_include_path", + "$dir_pw_third_party/abseil-cpp/configs:disabled_warnings", + "$dir_pw_third_party/abseil-cpp/configs:public_include_path", + "$dir_pw_third_party/fuzztest/configs:disabled_warnings", + "$dir_pw_third_party/fuzztest/configs:public_include_path", + "$dir_pw_third_party/re2/configs:disabled_warnings", + "$dir_pw_third_party/re2/configs:public_include_path", + ] + public_deps = [ + "$dir_pw_third_party/fuzztest/fuzztest", + dir_pw_containers, + dir_pw_result, + dir_pw_status, + dir_pw_string, + ] } } -pw_source_set("pw_fuzzer") { - public_configs = [ ":public_include_path" ] +# Used by fuzzable unit tests when fuzzing is disabled. Includes stubs of the +# Pigweed-compatible subset of FuzzTest's interface, as well as extensions to +# support common Pigweed types. +pw_source_set("fuzztest.disabled") { public = [ - "public/pw_fuzzer/asan_interface.h", - "public/pw_fuzzer/fuzzed_data_provider.h", + "private_overrides/pw_fuzzer/internal/fuzztest.h", + "public/pw_fuzzer/fuzztest.h", + "public_overrides/fuzztest/fuzztest.h", + ] + public_configs = [ + ":public_include_path", + ":overrides_include_path", + ] + public_deps = [ + dir_pw_containers, + dir_pw_result, + dir_pw_status, + dir_pw_string, ] - public_deps = [ "$dir_pw_log" ] } -pw_source_set("run_as_unit_test") { - configs = [ ":public_include_path" ] - sources = [ "pw_fuzzer_disabled.cc" ] - deps = [ - dir_pw_log, - dir_pw_unit_test, - ] +pw_test("fuzztest_tests") { + sources = [ "domain_test.cc" ] + deps = [ ":fuzztest" ] } -# See https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode -config("fuzzing_build_mode_unsafe_for_production") { - defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ] +# This target should only be used when defining a fuzzing toolchain, e.g. to set +# `pw_unit_test_GOOGLETEST_BACKEND = "$dir_pw_fuzzer:gtest" +# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. +if (dir_pw_third_party_googletest == "") { + pw_error("gtest") { + message_lines = [ + "pw_unit_test_GOOGLETEST_BACKEND is set to dir_pw_fuzzer:gtest, ", + "but dir_pw_third_party_googletest is not set.", + ] + } +} else if (!pw_toolchain_FUZZING_ENABLED) { + pw_error("gtest") { + message_lines = [ + "pw_unit_test_GOOGLETEST_BACKEND is set to dir_pw_fuzzer:gtest, ", + "but $current_toolchain does not support fuzzing.", + ] + } +} else { + group("gtest") { + if (pw_toolchain_OSS_FUZZ_ENABLED) { + public_deps = [ "$dir_pw_unit_test:light" ] + } else { + public_deps = [ "$dir_pw_third_party/googletest" ] + } + } } -config("fuzzing_verbose_logging") { - defines = [ "FUZZING_VERBOSE_LOGGING" ] +# This target should only be used when defining a fuzzing toolchain, e.g. to set +# `pw_unit_test_MAIN = "$dir_pw_fuzzer:fuzztest_main" +# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz. +if (dir_pw_third_party_fuzztest == "") { + pw_error("fuzztest_main") { + message_lines = [ + "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", + "but dir_pw_third_party_fuzztest is not set.", + ] + } +} else if (!pw_toolchain_FUZZING_ENABLED) { + pw_error("fuzztest_main") { + message_lines = [ + "pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ", + "but $current_toolchain does not support fuzzing.", + ] + } +} else { + group("fuzztest_main") { + if (pw_toolchain_OSS_FUZZ_ENABLED) { + deps = [ "$dir_pw_unit_test:simple_printing_main" ] + } else { + deps = [ "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_gtest_main" ] + } + } } -pw_doc_group("docs") { - inputs = [ "doc_resources/pw_fuzzer_coverage_guided.png" ] - sources = [ "docs.rst" ] +################################################################################ +# libFuzzer support +# +# Create libFuzzer-style fuzzers by using the `pw_fuzzer` template from +# fuzzer.gni. + +# Add flags for linking against compiler-rt's libFuzzer. This is added +# automatically by `pw_fuzzer`. +config("libfuzzer_config") { + ldflags = [ "-fsanitize=fuzzer" ] } -# Sample fuzzer -pw_fuzzer("toy_fuzzer") { - sources = [ "examples/toy_fuzzer.cc" ] - deps = [ - ":pw_fuzzer", - dir_pw_status, +# Includes wrapper's for LLVM's libFuzzer compiler runtime library. +pw_source_set("libfuzzer") { + public = [ + "public/pw_fuzzer/asan_interface.h", + "public/pw_fuzzer/fuzzed_data_provider.h", ] + public_configs = [ ":public_include_path" ] + public_deps = [ dir_pw_log ] } -pw_test_group("tests") { - tests = [ ":toy_fuzzer_test" ] +# This can be linked against fuzz target functions to create unit tests for +# them. +pw_source_set("libfuzzer_test") { + testonly = pw_unit_test_TESTONLY + sources = [ "pw_fuzzer_disabled.cc" ] + public_deps = [ ":libfuzzer" ] + deps = [ dir_pw_unit_test ] } +# libFuzzer-based fuzzers have a distinct dep graph. group("fuzzers") { - deps = [ ":toy_fuzzer" ] + deps = [ "examples/libfuzzer:fuzzers" ] +} + +################################################################################ +# Local fuzzing support + +# Add flags for adding LLVM sanitizer coverage for fuzzing. This is added by +# the host_clang_fuzz toolchains. +config("instrumentation") { + cflags = [ "-fsanitize=fuzzer-no-link" ] +} + +################################################################################ +# OSS-Fuzz support +# +# OSS-Fuzz manipulates compiler and linker flags directly. See +# google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements. +# +# WARNING: This is not hermetic by design. It never can be, and never will be. + +config("oss_fuzz_instrumentation") { + cflags_c = string_split(getenv("CFLAGS")) + cflags_cc = string_split(getenv("CXXFLAGS")) + + # OSS-Fuzz sets "-stdlib=libc++", which conflicts with the "-nostdinc++" set + # by `pw_minimal_cpp_stdlib`. + if (cflags_cc + [ "-stdlib=libc++" ] - [ "-stdlib=libc++" ] != cflags_cc) { + cflags_cc += [ "-Wno-unused-command-line-argument" ] + } + + # Disable UBSan vptr when the target is built with -fno-rtti. + if (cflags_cc + [ "-fno-rtti" ] - [ "-fno-rtti" ] != cflags_cc) { + cflags_cc += [ " -fno-sanitize=vptr" ] + } + cflags_cc += [ "-fcoverage-compilation-dir=" + getenv("PW_ROOT") ] + + ldflags = cflags_cc + [ "-fuse-ld=lld" ] +} + +config("libfuzzer_oss_fuzz_config") { + engine = getenv("LIB_FUZZING_ENGINE") + if (engine == "") { + engine = "-fsanitize=fuzzer" + } + ldflags = [ engine ] } |