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 )