github.com/prysmaticlabs/prysm@v1.4.4/tools/go/fuzz.bzl (about)

     1  load("@io_bazel_rules_go//go:def.bzl", "go_context", "go_rule")
     2  load(
     3      "@io_bazel_rules_go//go/private:providers.bzl",
     4      "GoLibrary",
     5      "INFERRED_PATH",
     6  )
     7  load(
     8      "@io_bazel_rules_go//go/private:mode.bzl",
     9      "LINKMODE_C_ARCHIVE",
    10  )
    11  load(
    12      "@io_bazel_rules_go//go:def.bzl",
    13      "go_binary",
    14      "go_library",
    15  )
    16  
    17  main_tpl = """
    18  // Generated file. DO NOT EDIT.
    19  
    20  package main
    21  import (
    22      "unsafe"
    23      target "%s"
    24  )
    25  // #include <stdint.h>
    26  import "C"
    27  //export LLVMFuzzerTestOneInput
    28  func LLVMFuzzerTestOneInput(data *C.char, size C.size_t) C.int {
    29  	s := make([]byte, size)
    30  	copy(s, (*[1 << 30]byte)(unsafe.Pointer(data))[:size:size])
    31  	target.%s(s)
    32  	return 0
    33  }
    34  func main() {
    35  }
    36  """
    37  
    38  def _gen_fuzz_main_impl(ctx):
    39      if ctx.var.get("gotags") != "libfuzzer":
    40          fail("gotags must be set to libfuzzer. Use --config=fuzz or --config=fuzzit.")
    41      if "libfuzzer" not in ctx.var.get("gc_goopts"):
    42          fail("gc_goopts must be set to -d=libfuzzer. Use --config=fuzz or --config=fuzzit.")
    43  
    44      pkg = ctx.attr.target_pkg
    45      func = ctx.attr.func
    46  
    47      output_file_name = ctx.label.name + "_main.fuzz.go"
    48      output_file = ctx.actions.declare_file(output_file_name)
    49      ctx.actions.write(output_file, main_tpl % (pkg, func))
    50      return [DefaultInfo(files = depset([output_file]))]
    51  
    52  gen_fuzz_main = rule(
    53      implementation = _gen_fuzz_main_impl,
    54      attrs = {
    55          "target_pkg": attr.string(mandatory = True),
    56          "func": attr.string(mandatory = True),
    57      },
    58  )
    59  
    60  fuzzer_options_tpl = """[libfuzzer]
    61  max_len=%d
    62  """
    63  
    64  def _generate_libfuzzer_config(ctx):
    65      output_file_name = ctx.label.name + ".options"
    66      output = fuzzer_options_tpl % (
    67          ctx.attr.max_len,
    68      )
    69      output_file = ctx.actions.declare_file(output_file_name)
    70      ctx.actions.write(output_file, output)
    71      return [DefaultInfo(files = depset([output_file]))]
    72  
    73  gen_libfuzzer_config = rule(
    74      implementation = _generate_libfuzzer_config,
    75      attrs = {
    76          "max_len": attr.int(default = 0),
    77      },
    78  )
    79  
    80  def _upload_to_gcp_impl(ctx):
    81      return [
    82          DefaultInfo(),
    83      ]
    84  
    85  upload_to_gcp = rule(
    86      implementation = _upload_to_gcp_impl,
    87      attrs = {
    88          "gcp_bucket": attr.string(mandatory = True),
    89          "libfuzzer_bundle": attr.label(mandatory = True),
    90          "afl_bundle": attr.label(mandatory = True),
    91      },
    92  )
    93  
    94  def go_fuzz_test(
    95          name,
    96          corpus,
    97          corpus_path,
    98          importpath,
    99          func = "Fuzz",
   100          repository = "",
   101          max_len = 0,
   102          gcp_bucket = "gs://builds.prysmaticlabs.appspot.com",
   103          size = "medium",
   104          tags = [],
   105          **kwargs):
   106      go_library(
   107          name = name + "_lib_with_fuzzer",
   108          tags = ["manual"] + tags,
   109          visibility = ["//visibility:private"],
   110          testonly = 1,
   111          importpath = importpath,
   112          gc_goopts = ["-d=libfuzzer"],
   113          **kwargs
   114      )
   115      gen_fuzz_main(
   116          name = name + "_libfuzz_main",
   117          target_pkg = importpath,
   118          func = func,
   119          tags = ["manual"] + tags,
   120          testonly = 1,
   121          visibility = ["//visibility:private"],
   122      )
   123      gen_libfuzzer_config(
   124          name = name + "_options",
   125          max_len = max_len,
   126      )
   127      go_binary(
   128          name = name + "_binary",
   129          srcs = [name + "_libfuzz_main"],
   130          deps = [name + "_lib_with_fuzzer"],
   131          linkmode = LINKMODE_C_ARCHIVE,
   132          cgo = True,
   133          tags = ["manual"] + tags,
   134          visibility = ["//visibility:private"],
   135          gc_goopts = ["-d=libfuzzer"],
   136          testonly = 1,
   137      )
   138      native.genrule(
   139          name = name,
   140          outs = [name + ".a"],
   141          srcs = [":" + name + "_binary"],
   142          cmd = "cp $< $@",
   143          visibility = kwargs.get("visibility"),
   144          tags = ["manual"] + tags,
   145          testonly = 1,
   146      )
   147  
   148      if not (corpus.startswith("//") or corpus.startswith(":") or corpus.startswith("@")):
   149          corpus_name = name + "_corpus"
   150          corpus = native.glob([corpus + "/**"])
   151          native.filegroup(
   152              name = corpus_name,
   153              srcs = corpus,
   154          )
   155      else:
   156          corpus_name = corpus
   157  
   158      additional_args = []
   159      if max_len > 0:
   160          additional_args += ["-max_len=%s" % max_len]
   161  
   162      native.cc_test(
   163          name = name + "_with_afl",
   164          linkopts = [
   165              "-fsanitize=address",
   166              "-fsanitize-coverage=trace-pc-guard",
   167          ],
   168          linkstatic = 1,
   169          testonly = 1,
   170          srcs = [":" + name],
   171          deps = [
   172              "@herumi_bls_eth_go_binary//:lib",
   173              "//third_party/afl:fuzzing_engine",
   174          ],
   175          tags = ["manual", "fuzzer"] + tags,
   176      )
   177  
   178      native.genrule(
   179          name = name + "_afl_bundle",
   180          outs = [name + "_afl_bundle.zip"],
   181          srcs = [
   182              "//third_party/afl:libs",
   183              ":" + name + "_with_afl",
   184          ],
   185          cmd = "cp $(location :" + name + "_with_afl) fuzzer; $(location @bazel_tools//tools/zip:zipper) cf $@ $(locations //third_party/afl:libs) fuzzer",
   186          tools = [
   187              "@bazel_tools//tools/zip:zipper",
   188          ],
   189          testonly = 1,
   190          tags = ["manual"] + tags,
   191      )
   192  
   193      native.cc_test(
   194          name = name + "_with_libfuzzer",
   195          linkopts = ["-fsanitize=fuzzer,address"],
   196          copts = ["-fsanitize=fuzzer,address"],
   197          linkstatic = 1,
   198          testonly = 1,
   199          srcs = [":" + name],
   200          deps = ["@herumi_bls_eth_go_binary//:lib"],
   201          tags = ["manual", "fuzzer"] + tags,
   202          args = [
   203              corpus_path,
   204              "-print_final_stats=1",
   205              "-use_value_profile=1",
   206              "-max_total_time=3540",  # One minute early of 3600.
   207          ] + additional_args,
   208          data = [corpus_name],
   209          timeout = "eternal",
   210      )
   211  
   212      native.genrule(
   213          name = name + "_libfuzzer_bundle",
   214          outs = [name + "_libfuzzer_bundle.zip"],
   215          srcs = [
   216              ":" + name + "_with_libfuzzer",
   217              ":" + name + "_options",
   218          ],
   219          cmd = "cp $(location :" + name + "_with_libfuzzer) fuzzer; " +
   220                "cp $(location :" + name + "_options) fuzzer.options; " +
   221                "$(location @bazel_tools//tools/zip:zipper) cf $@ fuzzer fuzzer.options",
   222          tools = ["@bazel_tools//tools/zip:zipper"],
   223          testonly = 1,
   224          tags = ["manual"] + tags,
   225      )
   226  
   227      upload_to_gcp(
   228          name = name + "_uploader",
   229          gcp_bucket = gcp_bucket,
   230          afl_bundle = ":" + name + "_afl_bundle",
   231          libfuzzer_bundle = ":" + name + "_libfuzzer_bundle",
   232          tags = ["manual"] + tags,
   233      )