123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- # Copyright 2015 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- # Defines fuzzer_test.
- #
- import("//build/config/features.gni")
- import("//build/config/sanitizers/sanitizers.gni")
- import("//testing/test.gni")
- # fuzzer_test is used to define individual libfuzzer tests.
- #
- # Supported attributes:
- # - (required) sources - fuzzer test source files
- # - deps - test dependencies
- # - libs - Additional libraries to link.
- # - frameworks - Apple-only. Additional frameworks to link.
- # - additional_configs - additional configs to be used for compilation
- # - dict - a dictionary file for the fuzzer.
- # - environment_variables - certain whitelisted environment variables for the
- # fuzzer (AFL_DRIVER_DONT_DEFER is the only one allowed currently).
- # - libfuzzer_options - options for the fuzzer (e.g. -close_fd_mask=N).
- # - asan_options - AddressSanitizer options (e.g. allow_user_segv_handler=1).
- # - msan_options - MemorySanitizer options.
- # - ubsan_options - UndefinedBehaviorSanitizer options.
- # - seed_corpus - a directory with seed corpus.
- # - seed_corpus_deps - dependencies for generating the seed corpus.
- # - grammar_options - defines a grammar used by a grammar based mutator.
- #
- # If use_libfuzzer gn flag is defined, then proper fuzzer would be build.
- # Without use_libfuzzer or use_afl a unit-test style binary would be built on
- # linux and the whole target is a no-op otherwise.
- #
- # The template wraps test() target with appropriate dependencies.
- # If any test run-time options are present (dict or libfuzzer_options), then a
- # config (.options file) file would be generated or modified in root output
- # dir (next to test).
- template("fuzzer_test") {
- if (!disable_libfuzzer && use_fuzzing_engine) {
- assert(defined(invoker.sources), "Need sources in $target_name.")
- test_deps = [ "//testing/libfuzzer:libfuzzer_main" ]
- test_data_deps = []
- if (defined(invoker.deps)) {
- test_deps += invoker.deps
- }
- if (defined(invoker.data_deps)) {
- test_data_deps += invoker.data_deps
- }
- supporting_file_test_deps = []
- supporting_file_test_data_deps = []
- if (defined(invoker.seed_corpus) || defined(invoker.seed_corpuses)) {
- assert(!(defined(invoker.seed_corpus) && defined(invoker.seed_corpuses)),
- "Do not use both seed_corpus and seed_corpuses for $target_name.")
- out = "$root_build_dir/$target_name" + "_seed_corpus.zip"
- seed_corpus_deps = []
- if (defined(invoker.seed_corpus_deps)) {
- seed_corpus_deps += invoker.seed_corpus_deps
- }
- action(target_name + "_seed_corpus") {
- script = "//testing/libfuzzer/archive_corpus.py"
- testonly = true
- args = [
- "--output",
- rebase_path(out, root_build_dir),
- ]
- if (defined(invoker.seed_corpus)) {
- args += [ rebase_path(invoker.seed_corpus, root_build_dir) ]
- }
- if (defined(invoker.seed_corpuses)) {
- foreach(seed_corpus_path, invoker.seed_corpuses) {
- args += [ rebase_path(seed_corpus_path, root_build_dir) ]
- }
- }
- outputs = [ out ]
- deps = [ "//testing/libfuzzer:seed_corpus" ] + seed_corpus_deps
- }
- if (archive_seed_corpus) {
- supporting_file_test_deps += [ ":" + target_name + "_seed_corpus" ]
- }
- }
- if (defined(invoker.dict) || defined(invoker.libfuzzer_options) ||
- defined(invoker.asan_options) || defined(invoker.msan_options) ||
- defined(invoker.ubsan_options) ||
- defined(invoker.environment_variables) ||
- defined(invoker.grammar_options)) {
- if (defined(invoker.dict)) {
- # Copy dictionary to output.
- copy(target_name + "_dict_copy") {
- sources = [ invoker.dict ]
- outputs = [ "$root_build_dir/" + target_name + ".dict" ]
- }
- supporting_file_test_deps += [ ":" + target_name + "_dict_copy" ]
- }
- # Generate .options file.
- config_file_name = target_name + ".options"
- action(config_file_name) {
- script = "//testing/libfuzzer/gen_fuzzer_config.py"
- args = [
- "--config",
- rebase_path("$root_build_dir/" + config_file_name, root_build_dir),
- ]
- if (defined(invoker.dict)) {
- args += [
- "--dict",
- rebase_path("$root_build_dir/" + invoker.target_name + ".dict",
- root_build_dir),
- ]
- }
- if (defined(invoker.libfuzzer_options)) {
- args += [ "--libfuzzer_options" ]
- args += invoker.libfuzzer_options
- }
- if (defined(invoker.asan_options)) {
- args += [ "--asan_options" ]
- args += invoker.asan_options
- }
- if (defined(invoker.msan_options)) {
- args += [ "--msan_options" ]
- args += invoker.msan_options
- }
- if (defined(invoker.ubsan_options)) {
- args += [ "--ubsan_options" ]
- args += invoker.ubsan_options
- }
- if (defined(invoker.environment_variables)) {
- args += [ "--environment_variables" ]
- args += invoker.environment_variables
- }
- if (defined(invoker.grammar_options)) {
- args += [ "--grammar_options" ]
- args += invoker.grammar_options
- }
- outputs = [ "$root_build_dir/$config_file_name" ]
- }
- supporting_file_test_deps += [ ":" + config_file_name ]
- }
- if (generate_fuzzer_owners) {
- # Generating owners files is slow, only enable when fuzzing engine is
- # used.
- owners_file_name = target_name + ".owners"
- action(owners_file_name) {
- script = "//testing/libfuzzer/gen_fuzzer_owners.py"
- pool = "//testing/libfuzzer:fuzzer_owners_pool"
- args = [
- "--owners",
- rebase_path("$root_build_dir/" + owners_file_name, root_build_dir),
- ]
- if (defined(invoker.sources) && invoker.sources != []) {
- args += [ "--sources" ] + rebase_path(invoker.sources, "//")
- } else if (defined(invoker.deps) && invoker.deps != []) {
- _full_deps = []
- foreach(_dep, invoker.deps) {
- _full_deps += [ get_label_info(_dep, "dir") + ":" +
- get_label_info(_dep, "name") ]
- }
- args += [
- "--build-dir",
- rebase_path("$root_build_dir/", root_build_dir),
- "--deps",
- ] + _full_deps
- }
- outputs = [ "$root_build_dir/$owners_file_name" ]
- }
- supporting_file_test_data_deps += [ ":" + owners_file_name ]
- }
- # Copy to executable folder and codesign for catalyst
- if (is_ios) {
- # iOS only supports fuzzer in catalyst environment.
- assert(target_environment == "catalyst")
- # Loop over two kinds of deps to codesign these in two |action_foreach|s.
- # Use the "test_deps", "test_data_deps" as identifiers in for loop.
- foreach(_deps_type_label,
- [
- "test_deps",
- "test_data_deps",
- ]) {
- _dep_list = []
- if (_deps_type_label == "test_deps") {
- _dep_list = supporting_file_test_deps
- } else {
- _dep_list = supporting_file_test_data_deps
- }
- _files_to_sign = []
- foreach(dep, _dep_list) {
- _files_to_sign += get_target_outputs(dep)
- }
- if (_files_to_sign != []) {
- _codesign_action_name =
- target_name + "_codesign_supporting_files_" + _deps_type_label
- action_foreach(_codesign_action_name) {
- testonly = true
- script = "//build/config/ios/codesign.py"
- sources = _files_to_sign
- _codesign_output_path =
- "${root_build_dir}/codesign/{{source_file_part}}"
- outputs = [ _codesign_output_path ]
- args = [
- "code-sign-file",
- "--identity=" + ios_code_signing_identity,
- "--output=" + rebase_path(_codesign_output_path, root_build_dir),
- "{{source}}",
- ]
- deps = _dep_list
- }
- _bundle_data_name = target_name + "_bundle_data_" + _deps_type_label
- bundle_data(_bundle_data_name) {
- testonly = true
- sources = get_target_outputs(":${_codesign_action_name}")
- outputs = [ "{{bundle_executable_dir}}/{{source_file_part}}" ]
- public_deps = [ ":${_codesign_action_name}" ]
- }
- if (_deps_type_label == "test_deps") {
- test_deps += [ ":${_bundle_data_name}" ]
- } else {
- test_data_deps += [ ":${_bundle_data_name}" ]
- }
- }
- }
- } else {
- test_deps += supporting_file_test_deps
- test_data_deps += supporting_file_test_data_deps
- }
- test(target_name) {
- forward_variables_from(invoker,
- [
- "cflags",
- "cflags_cc",
- "check_includes",
- "defines",
- "include_dirs",
- "sources",
- "libs",
- "frameworks",
- ])
- deps = test_deps
- data_deps = test_data_deps
- if (defined(invoker.additional_configs)) {
- configs += invoker.additional_configs
- }
- configs += [ "//testing/libfuzzer:fuzzer_test_config" ]
- # Used by WebRTC to suppress some Clang warnings in their codebase.
- if (defined(invoker.suppressed_configs)) {
- configs -= invoker.suppressed_configs
- }
- if (defined(invoker.generated_sources)) {
- sources += invoker.generated_sources
- }
- if (is_ios) {
- info_plist =
- "//testing/libfuzzer/fuzzer_support_ios/libfuzzer-Info.plist"
- }
- if (is_mac) {
- sources += [ "//testing/libfuzzer/libfuzzer_exports.h" ]
- }
- }
- } else {
- # noop on unsupported platforms.
- # mark attributes as used.
- not_needed(invoker, "*")
- group(target_name) {
- }
- }
- }
|