如何为 TensorFlow 编写 Python Fuzzing 测试
2021 年 4 月 1 日

作者:Laura Pak

TensorFlow Python Fuzzer graphic

Fuzzing 测试是一种使用生成数据测试 API 的过程。Fuzzing 确保代码在负面路径上不会崩溃,它会生成随机输入来尝试覆盖代码的每个分支。一种流行的选择是将 fuzzer 与 sanitizer 配合使用,sanitizer 是用于检查非法条件并因此标记由 fuzzer 输入触发的错误的工具。

这样,fuzzing 可以发现

  • 缓冲区溢出
  • 内存泄漏
  • 死锁
  • 无限递归
  • 往返一致性失败
  • 未捕获的异常
  • 等等。

最佳的 fuzzing 方法是让 fuzzing 测试持续运行。测试运行得越多,就能生成和测试的输入就越多。在这篇文章中,您将学习如何将 Python fuzzer 添加到 TensorFlow。

技术上的操作方法

TensorFlow Python fuzzer 通过 OSS-Fuzz 运行,OSS-Fuzz 是一个针对开源项目的持续 fuzzing 服务。

对于 Python fuzzer,OSS-Fuzz 使用 Atheris,这是一个覆盖率引导的 Python fuzzing 引擎。Atheris 基于 fuzzing 引擎 libFuzzer,它可以与动态内存错误检测器 Address Sanitizer 或快速未定义行为检测器 Undefined Behavior Sanitizer 一起使用。Atheris 依赖项将预安装在 OSS-Fuzz 基础 Docker 镜像上。

这是一个 TF 的 Python fuzzer 的基本示例。运行时将使用不同的随机数据调用 TestCode

import sys
import atheris_no_libfuzzer as atheris

def TestCode(data):
  DoSomethingWith(data)

def main():
  atheris.Setup(sys.argv, TestCode, enable_python_coverage=True)
  atheris.Fuzz()

tensorflow 仓库 中,在与其他 fuzzer 相同的 目录 中,添加您自己的 Python fuzzer,如上所示。在 TestCode 中,选择您要 fuzz 的 TensorFlow API。在 constant_fuzz.py 中,该 API 是 tf.constant。该 fuzzer 只是将数据传递给选定的 API,以查看它是否会崩溃。无需编写捕获崩溃的代码;OSS-Fuzz 会检测并报告错误。

有时 API 需要比单个输入更结构化的数据。TensorFlow 有一个名为 FuzzingHelper 的 Python 类,它允许您生成随机整数列表、随机布尔值等。在 sparseCountSparseOutput_fuzz.py 中查看其使用的示例,这是一个检查 API tf.raw_ops.SparseCountSparseOutput 中未捕获异常的 fuzzer。

要构建和运行,您的 fuzzer 需要一个类型为 tf_py_fuzz_target 的 fuzzing 目标,该目标在 tf_fuzzing.bzl 中定义。以下是一个示例 fuzzing 目标,此处有更多示例

tf_py_fuzz_target(
    name = "fuzz_target_name",
    srcs = ["your_fuzzer.py"],
    tags = ["notap"],  # Important: include to run in OSS.
)

使用 Docker 测试您的 fuzzer

确保您的 fuzzer 在 OSS-Fuzz 中使用 Docker 构建。

首先 安装 Docker。在您的终端中,运行命令 docker image prune 来删除任何悬空镜像。

从 Github 克隆 oss-fuzz。用于 Python TF fuzzer 的项目,tensorflow-py,包含一个要执行在 Dockerfile 中定义的 Docker 容器中的 build.sh 文件。Build.sh 定义了如何在 tensorflow-py 中为 fuzzing 目标构建二进制文件。具体来说,它会构建在 $SRC/tensorflow/tensorflow 中找到的所有 Python fuzzer,包括您的新 fuzzer!

oss-fuzz 中,运行以下命令

python infra/helper.py shell tensorflow
export FUZZING_LANGUAGE=python
compile

命令 compile 将运行 build.sh,它将尝试构建您的新 fuzzer。

结果

您的 fuzzer 启动并运行后,您可以在此 仪表板 中搜索您的 fuzzer,以查看您的 fuzzer 发现了哪些漏洞。

结论

Fuzzing 是一种从负面路径测试软件的激动人心的方法。无论您是想涉足安全领域,还是想要更深入地了解 TensorFlow 的内部机制,我们都希望这篇文章能为您提供一个良好的起点。

下一篇文章
How-to Write a Python Fuzzer for TensorFlow

作者:Laura Pak Fuzzing 测试是一种使用生成数据测试 API 的过程。Fuzzing 确保代码在负面路径上不会崩溃,它会生成随机输入来尝试覆盖代码的每个分支。一种流行的选择是将 fuzzer 与 sanitizer 配合使用,sanitizer 是用于检查非法条件并因此标记由 fuzzer 输入触发的错误的工具。这样,fuzzing 可以…