:::info 日期:2021 年 06 月 03 日
作者:Katie Hockman and Jay Conrod
原文链接:https://go.dev/blog/fuzz-beta :::

我们很高兴地宣布,原生模糊测试已准备好在其开发分支 dev.fuzz 中进行 Beta 测试!

Fuzzing 是一种自动化测试,它不断地操纵程序的输入以发现诸如恐慌或错误之类的问题。 这些半随机数据突变可以发现现有单元测试可能遗漏的新代码覆盖率,并发现否则会被忽视的边缘情况错误。 由于模糊测试可以达到这些边缘情况,因此模糊测试对于发现安全漏洞和漏洞特别有价值。

有关此功能的更多详细信息,请参阅 golang.org/s/draft-fuzzing-design

准备开始

首先,您可以运行以下命令

  1. $ go get golang.org/dl/gotip
  2. $ gotip download dev.fuzz

这从 dev.fuzz 开发分支构建了 Go 工具链,将来一旦代码合并到 master 分支就不需要了。 运行后,gotip 可以作为 go 命令的替代品。 您现在可以运行以下命令

  1. $ gotip test -fuzz=FuzzFoo

dev.fuzz 分支中将有持续的开发和错误修复,因此您应该定期运行 gotip download dev.fuzz 以使用最新代码。

为了与 Go 的已发布版本兼容,请在将包含 fuzz 目标的源文件提交到存储库时使用 gofuzzbeta 构建标记。 默认情况下,在 dev.fuzz 分支中的构建时启用此标记。 如果您对如何使用它们有疑问,请参阅有关构建标记的 go 命令文档

  1. // +build gofuzzbeta

写一个模糊的目标

模糊目标必须在 _test.go 文件中作为 FuzzXxx 形式的函数。 该函数必须传递一个 testing.F 参数,就像传递给 TestXxx 函数的 *testing.T 参数一样。
下面是一个测试 net/url 包行为的模糊目标示例。

  1. // +build gofuzzbeta
  2. package fuzz
  3. import (
  4. "net/url"
  5. "reflect"
  6. "testing"
  7. )
  8. func FuzzParseQuery(f *testing.F) {
  9. f.Add("x=1&y=2")
  10. f.Fuzz(func(t *testing.T, queryStr string) {
  11. query, err := url.ParseQuery(queryStr)
  12. if err != nil {
  13. t.Skip()
  14. }
  15. queryStr2 := query.Encode()
  16. query2, err := url.ParseQuery(queryStr2)
  17. if err != nil {
  18. t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err)
  19. }
  20. if !reflect.DeepEqual(query, query2) {
  21. t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2)
  22. }
  23. })
  24. }

你可以通过 go doc 阅读更多关于 fuzzing API 的信息

  1. gotip doc testing
  2. gotip doc testing.F
  3. gotip doc testing.F.Add
  4. gotip doc testing.F.Fuzz

期望

这是开发分支中的 beta 版本,因此您应该会遇到一些错误和不完整的功能集。 检查问题跟踪器是否存在标记为“模糊”的问题,以了解现有错误和缺失功能的最新情况。

请注意,模糊测试会消耗大量内存,并且可能会影响机器运行时的性能。 go test -fuzz 默认在 $GOMAXPROCS 进程中并行运行模糊测试。 您可以通过使用 go test 显式设置 -parallel 标志来减少模糊测试时使用的进程数。 如果需要更多信息,请通过运行 gotip help testflag 阅读 go test 命令的文档。

另请注意,模糊引擎在运行时会将扩展测试覆盖范围的值写入 $GOCACHE/fuzz 中的模糊缓存目录。 目前对可以写入模糊缓存的文件数量或总字节数没有限制,因此它可能会占用大量存储空间(即几 GB)。 您可以通过运行 gotip clean -fuzzcache 来清除模糊缓存。

下一步?

此功能在即将发布的 Go 版本 (1.17) 中将不可用,但计划在未来的 Go 版本中实现。 我们希望这个工作原型将允许 Go 开发人员开始编写模糊目标并提供有关设计的有用反馈,为合并到 master 做准备。

如果您遇到任何问题或对功能请求有想法,请提出问题

有关该功能的讨论和一般反馈,您还可以参与 Gophers Slack 中的 #fuzzing 频道

快乐模糊!