1*33edd672SMark# Copyright 2021 Code Intelligence GmbH 2*33edd672SMark# 3*33edd672SMark# Licensed under the Apache License, Version 2.0 (the "License"); 4*33edd672SMark# you may not use this file except in compliance with the License. 5*33edd672SMark# You may obtain a copy of the License at 6*33edd672SMark# 7*33edd672SMark# http://www.apache.org/licenses/LICENSE-2.0 8*33edd672SMark# 9*33edd672SMark# Unless required by applicable law or agreed to in writing, software 10*33edd672SMark# distributed under the License is distributed on an "AS IS" BASIS, 11*33edd672SMark# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*33edd672SMark# See the License for the specific language governing permissions and 13*33edd672SMark# limitations under the License. 14*33edd672SMark 15*33edd672SMarkdef java_fuzz_target_test( 16*33edd672SMark name, 17*33edd672SMark target_class = None, 18*33edd672SMark target_method = None, 19*33edd672SMark deps = [], 20*33edd672SMark runtime_deps = [], 21*33edd672SMark hook_jar = None, 22*33edd672SMark data = [], 23*33edd672SMark launcher_variant = "java", 24*33edd672SMark tags = [], 25*33edd672SMark fuzzer_args = [], 26*33edd672SMark srcs = [], 27*33edd672SMark size = None, 28*33edd672SMark timeout = None, 29*33edd672SMark env = None, 30*33edd672SMark env_inherit = None, 31*33edd672SMark verify_crash_input = True, 32*33edd672SMark verify_crash_reproducer = True, 33*33edd672SMark # Superset of the findings the fuzzer is expected to find. Since fuzzing runs are not 34*33edd672SMark # deterministic across OSes, pinpointing the exact set of findings is difficult. 35*33edd672SMark allowed_findings = [], 36*33edd672SMark # By default, expect a crash iff allowed_findings isn't empty. 37*33edd672SMark expect_crash = None, 38*33edd672SMark **kwargs): 39*33edd672SMark if target_class: 40*33edd672SMark fuzzer_args = fuzzer_args + ["--target_class=" + target_class] 41*33edd672SMark if target_method: 42*33edd672SMark fuzzer_args = fuzzer_args + ["--target_method=" + target_method] 43*33edd672SMark if expect_crash == None: 44*33edd672SMark expect_crash = len(allowed_findings) != 0 45*33edd672SMark 46*33edd672SMark target_name = name + "_target" 47*33edd672SMark target_deploy_jar = target_name + "_deploy.jar" 48*33edd672SMark 49*33edd672SMark # Deps can only be specified on java_binary targets with sources, which 50*33edd672SMark # excludes e.g. Kotlin libraries wrapped into java_binary via runtime_deps. 51*33edd672SMark deps = deps + ["//deploy:jazzer-api"] if srcs else [] 52*33edd672SMark native.java_binary( 53*33edd672SMark name = target_name, 54*33edd672SMark srcs = srcs, 55*33edd672SMark create_executable = False, 56*33edd672SMark visibility = ["//visibility:private"], 57*33edd672SMark deps = deps, 58*33edd672SMark runtime_deps = runtime_deps, 59*33edd672SMark testonly = True, 60*33edd672SMark tags = tags, 61*33edd672SMark **kwargs 62*33edd672SMark ) 63*33edd672SMark 64*33edd672SMark if launcher_variant == "java": 65*33edd672SMark # With the Java driver, we expect fuzz targets to depend on Jazzer 66*33edd672SMark # rather than have the launcher start a JVM with Jazzer on the class 67*33edd672SMark # path. 68*33edd672SMark native.java_import( 69*33edd672SMark name = target_name + "_import", 70*33edd672SMark jars = [target_deploy_jar], 71*33edd672SMark testonly = True, 72*33edd672SMark tags = tags, 73*33edd672SMark ) 74*33edd672SMark target_with_driver_name = target_name + "_driver" 75*33edd672SMark native.java_binary( 76*33edd672SMark name = target_with_driver_name, 77*33edd672SMark runtime_deps = [ 78*33edd672SMark target_name + "_import", 79*33edd672SMark "//src/main/java/com/code_intelligence/jazzer:jazzer_import", 80*33edd672SMark ], 81*33edd672SMark main_class = "com.code_intelligence.jazzer.Jazzer", 82*33edd672SMark testonly = True, 83*33edd672SMark tags = tags, 84*33edd672SMark ) 85*33edd672SMark 86*33edd672SMark if launcher_variant == "native": 87*33edd672SMark driver = "//launcher:jazzer" 88*33edd672SMark elif launcher_variant == "java": 89*33edd672SMark driver = target_with_driver_name 90*33edd672SMark else: 91*33edd672SMark fail("Invalid launcher variant: " + launcher_variant) 92*33edd672SMark 93*33edd672SMark native.java_test( 94*33edd672SMark name = name, 95*33edd672SMark runtime_deps = [ 96*33edd672SMark "//bazel/tools/java:fuzz_target_test_wrapper", 97*33edd672SMark ], 98*33edd672SMark jvm_flags = [ 99*33edd672SMark # Use the same memory settings for reproducers as those suggested by Jazzer when 100*33edd672SMark # encountering an OutOfMemoryError. 101*33edd672SMark "-Xmx1620m", 102*33edd672SMark # Ensure that reproducers can be compiled even if they contain UTF-8 characters. 103*33edd672SMark "-Dfile.encoding=UTF-8", 104*33edd672SMark ], 105*33edd672SMark size = size or "enormous", 106*33edd672SMark timeout = timeout or "moderate", 107*33edd672SMark # args are shell tokenized and thus quotes are required in the case where arguments 108*33edd672SMark # are empty. 109*33edd672SMark args = [ 110*33edd672SMark "$(rlocationpath %s)" % driver, 111*33edd672SMark "$(rlocationpath //deploy:jazzer-api)", 112*33edd672SMark "$(rlocationpath %s)" % target_deploy_jar, 113*33edd672SMark "$(rlocationpath %s)" % hook_jar if hook_jar else "''", 114*33edd672SMark str(verify_crash_input), 115*33edd672SMark str(verify_crash_reproducer), 116*33edd672SMark str(expect_crash), 117*33edd672SMark str(launcher_variant == "java"), 118*33edd672SMark "'" + ",".join(allowed_findings) + "'", 119*33edd672SMark ] + fuzzer_args, 120*33edd672SMark data = [ 121*33edd672SMark target_deploy_jar, 122*33edd672SMark "//deploy:jazzer-api", 123*33edd672SMark driver, 124*33edd672SMark ] + data + ([hook_jar] if hook_jar else []), 125*33edd672SMark env = env, 126*33edd672SMark env_inherit = env_inherit, 127*33edd672SMark main_class = "com.code_intelligence.jazzer.tools.FuzzTargetTestWrapper", 128*33edd672SMark use_testrunner = False, 129*33edd672SMark tags = tags, 130*33edd672SMark ) 131