构建模糊测试工具

本指南假定您已创建模糊测试器,现在想要 构建该模糊测试器。它使用与该指南中相同的示例代码

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

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

定义构建规则后,您可以使用 fx 构建模糊测试器

Fuchsia 库模糊测试器 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。

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

  • 建议模糊测试器名称与模糊测试目标函数名称一致,并将模糊测试目标函数包含在 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] 编译器运行时与提供的 sourcesdeps 或两者进行链接来构建模糊测试器 二进制文件。此代码必须提供一个模糊测试目标函数。

否则,系统会通过将测试桩与提供的 代码进行链接来构建模糊测试器单元测试。此测试桩使用固定输入(例如零长度输入)调用模糊测试目标函数。此测试可确保模糊测试器能够编译和链接,即使在不构建模糊测试时也是如此。

主机库模糊测试器 GN 模板

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

例如:

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

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

Fuchsia 模糊测试器组件 GN 模板

fuchsia_fuzzer_component template 会创建一个用于 运行模糊测试器的组件。它可以包含常用的组件参数,例如 component_namedeps

例如:

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

{1模糊测试器的输出名称必须作为第一个程序实参以软件包相对路径的形式提供。其他实参可以包括 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 模糊测试器软件包 GN 模板

fuchsia_fuzzer_package 模板 会将模糊测试器组件捆绑到 Fuchsiafuchsia_test_packagefuchsia_fuzzer_package 模板的特点是,当模糊测试工具链 变体 构建模糊测试器时,它会添加特定的构建规则来对模糊测试器进行注释。

该模板包含按语言组织的模糊测试器组件列表的参数。每种语言都有一组由其工具链作为编译器运行时提供的受支持的排错程序。当所选工具链变体包含给定语言支持的排错程序时,相应的模糊测试器组件列表能够进行模糊测试。

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

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

如果软件包没有使用相应语言编写的模糊测试器,则无需包含列表。

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

例如:

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

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

例如:

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

使用 fx 构建模糊测试器

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

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

例如:

fx set core.x64 --fuzz-with asan --with //bundles/tests --include-clippy=false
fx build

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