Add Centipede support.
diff --git a/WORKSPACE b/WORKSPACE
index 72e82b7..f944db9 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -20,7 +20,10 @@
load("@rules_fuzzing//fuzzing:repositories.bzl", "rules_fuzzing_dependencies")
-rules_fuzzing_dependencies(jazzer = True)
+rules_fuzzing_dependencies(
+ centipede = True,
+ jazzer = True,
+)
load("@rules_fuzzing//fuzzing:init.bzl", "rules_fuzzing_init")
diff --git a/fuzzing/engines/BUILD b/fuzzing/engines/BUILD
index ab38bc4..e9dfa8b 100644
--- a/fuzzing/engines/BUILD
+++ b/fuzzing/engines/BUILD
@@ -15,6 +15,7 @@
load("//fuzzing:cc_defs.bzl", "cc_fuzzing_engine")
load("//fuzzing:java_defs.bzl", "java_fuzzing_engine")
load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
# libFuzzer specification.
##########################
@@ -51,6 +52,27 @@
visibility = ["//visibility:public"],
)
+# Centipede specification.
+##########################
+
+string_flag(
+ name = "llvm_symbolizer",
+ build_setting_default = "llvm-symbolizer",
+ visibility = ["//visibility:public"],
+)
+
+cc_fuzzing_engine(
+ name = "centipede",
+ display_name = "Centipede",
+ launcher = "centipede_launcher.sh",
+ launcher_data = {
+ "@centipede//:centipede": "CENTIPEDE_PATH",
+ ":llvm_symbolizer": "LLVM_SYMBOLIZER_PATH",
+ },
+ library = "@centipede//:fuzz_target_runner",
+ visibility = ["//visibility:public"],
+)
+
# The replay engine specification.
##################################
diff --git a/fuzzing/engines/centipede_launcher.sh b/fuzzing/engines/centipede_launcher.sh
new file mode 100644
index 0000000..8c0334d
--- /dev/null
+++ b/fuzzing/engines/centipede_launcher.sh
@@ -0,0 +1,31 @@
+# Copyright 2022 Google LLC
+#
+# 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.
+
+command_line="$(python3 -c 'import os, sys; print(os.path.realpath(sys.argv[1]))' ${CENTIPEDE_PATH})"
+# command_line+=("--alsologtostderr")
+command_line+=("--workdir=${FUZZER_OUTPUT_ROOT}")
+command_line+=("--symbolizer_path=${LLVM_SYMBOLIZER_PATH}")
+
+if [[ -n "${FUZZER_SEED_CORPUS_DIR}" ]]; then
+ >&2 echo "WARNING: Seed corpus not supported yet."
+fi
+if (( FUZZER_IS_REGRESSION )); then
+ >&2 echo "ERROR: Regression mode not supported yet."
+ exit 1
+fi
+
+command_line+=("--binary=${FUZZER_BINARY}")
+
+echo "${command_line[@]}"
+exec "${command_line[@]}" "$@"
diff --git a/fuzzing/instrum_opts.bzl b/fuzzing/instrum_opts.bzl
index b497155..f60f5a1 100644
--- a/fuzzing/instrum_opts.bzl
+++ b/fuzzing/instrum_opts.bzl
@@ -35,6 +35,7 @@
"libfuzzer": instrum_defaults.libfuzzer,
"jazzer": instrum_defaults.jazzer,
"honggfuzz": instrum_defaults.honggfuzz,
+ "centipede": instrum_defaults.centipede,
"oss-fuzz": oss_fuzz_opts,
}
diff --git a/fuzzing/private/common.bzl b/fuzzing/private/common.bzl
index 27c8107..1d52f19 100644
--- a/fuzzing/private/common.bzl
+++ b/fuzzing/private/common.bzl
@@ -34,7 +34,10 @@
script_content = script_template.format(
environment = "\n".join([
"export %s='%s'" % (var, file.short_path)
- for var, file in binary_info.engine_info.launcher_environment.items()
+ for var, file in binary_info.engine_info.launcher_environment_files.items()
+ ] + [
+ "export %s='%s'" % (var, value)
+ for var, value in binary_info.engine_info.launcher_environment_vars.items()
]),
launcher = ctx.executable._launcher.short_path,
binary_path = ctx.executable.binary.short_path,
diff --git a/fuzzing/private/engine.bzl b/fuzzing/private/engine.bzl
index 9d8656d..f4b428c 100644
--- a/fuzzing/private/engine.bzl
+++ b/fuzzing/private/engine.bzl
@@ -14,6 +14,8 @@
"""The implementation of the {cc, java}_fuzzing_engine rules."""
+load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
+
FuzzingEngineInfo = provider(
doc = """
Provider for storing the language-independent part of the specification of a fuzzing engine.
@@ -22,7 +24,8 @@
"display_name": "A string representing the human-readable name of the fuzzing engine.",
"launcher": "A file representing the shell script that launches the fuzz target.",
"launcher_runfiles": "The runfiles needed by the launcher script on the fuzzing engine side, such as helper tools and their data dependencies.",
- "launcher_environment": "A dictionary from environment variables to files used by the launcher script.",
+ "launcher_environment_files": "A dictionary from environment variables to files used by the launcher script.",
+ "launcher_environment_vars": "A dictionary from environment variables to values used by the launcher script.",
},
)
@@ -32,22 +35,31 @@
launcher_runfiles = ctx.runfiles(files = [ctx.file.launcher])
env_vars = {}
+ env_files = {}
for data_label, data_env_var in ctx.attr.launcher_data.items():
- data_files = data_label.files.to_list()
- if data_env_var:
- if data_env_var in env_vars:
- fail("Multiple data dependencies map to variable '%s'." % data_env_var)
- if len(data_files) != 1:
- fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
- env_vars[data_env_var] = data_files[0]
- launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
- launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)
+ if data_env_var in env_vars or data_env_var in env_files:
+ fail("Multiple data dependencies map to variable '%s'." % data_env_var)
+
+ # We assume data dependencies are either build setting value, or targets representing exactly one file.
+ if BuildSettingInfo in data_label:
+ if not data_env_var:
+ fail("Build setting '%s' must map to an environment variable" % data_label)
+ env_vars[data_env_var] = data_label[BuildSettingInfo].value
+ else:
+ data_files = data_label.files.to_list()
+ if data_env_var:
+ if len(data_files) != 1:
+ fail("Data dependency for variable '%s' doesn't map to exactly one file." % data_env_var)
+ env_files[data_env_var] = data_files[0]
+ launcher_runfiles = launcher_runfiles.merge(ctx.runfiles(files = data_files))
+ launcher_runfiles = launcher_runfiles.merge(data_label[DefaultInfo].default_runfiles)
return FuzzingEngineInfo(
display_name = ctx.attr.display_name,
launcher = ctx.file.launcher,
launcher_runfiles = launcher_runfiles,
- launcher_environment = env_vars,
+ launcher_environment_files = env_files,
+ launcher_environment_vars = env_vars,
)
def _cc_fuzzing_engine_impl(ctx):
diff --git a/fuzzing/private/instrum_opts.bzl b/fuzzing/private/instrum_opts.bzl
index a2f21a9..b4fffe5 100644
--- a/fuzzing/private/instrum_opts.bzl
+++ b/fuzzing/private/instrum_opts.bzl
@@ -105,6 +105,19 @@
"-fno-sanitize=fuzzer",
],
),
+ centipede = _make_opts(
+ copts = [
+ "-gline-tables-only",
+ "-fno-builtin",
+ "-fsanitize-coverage=trace-pc-guard,pc-table,trace-loads,trace-cmp",
+ ],
+ linkopts = [
+ # "-Wl,--warn-backrefs-exclude=*/centipede/*runner*.o",
+
+ # TODO(sbucur): Should be added to centipede/runner.cc linkopts.
+ "-lpthread",
+ ],
+ ),
asan = _make_opts(
copts = ["-fsanitize=address"],
linkopts = ["-fsanitize=address"],
diff --git a/fuzzing/repositories.bzl b/fuzzing/repositories.bzl
index 5ca94e6..80b9719 100644
--- a/fuzzing/repositories.bzl
+++ b/fuzzing/repositories.bzl
@@ -18,12 +18,17 @@
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//fuzzing/private/oss_fuzz:repository.bzl", "oss_fuzz_repository")
-def rules_fuzzing_dependencies(oss_fuzz = True, honggfuzz = True, jazzer = False):
+def rules_fuzzing_dependencies(
+ oss_fuzz = True,
+ honggfuzz = True,
+ centipede = False,
+ jazzer = False):
"""Instantiates the dependencies of the fuzzing rules.
Args:
oss_fuzz: Include OSS-Fuzz dependencies.
honggfuzz: Include Honggfuzz dependencies.
+ centipede: Include Centipede dependencies.
jazzer: Include Jazzer repository. Instantiating all Jazzer dependencies
additionally requires invoking jazzer_dependencies() in
@jazzer//:repositories.bzl and jazzer_init() in @jazzer//:init.bzl.
@@ -78,6 +83,25 @@
strip_prefix = "honggfuzz-e0670137531242d66c9cf8a6dee677c055a8aacb",
)
+ if centipede:
+ maybe(
+ http_archive,
+ name = "centipede",
+ sha256 = "f52b8ae44e183b8f9501e382316de28d4c5b8d333af65d76def2d1b4b0b4a9a5",
+ url = "https://github.com/google/centipede/archive/d98e302e10a21aff0bbfae96b68ff61ab8f9d1ab.zip",
+ strip_prefix = "centipede-d98e302e10a21aff0bbfae96b68ff61ab8f9d1ab",
+ )
+
+ # TODO(sbucur): This should be provided by Centipede as an initialization library.
+ boringssl_ver = "18637c5f37b87e57ebde0c40fe19c1560ec88813"
+ maybe(
+ http_archive,
+ name = "boringssl",
+ sha256 = "7514826d98f032c16531de9f4c05e7bd05e07545ca39201d1616fa7ba3deadbc",
+ strip_prefix = "boringssl-%s" % boringssl_ver,
+ url = "https://github.com/google/boringssl/archive/%s.tar.gz" % boringssl_ver,
+ )
+
if jazzer:
maybe(
http_archive,