构建模糊测试工具

本指南假定您已创建一个要构建的模糊测试工具。它使用与该指南中相同的示例代码

Fuchsia 使用元构建系统 GN 生成明确描述如何构建系统的 .ninja 文件。GN 目标是构建图中的节点,表示特定输出(例如库或可执行文件)。GN 模板是用于生成其他目标的规则。

为了尽可能轻松地添加新的模糊测试工具,Fuchsia 提供了与模糊测试相关的 GN 模板。

定义 build 规则后,您可以使用 fx 构建 fuzzer

Fuchsia 库 fuzzer GN 模板

每种语言都有特定的模糊测试 GN 模板:

C/C++

fuchsia_library_fuzzer GN 模板会生成一个 executable 目标,该目标会编译模糊测试目标函数,并将其与被测代码和模糊测试引擎相关联。

如需为 C 或 C++ 模糊测试工具创建构建规则,请将 fuchsia_library_fuzzer GN 目标添加到适当的 BUILD.gn,例如包含相应单元测试规则的 BUILD.gn。

例如:

import("//build/fuzz.gni")

fuchsia_library_fuzzer("parser-fuzzer") {
  sources = [ "parser_fuzzer.cc" ]
  deps = [ ":parser-lib" ]
}

Rust

rustc_fuzzer GN 模板会生成一个 GN 目标,该目标会将 Rust 模糊测试目标函数编译为 C 对象文件,然后与模糊测试引擎关联。

如需为 Rust 模糊测试工具创建构建规则,请将 rustc_fuzzer GN 目标添加到 crate 的 BUILD.gn 中。

在选择添加此定位条件的位置和方式时,请考虑以下事项:

  • 建议将 fuzz 工具名称与 fuzz 目标函数名称保持一致,并将 fuzz 目标函数包含在 Rust 库(即 src/lib.rs)中。遵循这些建议时,您可以将模板正文留空。例如,使用 toy_example_arbitrary 示例,您需要在 BUILD.gn 中添加以下内容:
import("//build/rust/rustc_fuzzer.gni")

rustc_fuzzer("toy_example_arbitrary") {
}
  • 如果模糊测试目标函数名称与模糊测试程序名称不同,您必须为其提供 rustfunction 参数。例如,使用 toy_example_u8 示例,您需要向 BUILD.gn 添加以下内容:
import("//build/rust/rustc_fuzzer.gni")

rustc_fuzzer("toy_example_raw_bytes") {
    rustfunction = "toy_example_u8"
}
  • 如果要测试的代码无法轻松分解到库中,可以通过另外两个步骤使用 Rust 二进制文件:

  • 您必须从编译中排除 main 函数以及模糊测试时不使用的所有项,例如仅在 main 中使用的导入。例如:

    #[cfg(not(fuzz))]
    use only::used::in::main;
    
    #[cfg(not(fuzz))]
    fn main() { ... }
    
  • 您必须使用 source_root 参数向 rustc_fuzzer 明确提供模糊测试目标函数。例如,在 BUILD.gn 中:

    import("//build/rust/rustc_fuzzer.gni")
    
    rustc_fuzzer("toy_example_with_main") {
        source_root = "src/main.rs"
    }
    

选择某个模糊测试变体后,这些模板将通过将 [libFuzzer] 编译器运行时与提供的 sources 和/或 deps 相关联来构建模糊测试工具二进制文件。此代码必须提供模糊测试目标函数。

否则,您可以通过将测试框架与所提供的代码相关联来构建模糊测试单元测试。此测试框架会使用固定输入(例如长度为零的输入)调用模糊测试目标函数。此测试可确保模糊测试程序能够编译和链接,即使未构建以进行模糊测试也是如此。

主机库 fuzzer GN 模板

您还可以使用 Fuchsia 构建系统构建在开发主机上运行的模糊测试工具。如需构建主机模糊测试工具,请使用 host_library_fuzzer GN 模板。

例如:

host_library_fuzzer("my_host_fuzzer") {
  sources = [ ... ]
  deps = [ ... ]
}

