构建模糊测试工具

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

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

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

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

Fuchsia 库模糊测试器 GN 模板

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

C/C++

fuchsia_library_fuzzer GN 模板会生成一个 executable 目标,该目标可将模糊测试目标函数与被测代码和模糊测试引擎进行编译和链接。

如需为 C 或 C++ 模糊测试工具创建 build 规则,请将 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 fuzz 目标函数编译为 C 对象文件,然后将其与模糊测试引擎相关联。

如需为 Rust 模糊测试工具创建 build 规则,请向 crate 的 BUILD.gn 添加 rustc_fuzzer 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 或两者相关联来构建模糊测试工具二进制文件。此代码必须提供 fuzz target 函数。

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

宿主库模糊测试工具 GN 模板

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

例如:

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

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

Fuchsia fuzzing 工具组件 GN 模板

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

例如:

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

库模糊测试工具的 清单必须包含 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 fuzz 测试工具软件包 GN 模板

fuchsia_fuzzer_package 模板将模糊测试器组件捆绑到 Fuchsia 软件包中,类似于 fuchsia_test_package 捆绑测试组件的方式。通过添加特定的 build 规则来区分 fuchsia_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" ]
}

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

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

例如:

fuchsia_fuzzer_package("my-fuzzers") {
  package_name = "the-fuzzers"
  cpp_fuzzer_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 --include-clippy=false
fx build

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