• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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