Fuzzing Arrow C++#
为了提高对无效输入的鲁棒性,我们已在 Arrow C++ 功能集的多个部分启用了模糊测试(fuzz testing),目前包括:
IPC 流读取器
IPC 文件读取器
Parquet 文件读取器
Parquet 编码器和解码器
CSV 文件读取器
我们欢迎任何旨在扩展模糊测试范围的贡献,以覆盖那些可能摄入无效或恶意数据的领域。
模糊测试目标与实用工具#
通过传递 -DARROW_FUZZING=ON CMake 选项(或等效地使用 fuzzing 预设),您将构建与上述 Arrow 功能对应的模糊测试目标以及其他相关实用工具。
生成种子语料库#
模糊测试本质上是通过随机变异先前测试过的输入来探索域空间,而无需对被模糊测试的领域有任何高层次的了解。然而,域空间非常巨大,仅靠这种策略可能无法真正产生任何“有趣的”输入。
因此,为了引导这一过程,提供一个包含有效(或无效但值得注意)输入的种子语料库(seed corpus)非常重要,模糊测试基础设施可以从中派生出新的输入进行测试。我们提供了一个脚本来自动完成该任务。假设模糊测试可执行文件位于 build/debug 中,则可以按如下方式生成种子语料库:
$ ./build-support/fuzzing/generate_corpuses.sh build/debug
持续模糊测试基础设施#
模糊测试过程计算密集,因此受益于专门的计算设施。Arrow C++ 由 Google 运营的 OSS-Fuzz 持续模糊测试基础设施进行测试。
由 OSS-Fuzz 发现的问题会通知给有限的 核心开发者。如果您是 Arrow 核心开发者并希望被添加到该列表中,可以在 邮件列表 上申请。
本地复现#
当通过模糊测试发现崩溃时,下载用于产生崩溃的数据并利用它来复现崩溃,以便进行调试和调查,这通常非常有用。
假设您位于 cpp 目录下的子目录中,以下命令允许您构建带有调试信息和各种清理程序(sanitizer)检查启用的模糊测试目标。
$ cmake .. --preset=fuzzing
然后,假设您已经下载了崩溃数据文件(我们称之为 testcase-arrow-ipc-file-fuzz-123465),您可以通过在该文件上运行受影响的模糊测试目标来复现崩溃:
$ build/debug/arrow-ipc-file-fuzz testcase-arrow-ipc-file-fuzz-123465
(您可能希望在调试器下运行该命令,以便更仔细地检查程序状态)
使用 conda#
模糊测试可执行文件必须使用 clang 编译,并链接到提供模糊测试运行时的库。如果您使用 conda 来提供依赖项,则可能需要在构建模糊测试目标之前安装这些依赖项:
$ conda install clang clangxx compiler-rt
$ cmake .. --preset=fuzzing
回归测试文件#
当发现并修复了模糊测试器检测到的错误时,必须将相应的复现器存储在 arrow-testing 仓库中,以确保代码不会发生回归。
这些文件的位置如下:
IPC 流:位于
data/arrow-ipc-stream目录IPC 文件:位于
data/arrow-ipc-file目录Parquet 文件:位于
data/parquet/fuzzing目录CSV 文件:位于
data/csv/fuzzing目录
这些文件中的大多数对于其各自的格式来说都是无效文件,用于加压测试实现代码中的错误检测和报告功能。