| # Copyright 2023 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("//testing/libfuzzer/fuzzer_test.gni") |
| import("//third_party/protobuf/proto_library.gni") |
| |
| # This template allows creation of a fuzzer which has access to all the |
| # functionality of a browser_test, including a full GUI instance of Chromium. |
| # See in_process_fuzzer.h. |
| # |
| # It accepts all the same arguments as //testing/libfuzzer/fuzzer_test.gni's |
| # fuzzer_test template. |
| template("in_process_fuzzer") { |
| if (fuzzing_engine_supports_custom_main) { |
| fuzzer_test(target_name) { |
| deps = [ "//chrome/test/fuzzing:in_process_fuzzer_runner" ] |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "deps", |
| "exclude_main", |
| "asan_options", |
| ]) |
| |
| # As these are full browser tests, we have crashpad running, |
| # and we can't intercept signals that crashpad needs. |
| sanitizer_options = [ |
| "allow_user_segv_handler=1", |
| "handle_sigtrap=1", |
| "handle_abort=1", |
| "handle_segv=1", |
| "handle_sigbus=1", |
| "handle_sigfpe=1", |
| "handle_sigill=1", |
| "handle_sigtrap=1", |
| ] |
| |
| asan_options = [ |
| # Browser tests store arbitrary data in globals; leak |
| # detection will come up with lots of false positives. |
| "detect_leaks=0", |
| ] |
| |
| asan_options += sanitizer_options |
| |
| ubsan_options = sanitizer_options |
| |
| msan_options = sanitizer_options |
| |
| # Again, these are full browser tests, so it needs a fairly high memory |
| # limit so that it runs correctly. |
| libfuzzer_options = [ |
| "rss_limit_mb=8192", |
| |
| # We can't allow libfuzzer to fork because these fuzzers may have |
| # pre-existing threads. See crbug.com/325928325 |
| "fork=0", |
| ] |
| |
| centipede_options = [ |
| # Provide plenty of capacity for test cases to flow between centipede |
| # and the fuzz target. |
| "shmem_size_mb=4096", |
| |
| # Browser tests are big |
| "address_space_limit_mb=0", |
| |
| # For testing. Those fuzzers are extremely slow on ClusterFuzz, and |
| # using this option doesn't help. |
| "fork_server=0", |
| |
| "rss_limit_mb=8192", |
| |
| # This value is the one used by CF for Centipede fuzzers. |
| # Default computed timeout per batch is ridiculously low (1127, which |
| # means ~1.1 sec per input average) for those fuzzers. |
| "timeout_per_batch=8400", |
| ] |
| |
| if (defined(invoker.asan_options)) { |
| asan_options += invoker.asan_options |
| } |
| if (defined(invoker.libfuzzer_options)) { |
| libfuzzer_options += invoker.libfuzzer_options |
| } |
| if (defined(invoker.centipede_options)) { |
| centipede_options += invoker.centipede_options |
| } |
| exclude_main = true |
| } |
| } else { |
| # noop if the fuzzer harness always provides its own main |
| not_needed(invoker, "*") |
| |
| group(target_name) { |
| } |
| } |
| } |
| |
| # This template is a proto-based version of the in_process_fuzzer template. |
| # |
| # This rule copies the proto-relevant bits from the mojolpm_fuzzer_test |
| # template (//mojo/public/tools/fuzzers/mojolpm.gni) |
| # |
| # Parameters: |
| # sources |
| # List of source .cc files to compile. |
| # |
| # deps |
| # List of dependencies to compile this target. |
| # |
| # proto_source |
| # Single source .proto file defining the structure of a testcase. |
| # |
| # proto_deps |
| # List of additional dependencies for compiling proto_source. |
| # |
| # testcase_proto_kind (optional, required if seed_corpus_sources provided) |
| # Name of proto message type representing a testcase. |
| # |
| # seed_corpus_sources (optional) |
| # List of source .textproto files used to build a seed corpus. |
| |
| template("in_process_proto_fuzzer") { |
| if (fuzzing_engine_supports_custom_main) { |
| assert(defined(invoker.sources) && defined(invoker.proto_source), |
| "\"sources\" and \"proto_source\" must be defined for $target_name") |
| |
| assert( |
| !defined(invoker.seed_corpus_sources) || |
| defined(invoker.testcase_proto_kind), |
| "\"testcase_proto_kind\" must be defined for $target_name since \"seed_corpus_sources\" is defined.") |
| |
| proto_target_name = "${target_name}_proto" |
| |
| proto_library(proto_target_name) { |
| # Work relative to src (//) instead of (by default) the BUILD file. |
| proto_in_dir = "//" |
| |
| sources = [ invoker.proto_source ] |
| generate_python = false |
| |
| proto_deps = [] |
| |
| import_dirs = [ root_gen_dir ] |
| |
| link_deps = [] |
| |
| if (defined(invoker.proto_deps)) { |
| proto_deps += invoker.proto_deps |
| link_deps += invoker.proto_deps |
| } |
| |
| testonly = true |
| } |
| |
| if (defined(invoker.seed_corpus_sources)) { |
| protoc_convert_target_name = "${target_name}_protoc_convert" |
| seed_corpus_path = "${target_gen_dir}/${target_name}_seed_corpus" |
| |
| protoc_convert(protoc_convert_target_name) { |
| sources = invoker.seed_corpus_sources |
| |
| inputs = [ invoker.proto_source ] |
| |
| output_pattern = "${seed_corpus_path}/{{source_name_part}}.binarypb" |
| |
| args = [ |
| "--encode=${invoker.testcase_proto_kind}", |
| "-I", |
| rebase_path(root_gen_dir), |
| "-I", |
| rebase_path("//"), |
| rebase_path(inputs[0]), |
| ] |
| |
| deps = [] |
| |
| if (defined(invoker.proto_deps)) { |
| deps += invoker.proto_deps |
| } |
| |
| testonly = true |
| } |
| } |
| |
| in_process_fuzzer(target_name) { |
| sources = invoker.sources |
| deps = [ |
| ":${proto_target_name}", |
| "//chrome/test/fuzzing:in_process_proto_fuzzer_runner", |
| "//third_party/libprotobuf-mutator", |
| ] |
| |
| if (defined(invoker.deps)) { |
| deps += invoker.deps |
| } |
| |
| if (defined(invoker.seed_corpus_sources)) { |
| seed_corpus = seed_corpus_path |
| seed_corpus_deps = [ ":${protoc_convert_target_name}" ] |
| } |
| } |
| } else { |
| # noop if the fuzzer harness always provides its own main |
| not_needed(invoker, "*") |
| |
| group(target_name) { |
| } |
| } |
| } |