aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 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 | |
aizatsky | 7dfb5734 | 2015-12-21 04:02:52 | [diff] [blame] | 5 | # Defines fuzzer_test. |
| 6 | # |
Max Moroz | 915eb5a | 2018-04-24 16:10:35 | [diff] [blame] | 7 | import("//build/config/coverage/coverage.gni") |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 8 | import("//build/config/features.gni") |
| 9 | import("//build/config/sanitizers/sanitizers.gni") |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 10 | import("//testing/test.gni") |
| 11 | |
| 12 | # fuzzer_test is used to define individual libfuzzer tests. |
| 13 | # |
| 14 | # Supported attributes: |
| 15 | # - (required) sources - fuzzer test source files |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 16 | # - deps - test dependencies |
| 17 | # - additional_configs - additional configs to be used for compilation |
| 18 | # - dict - a dictionary file for the fuzzer. |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 19 | # - libfuzzer_options - options for the fuzzer (e.g. -max_len or -timeout). |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 20 | # - seed_corpus - a directory with seed corpus. |
Calder Kitagawa | 90e9fb1 | 2018-05-07 16:08:57 | [diff] [blame] | 21 | # - seed_corpus_deps - dependencies for generating the seed corpus. |
Abhishek Arya | c73294d | 2018-04-26 22:12:43 | [diff] [blame] | 22 | # - skip_owners - if true, skips writing the owners file. |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 23 | # |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 24 | # If use_libfuzzer gn flag is defined, then proper fuzzer would be build. |
metzman | 8c9ed0e | 2016-06-21 20:37:20 | [diff] [blame] | 25 | # Without use_libfuzzer or use_afl a unit-test style binary would be built on |
| 26 | # linux and the whole target is a no-op otherwise. |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 27 | # |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 28 | # The template wraps test() target with appropriate dependencies. |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 29 | # If any test run-time options are present (dict or libfuzzer_options), then a |
| 30 | # config (.options file) file would be generated or modified in root output |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 31 | # dir (next to test). |
| 32 | template("fuzzer_test") { |
Max Moroz | 915eb5a | 2018-04-24 16:10:35 | [diff] [blame] | 33 | assert(!(is_mac && use_clang_coverage && use_fuzzing_engine), |
| 34 | "Code Coverage for fuzz targets does not work on Mac until " + |
| 35 | "crbug.com/790747 is resolved.") |
| 36 | |
Jonathan Metzman | d901d1b | 2017-10-09 23:07:28 | [diff] [blame] | 37 | if (!disable_libfuzzer && (use_fuzzing_engine || use_drfuzz || is_linux)) { |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 38 | assert(defined(invoker.sources), "Need sources in $target_name.") |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 39 | |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 40 | test_deps = [ "//testing/libfuzzer:libfuzzer_main" ] |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 41 | |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 42 | if (defined(invoker.deps)) { |
| 43 | test_deps += invoker.deps |
| 44 | } |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 45 | |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 46 | if (defined(invoker.seed_corpus) || defined(invoker.seed_corpuses)) { |
| 47 | assert(!(defined(invoker.seed_corpus) && defined(invoker.seed_corpuses)), |
| 48 | "Do not use both seed_corpus and seed_corpuses for $target_name.") |
| 49 | |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 50 | out = "$root_build_dir/$target_name" + "_seed_corpus.zip" |
| 51 | |
Calder Kitagawa | 90e9fb1 | 2018-05-07 16:08:57 | [diff] [blame] | 52 | seed_corpus_deps = [] |
| 53 | |
| 54 | if (defined(invoker.seed_corpus_deps)) { |
| 55 | seed_corpus_deps += invoker.seed_corpus_deps |
| 56 | } |
| 57 | |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 58 | action(target_name + "_seed_corpus") { |
| 59 | script = "//testing/libfuzzer/archive_corpus.py" |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 60 | |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 61 | args = [ |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 62 | "--output", |
wychen | 5e1f725 | 2017-05-30 08:05:10 | [diff] [blame] | 63 | rebase_path(out, root_build_dir), |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 64 | ] |
| 65 | |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 66 | if (defined(invoker.seed_corpus)) { |
wychen | 5e1f725 | 2017-05-30 08:05:10 | [diff] [blame] | 67 | args += [ rebase_path(invoker.seed_corpus, root_build_dir) ] |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | if (defined(invoker.seed_corpuses)) { |
| 71 | foreach(seed_corpus_path, invoker.seed_corpuses) { |
wychen | 5e1f725 | 2017-05-30 08:05:10 | [diff] [blame] | 72 | args += [ rebase_path(seed_corpus_path, root_build_dir) ] |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 73 | } |
| 74 | } |
| 75 | |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 76 | outputs = [ |
| 77 | out, |
| 78 | ] |
mmoroz | 902ef43 | 2017-02-07 17:03:37 | [diff] [blame] | 79 | |
Calder Kitagawa | 90e9fb1 | 2018-05-07 16:08:57 | [diff] [blame] | 80 | deps = [ "//testing/libfuzzer:seed_corpus" ] + seed_corpus_deps |
aizatsky | 198e302 | 2016-03-08 21:33:46 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | test_deps += [ ":" + target_name + "_seed_corpus" ] |
| 84 | } |
| 85 | |
mmoroz | 062a4a6 | 2016-04-12 09:02:33 | [diff] [blame] | 86 | if (defined(invoker.dict) || defined(invoker.libfuzzer_options)) { |
| 87 | if (defined(invoker.dict)) { |
| 88 | # Copy dictionary to output. |
| 89 | copy(target_name + "_dict_copy") { |
| 90 | sources = [ |
| 91 | invoker.dict, |
| 92 | ] |
| 93 | outputs = [ |
| 94 | "$root_build_dir/" + target_name + ".dict", |
| 95 | ] |
| 96 | } |
| 97 | test_deps += [ ":" + target_name + "_dict_copy" ] |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 98 | } |
| 99 | |
mmoroz | 062a4a6 | 2016-04-12 09:02:33 | [diff] [blame] | 100 | # Generate .options file. |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 101 | config_file_name = target_name + ".options" |
| 102 | action(config_file_name) { |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 103 | script = "//testing/libfuzzer/gen_fuzzer_config.py" |
| 104 | args = [ |
| 105 | "--config", |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 106 | rebase_path("$root_build_dir/" + config_file_name, root_build_dir), |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 107 | ] |
| 108 | |
mmoroz | 062a4a6 | 2016-04-12 09:02:33 | [diff] [blame] | 109 | if (defined(invoker.dict)) { |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 110 | args += [ |
mmoroz | 062a4a6 | 2016-04-12 09:02:33 | [diff] [blame] | 111 | "--dict", |
wychen | 5e1f725 | 2017-05-30 08:05:10 | [diff] [blame] | 112 | rebase_path("$root_build_dir/" + invoker.target_name + ".dict", |
| 113 | root_build_dir), |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 114 | ] |
| 115 | } |
mmoroz | 062a4a6 | 2016-04-12 09:02:33 | [diff] [blame] | 116 | |
| 117 | if (defined(invoker.libfuzzer_options)) { |
| 118 | args += [ "--libfuzzer_options" ] |
| 119 | args += invoker.libfuzzer_options |
| 120 | } |
| 121 | |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 122 | outputs = [ |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 123 | "$root_build_dir/$config_file_name", |
mmoroz | 344a75ae | 2016-03-02 16:57:17 | [diff] [blame] | 124 | ] |
| 125 | } |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 126 | test_deps += [ ":" + config_file_name ] |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 127 | } |
| 128 | |
Abhishek Arya | c73294d | 2018-04-26 22:12:43 | [diff] [blame] | 129 | # Generate .owners file (if skip_owners is not true). |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 130 | owners_file_name = target_name + ".owners" |
| 131 | action(owners_file_name) { |
| 132 | script = "//testing/libfuzzer/gen_fuzzer_owners.py" |
| 133 | args = [ |
| 134 | "--owners", |
| 135 | rebase_path("$root_build_dir/" + owners_file_name, root_build_dir), |
| 136 | ] |
Abhishek Arya | e1488c92 | 2018-04-26 03:25:58 | [diff] [blame] | 137 | |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 138 | if (defined(invoker.sources) && invoker.sources != []) { |
| 139 | args += [ "--sources" ] + rebase_path(invoker.sources, root_build_dir) |
| 140 | } else if (defined(invoker.deps) && invoker.deps != []) { |
Lei Zhang | 5c96e42 | 2018-05-30 18:27:11 | [diff] [blame^] | 141 | _full_deps = [] |
| 142 | foreach(_dep, invoker.deps) { |
| 143 | _full_deps += [ get_label_info(_dep, "dir") + ":" + |
| 144 | get_label_info(_dep, "name") ] |
| 145 | } |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 146 | args += [ |
| 147 | "--build-dir", |
| 148 | rebase_path("$root_build_dir/", root_build_dir), |
| 149 | "--deps", |
Lei Zhang | 5c96e42 | 2018-05-30 18:27:11 | [diff] [blame^] | 150 | ] + _full_deps |
Abhishek Arya | e1488c92 | 2018-04-26 03:25:58 | [diff] [blame] | 151 | } |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 152 | |
| 153 | outputs = [ |
| 154 | "$root_build_dir/$owners_file_name", |
| 155 | ] |
Abhishek Arya | e1488c92 | 2018-04-26 03:25:58 | [diff] [blame] | 156 | } |
Abhishek Arya | 31f18f5 | 2018-04-27 19:27:34 | [diff] [blame] | 157 | test_deps += [ ":" + owners_file_name ] |
Abhishek Arya | e1488c92 | 2018-04-26 03:25:58 | [diff] [blame] | 158 | |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 159 | test(target_name) { |
| 160 | forward_variables_from(invoker, |
| 161 | [ |
[email protected] | 419d0f9 | 2017-09-14 12:07:47 | [diff] [blame] | 162 | "cflags", |
| 163 | "cflags_cc", |
brettw | 6b0712a | 2016-07-15 17:48:20 | [diff] [blame] | 164 | "check_includes", |
wfh | dee978f | 2016-09-01 22:18:18 | [diff] [blame] | 165 | "defines", |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 166 | "include_dirs", |
brettw | 6b0712a | 2016-07-15 17:48:20 | [diff] [blame] | 167 | "sources", |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 168 | ]) |
| 169 | deps = test_deps |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 170 | |
| 171 | if (defined(invoker.additional_configs)) { |
| 172 | configs += invoker.additional_configs |
| 173 | } |
aizatsky | 345732a | 2016-04-14 22:30:44 | [diff] [blame] | 174 | configs += [ "//testing/libfuzzer:fuzzer_test_config" ] |
katrielc | 2bfe7048 | 2016-06-16 13:43:00 | [diff] [blame] | 175 | |
| 176 | # Used by WebRTC to suppress some Clang warnings in their codebase. |
| 177 | if (defined(invoker.suppressed_configs)) { |
| 178 | configs -= invoker.suppressed_configs |
| 179 | } |
Robert Sesek | d88ebf8 | 2017-10-17 21:54:41 | [diff] [blame] | 180 | |
| 181 | if (is_mac) { |
Max Moroz | ae3aae5 | 2017-10-18 01:50:19 | [diff] [blame] | 182 | sources += [ "//testing/libfuzzer/libfuzzer_exports.h" ] |
Robert Sesek | d88ebf8 | 2017-10-17 21:54:41 | [diff] [blame] | 183 | } |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 184 | } |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 185 | } else { |
| 186 | # noop on unsupported platforms. |
| 187 | # mark attributes as used. |
Tom Anderson | c94b10c | 2018-05-18 16:12:51 | [diff] [blame] | 188 | not_needed(invoker, "*") |
aizatsky | 43d459a5 | 2016-02-13 01:22:18 | [diff] [blame] | 189 | |
| 190 | group(target_name) { |
aizatsky | cb1a4393 | 2015-12-14 20:59:14 | [diff] [blame] | 191 | } |
| 192 | } |
| 193 | } |