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