Skip to content

Commit

Permalink
pw_fuzzer: Improve .bazelrc fuzzing support
Browse files Browse the repository at this point in the history
This CL drops the fuzztest.bazelrc generated by FuzzTest, and instead
adds imports two new files from //pw_fuzzer: libfuzzer.bazelrc and
fuzztest.bazelrc. These facilitate adding fuzzing support to downstream
projects' .bazelrc files as well.

Additionally, this CL fixes up the Bazel support for FuzzTest. It uses
the //pw_toolchain/host_clang:asan_feature and adds a
//pw_toolchain/host_clang:fuzztest_feature instead of using FuzzTest's
approach of setting {c|link}opts directly.

Finally, this CL extands the same support for libFuzzer, in the form of
//pw_fuzzer/libfuzzer.bazelrc.

Bug: b/347696410
Change-Id: I39ae203574a1065f76a6ca0ac0b1e08242cb380a
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/216112
Reviewed-by: Ted Pudlik <[email protected]>
Lint: Lint 🤖 <[email protected]>
Commit-Queue: Aaron Green <[email protected]>
  • Loading branch information
nopsledder authored and CQ Bot Account committed Sep 13, 2024
1 parent 82759cc commit 993b55e
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 82 deletions.
20 changes: 6 additions & 14 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,6 @@ common:asan --//pw_toolchain/host_clang:asan
# accumulate.
test:asan --test_tag_filters=-integration,-noasan

# Define the --config=asan-libfuzzer configuration.
build:asan-libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:libfuzzer
build:asan-libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan

# Include FuzzTest build configurations.
try-import %workspace%/third_party/fuzztest/fuzztest.bazelrc
build:fuzztest \
--//pw_fuzzer:fuzztest_backend=@com_google_fuzztest//fuzztest:fuzztest_core
build:fuzztest \
--@pigweed//pw_unit_test:main=@com_google_fuzztest//fuzztest:fuzztest_gtest_main

common:ubsan --//pw_toolchain/host_clang:ubsan
# TODO: https://github.com/bazelbuild/bazel/issues/7322 - We need to repeat the
# -integration because the test_tag_filters flag does not accumulate.
Expand All @@ -124,6 +110,12 @@ common:tsan --//pw_toolchain/host_clang:tsan
# -integration because the test_tag_filters flag does not accumulate.
test:tsan --test_tag_filters=-integration,-notsan

# Include libFuzzer build configurations.
import %workspace%/pw_fuzzer/libfuzzer.bazelrc

# Include FuzzTest build configurations.
import %workspace%/pw_fuzzer/fuzztest.bazelrc

