Add support for .options files to fuzzing_binary (#148)
* Add support for .options files to fuzzing_binary
.options files can be used to supply custom options to sanitizers. While
they are rarely used for C++ fuzz targets (and thus not exposed via the
cc_fuzz_test macro for now), they are necessary to run JVM fuzz targets
correctly and will be used internally by the java_fuzz_test macro in a
follow-up commit.
* Address review comments
diff --git a/docs/BUILD b/docs/BUILD
index cb9f365..9b63c93 100644
--- a/docs/BUILD
+++ b/docs/BUILD
@@ -36,6 +36,7 @@
bzl_library(
name = "bazel_skylib",
srcs = [
+ "@bazel_skylib//lib:dicts",
"@bazel_skylib//rules:common_settings",
],
)
diff --git a/fuzzing/private/binary.bzl b/fuzzing/private/binary.bzl
index 904f106..f157137 100644
--- a/fuzzing/private/binary.bzl
+++ b/fuzzing/private/binary.bzl
@@ -14,6 +14,7 @@
"""Defines a rule for creating an instrumented fuzzing executable."""
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("//fuzzing/private:engine.bzl", "FuzzingEngineInfo")
load(
"//fuzzing/private:instrum_opts.bzl",
@@ -35,7 +36,12 @@
"binary_runfiles": "The runfiles of the fuzz test executable.",
"corpus_dir": "The directory of the corpus files used as input seeds.",
"dictionary_file": "The dictionary file to use in fuzzing runs.",
- "engine_info": "The `FuzzingEngineInfo` provider of the fuzzing engine used in the fuzz test.",
+ "engine_info": "The `FuzzingEngineInfo` provider of the fuzzing " +
+ "engine used in the fuzz test.",
+ "options_file": "A file containing fuzzing engine and sanitizer " +
+ "options to use during execution. The file loosely " +
+ "follows the INI format and currently only applies " +
+ "to OSS-Fuzz.",
},
)
@@ -110,6 +116,8 @@
other_runfiles.append(ctx.file.corpus)
if ctx.file.dictionary:
other_runfiles.append(ctx.file.dictionary)
+ if ctx.file.options:
+ other_runfiles.append(ctx.file.options)
return [
DefaultInfo(
executable = output_file,
@@ -121,9 +129,32 @@
corpus_dir = ctx.file.corpus,
dictionary_file = ctx.file.dictionary,
engine_info = ctx.attr.engine[FuzzingEngineInfo],
+ options_file = ctx.file.options,
),
]
+_common_fuzzing_binary_attrs = {
+ "engine": attr.label(
+ doc = "The specification of the fuzzing engine used in the binary.",
+ providers = [FuzzingEngineInfo],
+ mandatory = True,
+ ),
+ "corpus": attr.label(
+ doc = "A directory of corpus files used as input seeds.",
+ allow_single_file = True,
+ ),
+ "dictionary": attr.label(
+ doc = "A dictionary file to use in fuzzing runs.",
+ allow_single_file = True,
+ ),
+ "options": attr.label(
+ doc = "A file containing fuzzing engine and sanitizer options to use " +
+ "use during execution. The file loosely follows the INI " +
+ "format and currently only applies to OSS-Fuzz.",
+ allow_single_file = True,
+ ),
+}
+
fuzzing_binary = rule(
implementation = _fuzzing_binary_impl,
doc = """
@@ -138,33 +169,20 @@
* `@rules_fuzzing//fuzzing:cc_engine_sanitizer`
* `@rules_fuzzing//fuzzing:cc_fuzzing_build_mode`
""",
- attrs = {
+ attrs = dicts.add(_common_fuzzing_binary_attrs, {
"binary": attr.label(
executable = True,
doc = "The fuzz test executable to instrument.",
cfg = fuzzing_binary_transition,
mandatory = True,
),
- "engine": attr.label(
- doc = "The specification of the fuzzing engine used in the binary.",
- providers = [FuzzingEngineInfo],
- mandatory = True,
- ),
- "corpus": attr.label(
- doc = "A directory of corpus files used as input seeds.",
- allow_single_file = True,
- ),
- "dictionary": attr.label(
- doc = "A dictionary file to use in fuzzing runs.",
- allow_single_file = True,
- ),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_instrument_binary": attr.bool(
default = True,
),
- },
+ }),
executable = True,
provides = [FuzzingBinaryInfo],
)
@@ -178,30 +196,17 @@
be incorporated in the target configuration (e.g., on the command line or the
.bazelrc configuration file).
""",
- attrs = {
+ attrs = dicts.add(_common_fuzzing_binary_attrs, {
"binary": attr.label(
executable = True,
doc = "The instrumented fuzz test executable.",
cfg = "target",
mandatory = True,
),
- "engine": attr.label(
- doc = "The specification of the fuzzing engine used in the binary.",
- providers = [FuzzingEngineInfo],
- mandatory = True,
- ),
- "corpus": attr.label(
- doc = "A directory of corpus files used as input seeds.",
- allow_single_file = True,
- ),
- "dictionary": attr.label(
- doc = "A dictionary file to use in fuzzing runs.",
- allow_single_file = True,
- ),
"_instrument_binary": attr.bool(
default = False,
),
- },
+ }),
executable = True,
provides = [FuzzingBinaryInfo],
)
diff --git a/fuzzing/private/oss_fuzz/package.bzl b/fuzzing/private/oss_fuzz/package.bzl
index 6184303..16e3749 100644
--- a/fuzzing/private/oss_fuzz/package.bzl
+++ b/fuzzing/private/oss_fuzz/package.bzl
@@ -43,12 +43,16 @@
if [[ -n "{dictionary_path}" ]]; then
ln -s "$(pwd)/{dictionary_path}" "$STAGING_DIR/{base_name}.dict"
fi
+ if [[ -n "{options_path}" ]]; then
+ ln -s "$(pwd)/{options_path}" "$STAGING_DIR/{base_name}.options"
+ fi
tar -chf "{output}" -C "$STAGING_DIR" .
""".format(
base_name = ctx.attr.base_name,
binary_path = binary_info.binary_file.path,
corpus_dir = binary_info.corpus_dir.path if binary_info.corpus_dir else "",
dictionary_path = binary_info.dictionary_file.path if binary_info.dictionary_file else "",
+ options_path = binary_info.options_file.path if binary_info.options_file else "",
output = output_archive.path,
),
)