0.2.7 2022年8月16日
0.2.6 2022年8月14日
0.2.2 2022年7月22日
0.1.7 2022年7月10日
0.1.1 2022年6月6日

#16 in #corpus


aptos-fuzz 中使用

Apache-2.0

4MB
80K SLoC

Aptos 的模糊测试支持

此crate包含对Aptos目标的模糊测试支持。该支持包括

  • 使用 proptest 生成语料库
  • 使用 cargo test 自动运行失败的示例

先决条件

如果尚未安装,请安装 cargo-fuzzcargo install cargo-fuzz

模糊测试一个目标

首先,切换到本README所在的目录: cd testsuite/aptos-fuzzer

要列出已知的模糊测试目标,运行 cargo run --bin aptos-fuzzer list

为了有效进行模糊测试,需要一个现有的输入语料库。此crate包含使用 proptest 生成语料库的支持。使用 cargo run --bin aptos-fuzzer generate <target> 生成语料库。

一旦生成了语料库,模糊测试器就准备就绪,只需运行

RUSTC_BOOTSTRAP=1 cargo run --bin aptos-fuzzer --release fuzz <target>

要获取更多选项,请运行cargo run --bin aptos-fuzzer -- --help。请注意,作为cargo fuzz使用不稳定编译器标志的必要条件,必须设置RUSTC_BOOTSTRAP=1

添加新的目标

模糊测试目标存放在src/fuzz_targets/中。添加新目标需要创建一个新的类型并为它实现FuzzTargetImpl

有关示例,请参阅src/fuzz_targets/中现有的实现。

请记得将您的目标添加到src/fuzz_targets.rs中的ALL_TARGETS。完成此操作后,运行cargo run --bin aptos-fuzzer list应列出您的新目标。

调试和测试工件

如果模糊测试器找到失败的工件,它将工件保存到fuzz目录中的文件中,并打印其路径。要将此工件添加到测试套件中,将其复制到artifacts/<target>/目录中的一个文件中。

现在,cargo test将测试反序列化程序与新的工件。测试可能会在第一次使用时失败。

请注意,默认情况下,cargo test将在单独的进程中运行每个测试以隔离失败和内存使用;如果您正在附加调试器并运行单个测试,请设置NO_FORK=1以禁用分叉。

一旦反序列化程序已修复,请将工件检入artifacts/<target>/目录。然后该工件将作为cargo test运行时的回归测试。

有两种方法可以重现问题以进行调查

  1. 直接运行 Harness 测试(模糊测试器运行的代码)
  2. 运行模糊测试代码

以下命令(其中包含您的工件,位于类似路径)将使用您的输入运行 Harness 测试

cargo run --bin investigate -- -i artifacts/compiled_module/crash-5d7f403f

以下命令将在相关目标上运行 libfuzzer,使用您的输入

# build single fuzzer for target using instruction in the 'google oss-fuzz integration' section
./fuzzer input

请注意,对于崩溃,这应该可以正常工作,但对于超时可能需要 libfuzzer 的-timeout 25参数,对于内存不足可能需要 libfuzzer 的-rss_limit_mb=2560参数。

请参阅Google OSS-Fuzz 关于重现错误的文档

火焰图

要获取 Harness 测试的火焰图,请运行以下命令

FUZZ_TARGET=compiled_module cargo flamegraph -p aptos-fuzzer --bin flamegraph

最好先生成一些语料库并在上面运行模糊测试器一段时间(以找到新的语料库)。语料库越大,您获得的火焰图就越好。

模糊测试覆盖率

要测试模糊测试器的覆盖率,您可以使用grcov运行以下命令

RUSTFLAGS='--cfg feature="fuzzing"' CORPUS_PATH=fuzz/corpus cargo xtest --html-cov-dir <some path for html output> -p aptos-fuzzer -- --test-threads 1 --ignored coverage

构建单个模糊测试器

要将我们的模糊器集成到Google OSS-Fuzz项目中,我们需要为每个模糊器提供一个二进制文件。当您想使用Instruments等工具分析模糊器时,这也会很有用。为此,build.rs可以根据环境变量创建一个模糊器二进制文件。使用方法如下:

cd aptos-core/testsuite/aptos-fuzzer
fuzz/google-oss-fuzz/build_fuzzer.sh ConsensusProposal .
./ConsensusProposal

故障排除

我的堆栈跟踪不包含文件名和行号

您需要使用llvm-symbolizer,请参阅https://github.com/rust-fuzz/cargo-fuzz/issues/160

macOS: 使用cc链接失败

请确保Xcode已更新到最新版本。记住在重新构建之前,实际上使用xcode-select更新新应用程序文件夹,并执行cargo clean

sudo xcode-select -s /Applications/Xcode_X.Y.Z.app

如果您遇到链接器错误,如

$ RUSTC_BOOTSTRAP=1 cargo run --bin aptos-fuzzer --release fuzz <target>
# ...
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-L" "/Users/philiphayes/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" # ...
  = note: Undefined symbols for architecture x86_64:
            "_CFMutableAttributedStringGetTypeID", referenced from:
                _$LT$core_foundation..attributed_string..CFMutableAttributedString$u20$as$u20$core_foundation..base..TCFType$GT$::type_id::h9f6f71bdd347aca0 # ...
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error

这可能是由于core-foundation-rs(https://github.com/servo/core-foundation-rs/pull/357)中的问题造成的,该问题已在最新版本中修复,但我们的一个间接依赖项native-tls仅在它的master分支中更新。要修复此问题,请将以下内容添加到aptos-core/Cargo.toml的末尾

[patch.crates-io]
native-tls = { git = "https://github.com/sfackler/rust-native-tls" }

依赖项

~117MB
~2.5M SLoC