构建模糊测试工具

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

Fuchsia 使用 GN(一种元构建系统)生成 .ninja 文件,以明确描述如何构建系统。GN 目标是 build 图中代表特定输出(如库或可执行文件)的节点。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] 编译器运行时与提供的 sources 和/或 deps 相关联,以构建模糊测试工具二进制文件。此代码必须提供模糊测试目标函数。

否则,通过将自动化测试框架与提供的代码相关联来构建模糊测试工具单元测试。该自动化测试框架使用固定输入(例如长度为零的输入)调用模糊测试目标函数。此测试可确保模糊测试工具能够编译和链接,即使没有针对模糊测试进行构建也是如此。

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

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

例如:

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

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

Fuchsia 模糊测试工具组件 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 选项,或称为种子输入的目录的软件包相对路径(称为种子语料库)。

例如:

{
    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 模板

1fuchsia_fuzzer_packagefuchsia_test_packagefuchsia_fuzzer_package 模板的区别在于,当通过模糊测试工具链变体构建时,它会添加特定构建规则来为模糊测试工具添加注释。

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

例如,如果 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 命令可用于运行模糊测试工具