1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# Defines fuzzer_test. 6# 7import("//build_overrides/build.gni") 8 9# fuzzer_test is used to define individual libfuzzer tests. 10# 11# Supported attributes: 12# - (required) sources - fuzzer test source files 13# - deps - test dependencies 14# - libs - Additional libraries to link. 15# - additional_configs - additional configs to be used for compilation 16# - dict - a dictionary file for the fuzzer. 17# - environment_variables - certain environment variables allowed for the 18# fuzzer (AFL_DRIVER_DONT_DEFER is the only one allowed currently). 19# - libfuzzer_options - options for the fuzzer (e.g. -close_fd_mask=N). 20# - asan_options - AddressSanitizer options (e.g. allow_user_segv_handler=1). 21# - msan_options - MemorySanitizer options. 22# - ubsan_options - UndefinedBehaviorSanitizer options. 23# - seed_corpus - a directory with seed corpus. 24# - seed_corpus_deps - dependencies for generating the seed corpus. 25# 26# If use_libfuzzer gn flag is defined, then proper fuzzer would be build. 27# Without use_libfuzzer or use_afl a unit-test style binary would be built on 28# linux and the whole target is a no-op otherwise. 29# 30# The template wraps test() target with appropriate dependencies. 31# If any test run-time options are present (dict or libfuzzer_options), then a 32# config (.options file) file would be generated or modified in root output 33# dir (next to test). 34template("openscreen_fuzzer_test") { 35 if (is_clang && !build_with_chromium) { 36 assert(defined(invoker.sources), "Need sources in $target_name.") 37 38 test_deps = [ "//testing/libfuzzer:fuzzing_engine_main" ] 39 40 if (defined(invoker.seed_corpus) || defined(invoker.seed_corpuses)) { 41 assert(!(defined(invoker.seed_corpus) && defined(invoker.seed_corpuses)), 42 "Do not use both seed_corpus and seed_corpuses for $target_name.") 43 44 out = "$root_build_dir/$target_name" + "_seed_corpus.zip" 45 46 seed_corpus_deps = [] 47 48 if (defined(invoker.seed_corpus_deps)) { 49 seed_corpus_deps += invoker.seed_corpus_deps 50 } 51 52 action(target_name + "_seed_corpus") { 53 script = "//testing/libfuzzer/archive_corpus.py" 54 55 args = [ 56 "--output", 57 rebase_path(out, root_build_dir), 58 ] 59 60 if (defined(invoker.seed_corpus)) { 61 args += [ rebase_path(invoker.seed_corpus, root_build_dir) ] 62 } 63 64 if (defined(invoker.seed_corpuses)) { 65 foreach(seed_corpus_path, invoker.seed_corpuses) { 66 args += [ rebase_path(seed_corpus_path, root_build_dir) ] 67 } 68 } 69 70 outputs = [ out ] 71 72 deps = [ "//testing/libfuzzer:seed_corpus" ] + seed_corpus_deps 73 } 74 75 test_deps += [ ":" + target_name + "_seed_corpus" ] 76 } 77 78 if (defined(invoker.dict) || defined(invoker.libfuzzer_options) || 79 defined(invoker.asan_options) || defined(invoker.msan_options) || 80 defined(invoker.ubsan_options) || 81 defined(invoker.environment_variables)) { 82 if (defined(invoker.dict)) { 83 # Copy dictionary to output. 84 copy(target_name + "_dict_copy") { 85 sources = [ invoker.dict ] 86 outputs = [ "$root_build_dir/" + target_name + ".dict" ] 87 } 88 test_deps += [ ":" + target_name + "_dict_copy" ] 89 } 90 91 # Generate .options file. 92 config_file_name = target_name + ".options" 93 action(config_file_name) { 94 script = "//testing/libfuzzer/gen_fuzzer_config.py" 95 args = [ 96 "--config", 97 rebase_path("$root_build_dir/" + config_file_name, root_build_dir), 98 ] 99 100 if (defined(invoker.dict)) { 101 args += [ 102 "--dict", 103 rebase_path("$root_build_dir/" + invoker.target_name + ".dict", 104 root_build_dir), 105 ] 106 } 107 108 if (defined(invoker.libfuzzer_options)) { 109 args += [ "--libfuzzer_options" ] 110 args += invoker.libfuzzer_options 111 } 112 113 if (defined(invoker.asan_options)) { 114 args += [ "--asan_options" ] 115 args += invoker.asan_options 116 } 117 118 if (defined(invoker.msan_options)) { 119 args += [ "--msan_options" ] 120 args += invoker.msan_options 121 } 122 123 if (defined(invoker.ubsan_options)) { 124 args += [ "--ubsan_options" ] 125 args += invoker.ubsan_options 126 } 127 128 if (defined(invoker.environment_variables)) { 129 args += [ "--environment_variables" ] 130 args += invoker.environment_variables 131 } 132 133 outputs = [ "$root_build_dir/$config_file_name" ] 134 } 135 test_deps += [ ":" + config_file_name ] 136 } 137 138 executable(target_name) { 139 testonly = true 140 forward_variables_from(invoker, "*") 141 deps += test_deps 142 143 if (defined(invoker.additional_configs)) { 144 configs += invoker.additional_configs 145 } 146 configs += [ "//testing/libfuzzer:fuzzer_test_config" ] 147 148 if (defined(invoker.suppressed_configs)) { 149 configs -= invoker.suppressed_configs 150 } 151 152 if (defined(invoker.generated_sources)) { 153 sources += invoker.generated_sources 154 } 155 156 if (is_mac) { 157 sources += [ "//testing/libfuzzer/libfuzzer_exports.h" ] 158 } 159 } 160 } else { 161 # noop on unsupported platforms. 162 # mark attributes as used. 163 not_needed(invoker, "*") 164 165 group(target_name) { 166 } 167 } 168} 169