# Configure workspace status command to test pw_build_info git_build_info
# https://bazel.build/docs/user-manual#workspace-status-command
# TODO: b/348046338 - Add a Windows version of this command
Expand Down
6 changes: 6 additions & 0 deletions pigweed.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@
"--aspects=@rules_rust//rust:defs.bzl%rust_clippy_aspect",
"--output_groups=clippy_checks",
"//..."
],
[
"build",
"--config=asan",
"--config=fuzztest",
"//..."
]
],
"integration": [
Expand Down
9 changes: 9 additions & 0 deletions pw_bluetooth_sapphire/fuchsia/bt_host/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ cc_library(
"host.h",
"util.h",
],
# `fuchsia_cc_binary` does not understand Pigweed's sanitizer features, e.g.
# //pw_toolchain/host_clang:asan_feature. This leads to link errors if the
# binary is linked against FuzzTest, as the latter expects the sanitizer to
# provide the SanitizerCoverage implementation. Since the binary is not
# intended to be a fuzzer, it can just be excluded from fuzzing builds.
target_compatible_with = select({
"//pw_toolchain/host_clang:fuzztest_enabled": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
deps = [
":bt_host_config",
"//pw_async_fuchsia:dispatcher",
Expand Down
32 changes: 32 additions & 0 deletions pw_fuzzer/fuzztest.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# Adapted from @com_google_fuzztest//bazel:setup_configs

build:fuzztest --@pigweed//pw_toolchain/host_clang:fuzztest
build:fuzztest --dynamic_mode=off
build:fuzztest \
--per_file_copt=+//,-fuzztest/.*,-googletest/.*,-googlemock/.*@-fsanitize-coverage=inline-8bit-counters,-fsanitize-coverage=trace-cmp
build:fuzztest \
--@pigweed//pw_fuzzer:fuzztest_backend=@com_google_fuzztest//fuzztest:fuzztest_core
build:fuzztest \
--@pigweed//pw_unit_test:backend=@pigweed//pw_unit_test:googletest
build:fuzztest \
--@pigweed//pw_unit_test:main=@com_google_fuzztest//fuzztest:fuzztest_gtest_main

# For fuzzing, we want to disregard any test strategy options and execute each
# test locally and one at a time. We also want to display as much information as
# soon as it is available, including PRNG seeds and corpus statistics.
# Both of these are achieved by streaming the test output.
test:fuzztest --test_output=streamed
24 changes: 20 additions & 4 deletions pw_fuzzer/guides/fuzztest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,30 @@ See the following:
.. tab-item:: Bazel
:sync: bazel

FuzzTest provides a build configuration that can be imported into your
``.bazelrc`` file. Add the following:
Include Abseil-C++ and GoogleTest in your ``WORKSPACE`` file. For example:

.. code-block::
http_archive(
name = "com_google_absl",
sha256 = "338420448b140f0dfd1a1ea3c3ce71b3bc172071f24f4d9a57d59b45037da440",
strip_prefix = "abseil-cpp-20240116.0",
url = "https://github.com/abseil/abseil-cpp/releases/download/20240116.0/abseil-cpp-20240116.0.tar.gz",
)
git_repository(
name = "com_google_googletest",
commit = "3b6d48e8d5c1d9b3f9f10ac030a94008bfaf032b",
remote = "https://pigweed.googlesource.com/third_party/github/google/googletest",
)
Then, import the FuzzTest build configurations in your ``.bazelrc`` file
by adding and adapting the following:

.. code-block::
# Include FuzzTest build configurations.
try-import %workspace%/third_party/fuzztest/fuzztest.bazelrc
build:fuzztest --@pigweed//targets:fuzztest_config=//pw_fuzzer:fuzztest
try-import %workspace%/path/to/pigweed/pw_fuzzer/fuzztest.bazelrc
----------------------------------------
Step 1: Write a unit test for the target
Expand Down
21 changes: 5 additions & 16 deletions pw_fuzzer/guides/libfuzzer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,10 @@ installation. In order to use it, you only need to define a suitable toolchain.
.. tab-item:: Bazel
:sync: bazel

Include ``rules_fuzzing`` and its Abseil C++ dependency in your
``WORKSPACE`` file. For example:
Include ``rules_fuzzing`` in your ``WORKSPACE`` file. For example:

.. code-block::
# Required by: rules_fuzzing.
http_archive(
name = "com_google_absl",
sha256 = "3ea49a7d97421b88a8c48a0de16c16048e17725c7ec0f1d3ea2683a2a75adc21",
strip_prefix = "abseil-cpp-20230125.0",
urls = ["https://github.com/abseil/abseil-cpp/archive/refs/tags/20230125.0.tar.gz"],
)
# Set up rules for fuzz testing.
http_archive(
name = "rules_fuzzing",
Expand All @@ -81,15 +72,13 @@ installation. In order to use it, you only need to define a suitable toolchain.
rules_fuzzing_init()
Then, define the following build configuration in your ``.bazelrc`` file:
Then, import the libFuzzer build configurations in your ``.bazelrc`` file
by adding and adapting the following:

.. code-block::
build:asan-libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:libfuzzer
build:asan-libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
build:asan-libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan
# Include FuzzTest build configurations.
try-import %workspace%/path/to/pigweed/pw_fuzzer/libfuzzer.bazelrc
------------------------------------
Step 1: Write a fuzz target function
Expand Down
25 changes: 25 additions & 0 deletions pw_fuzzer/libfuzzer.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2024 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

# TODO(b/347696410): Currently, building with `--config=libfuzzer` causes link
# errors for `pw_target_runner`.

build:libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine=@rules_fuzzing//fuzzing/engines:libfuzzer
build:libfuzzer \
--@rules_fuzzing//fuzzing:cc_engine_instrumentation=libfuzzer
build:libfuzzer --@rules_fuzzing//fuzzing:cc_engine_sanitizer=asan

test:libfuzzer --test_output=streamed

5 changes: 5 additions & 0 deletions pw_system/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ pw_cc_binary(
# testonly dependencies.
testonly = True,
srcs = ["example_user_app_init.cc"],
# TODO(b/365184562): This target does not build with asan and fuzztest.
target_compatible_with = select({
"//pw_fuzzer:use_fuzztest": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
deps = [
":pw_system",
"//pw_unit_test:rpc_service",
Expand Down
22 changes: 22 additions & 0 deletions pw_toolchain/host_clang/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,28 @@ pw_cc_feature_set(
all_of = [":rules_rust_unsupported_feature"],
)

bool_flag(
name = "fuzztest",
build_setting_default = False,
)

config_setting(
name = "fuzztest_enabled",
flag_values = {
":fuzztest": "true",
},
)

pw_cc_feature(
name = "fuzztest_feature",
enabled = select({
":fuzztest_enabled": True,
"//conditions:default": False,
}),
feature_name = "fuzztest",
flag_sets = ["@pw_toolchain//flag_sets:fuzztest"],
)

# This is a sentinel feature defined by rules_rust. It is by definition
# unsupported: rules_rust will disable this feature when linking Rust code.
pw_cc_feature(
Expand Down
14 changes: 14 additions & 0 deletions pw_toolchain_bazel/flag_sets/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,17 @@ pw_cc_flag_set(
"-DTHREAD_SANITIZER",
],
)

pw_cc_flag_set(
name = "fuzztest",
actions = [
"@pw_toolchain//actions:all_compiler_actions",
"@pw_toolchain//actions:all_link_actions",
],
flags = [
"-mcrc32",
"-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION",
"-UNDEBUG",
"-D_LIBCPP_ENABLE_ASSERTIONS=1",
],
)
5 changes: 5 additions & 0 deletions targets/rp2040/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ pw_cc_binary(
name = "system_async_example",
testonly = True,
srcs = ["system_async_example.cc"],
# TODO(b/365184562): This target does not build with asan and fuzztest.
target_compatible_with = select({
"//pw_fuzzer:use_fuzztest": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
deps = [
"//pw_channel:rp2_stdio_channel",
"//pw_libcxx",
Expand Down
48 changes: 0 additions & 48 deletions third_party/fuzztest/fuzztest.bazelrc

This file was deleted.

0 comments on commit 993b55e

Please sign in to comment.