您可以使用 fx 构建主机模糊测试工具,而无需将其添加到 Fuchsia 组件或软件包中。

Fuchsia fuzzer 组件 GN 模板

fuchsia_fuzzer_component 模板会创建用于运行 fuzz 工具的组件。它可以包含常规的组件参数,例如 component_namedeps

例如:

fuchsia_fuzzer_component("my-fuzzer-component") {
  component_name = "my-fuzzer"
  manifest = "meta/my-fuzzer.cml"
  deps = [ ":my-corpus"]
}

库 fuzz 工具的 manifest 必须包含 libfuzzer 的默认分片。必须将模糊测试程序的输出名称作为第一个程序参数(以相对于软件包的路径形式)提供。其他参数可能包括 libFuzzer 选项,或种子输入目录的软件包相对路径(称为种子语料库)。

例如:

{
    include: [
        "//sdk/lib/inspect/client.shard.cml",
        "//src/sys/fuzzing/libfuzzer/default.shard.cml",
        "//src/sys/test_runners/fuzz/default.shard.cml",
        "//src/sys/test_runners/tmp_storage.shard.cml",
        "syslog/client.shard.cml",
    ]
    program: {
        args: [
            "test/my-fuzzer",
            "-max_input_size=256",
            "data/my-corpus",
        ]
    }
}

种子语料库应与组件的 deps 中包含的 resource 目标相匹配。

例如:


import("//build/dist/resource.gni")

resource("my-corpus") {
  sources = [
    "input0",
    "input1",
    "input2",
  ]
  outputs = [ "data/my-corpus/{{source_file_part}}" ]
}

Fuchsia fuzzer 软件包 GN 模板

fuchsia_fuzzer_package 模板会将 fuzz 测试组件打包到 Fuchsia 软件包中,类似于 fuchsia_test_package 打包测试组件的方式。 fuchsia_fuzzer_package 模板的区别在于,在使用模糊测试工具链变体进行构建时,您可以添加特定的构建规则,为模糊测试工具添加注解。

该模板包含一些参数,这些参数是按语言整理的模糊测试组件列表。每种语言都有一组由其工具链作为编译器运行时提供的受支持的sanitizer。如果所选的工具链变体包含适用于给定语言的沙盒化工具,则相应的模糊测试组件列表能够进行模糊测试。

例如,如果 C++ 工具链支持假设的 examplesan,Rust 工具链不支持,并且选择了 examplesan-fuzzer 变体,则以下软件包定义会构建用于模糊测试的 my-cpp-fuzzer 和仅用于测试的 my-rust-fuzzer

fuchsia_fuzzer_package("my-fuzzers") {
  cpp_fuzz_components = [ ":my-cpp-fuzzer" ]
  rust_fuzz_components = [ ":my-rust-fuzzer" ]
}

如果软件包中没有使用相应语言编写的模糊测试工具,则无需添加列表。

fuchsia_fuzzer_package 可以使用与 fuchsia_package 相同的所有参数。

例如:

fuchsia_fuzzer_package("my-fuzzers") {
  package_name = "the-fuzzers"
  cpp_fuzz_components = [ ":my-fuzzer" ]
}

定义后,软件包需要像任何其他测试软件包一样包含在 build 依赖项图中。这通常意味着将其添加到一组测试中。

例如:

group("tests") {
  deps = [
    ":my-test-package",
    ":my-fuzzers",
  ]
}

使用 fx 构建模糊测试工具

如上所述,只有在明确指示 Fuchsia 构建系统使用适当的模糊测试变体对模糊测试程序进行插桩以进行模糊测试时,该构建系统才会构建模糊测试程序。这些是以 -fuzzer 结尾的已知变体。每种类型都是sanitizer 变体的扩展,包括:

如需使用模糊测试变体构建 fuzzer_package,最简单的方法是将 --fuzz-with <sanitizer> 标志与 fx set 搭配使用。

例如:

fx set core.x64 --fuzz-with asan --with //bundles/tests
fx build

运行 fx set 后,您可以使用 ffx fuzz list 查看当前配置的模糊测试工具。您可以使用其他 ffx fuzz 命令来运行模糊测试工具