美文网首页
golang - fuzz

golang - fuzz

作者: husky_1 | 来源:发表于2022-04-05 17:52 被阅读0次

从1.18 版本开始, golang 语言将模糊测试(fuzzing test)集成在其标准工具链中

概述

Fuzzing 是一种通过不断控制程序的输入来查找bug的自动化测试方法。Go 中模糊测试使用覆盖率引导来智能浏览被测试代码,发现并向用户报告错误。由于它可以达到人类经常错过的边缘情况,因此模糊测试对于发现安全漏洞和漏洞特别有价值。 下面是一个模糊测试的例子,标明了重要组成部分


图一

编写模糊测试函数

要求

  • 模糊测试函数必须是以 FuzzXxx 命名,只能接收一个 *testing.F 的参数,且没有返回值
    如图1 中 FuzzFoo函数

  • 模糊测试必须在 *_test.go 文件中运行
    和单元测试相同,必须在 *_test.go 文件中定义 执行

  • 模糊目标(图一中的fuzz target)必须是调用 (*testing.F).Fuzz 的方法,该方法接收 *testing.T 作为首个参数,紧随之后的是模糊参数(图一中的i,s 参数)。该模糊目标(f.Fuzz)没有返回值

  • 每个模糊测试中有且只有一个模糊目标

  • 所有的种子语料库中(seed corpus)的参数(图一 中add函数中的参数5,“hello” 的参数顺序和类型与下面f.Fuzz 中的i,s 相对应)必须和模糊参数类型相同、顺序一致。为了满足调用 (*testing.F).Add 函数和模糊测试 testdata/fuzz 目录下的所有文件

  • 模糊参数类型只能是如下类型:

string, []byte
int, int8, int16, int32/rune, int64
uint, uint8/byte, uint16, uint32, uint64
float32, float64
bool

下面是使用模糊测试的一些建议

  • 模糊目标应该是快速和确定的,这样模糊引擎才能有效地工作,新的故障和代码覆盖率可以很容易地重现。
  • 由于模糊目标是在多个worker以不确定的顺序并行调用的,因此模糊目标的状态不应持续到每次调用结束后,并且模糊目标的行为不应依赖于全局状态

运行模糊测试

有两种运行模糊测试的模式:作为单元测试(默认 go test),或指定模糊测试的函数(go test -fuzz=FuzzTestName)。
默认情况下,模糊测试的运行与单元测试非常相似。每个种子语料库条目都将针对模糊目标进行测试,在退出之前报告执行状况。
要启用模糊测试,请使用 -fuzz 标志运行 go test,该标志提供与单个模糊测试匹配的正则表达式。
默认情况下,该模糊测试所在的包中的其他测试将在模糊测试开始之前运行。这是为了确保模糊测试不会报告现有测试已经发现的任何问题。 请注意,由您决定模糊测试运行的时间。如果没有发现任何错误,该测试的的执行很有可能会无限期地运行。未来将支持使用 OSS-Fuzz 等工具连续运行这些模糊测试,请参阅问题 #50192[(https://github.com/golang/go/issues/50192]
注意:模糊测试应该在支持覆盖检测的平台(目前是 AMD64 和 ARM64)上运行,这样语料库可以在运行时有意义地增长,并且可以在模糊测试时覆盖更多代码。

命令行输出

在进行模糊测试时,模糊测试引擎会生成新的输入并针对提供的模糊目标运行它们。默认情况下,它会继续运行,直到找到失败的输入,或者用户取消进程(例如使用 Ctrl^C)
模糊测试输出样例如下:

~ go test -fuzz FuzzFoo
fuzz: elapsed: 0s, gathering baseline coverage: 0/192 completed
fuzz: elapsed: 0s, gathering baseline coverage: 192/192 completed, now fuzzing with 8 workers
fuzz: elapsed: 3s, execs: 325017 (108336/sec), new interesting: 11 (total: 202)
fuzz: elapsed: 6s, execs: 680218 (118402/sec), new interesting: 12 (total: 203)
fuzz: elapsed: 9s, execs: 1039901 (119895/sec), new interesting: 19 (total: 210)
fuzz: elapsed: 12s, execs: 1386684 (115594/sec), new interesting: 21 (total: 212)
PASS
ok      foo 12.692s

第一行表示在开始模糊测试之前收集了“基线覆盖率
为了收集基线覆盖率,模糊引擎同时执行种子语料库(seed corpus)和生成语料库(generated corpus),以确保没有发生错误并确认现有语料库已经提供的代码覆盖率

接下来几行提供了对主动模糊测试执行的深入了解

  • elapsed: 自模糊测试流程开始以来经过的时间
  • execs: 针对模糊目标运行的输入总数(平均执行次数/秒)
  • new interesting: 在此模糊测试执行期间添加到生成的语料库中的new interesting输入的总数(以及整个语料库的总大小)

For an input to be “interesting”, it must expand the code coverage beyond what the existing generated corpus can reach. It’s typical for the number of new interesting inputs to grow quickly at the start and eventually slow down, with occasional bursts as new branches are discovered.
You should expect to see the “new interesting” number taper off over time as the inputs in the corpus begin to cover more lines of the code, with occasional bursts if the fuzzing engine finds a new code path.

失败的输入

在模糊测试时可能因为如下的几个原因导致测试失败发生

  • 在代码或者测试中发生了panic 异常
  • 在模糊目标(fuzz target) 中调用了 t.Fail,或者直接或者间接调用发如 t.Error or t.Fatal的方法
  • 发生不可恢复的错误,例如 os.Exit 或堆栈溢出
  • 模糊目标(fuzz target)花了太长时间才能完成。目前,执行模糊目标的timeout时间为 1 秒。这可能由于死锁,无限循环或是代码中的预期行为而失败。这就是为什么建议模糊目标(fuzz target)的执行时间要快的原因之一

If an error occurs, the fuzzing engine will attempt to minimize the input to the smallest possible and most human readable value which will still produce an error. To configure this, see the custom settings section.

最小化完成后,将记录错误消息,输出将以如下内容结束

Failing input written to testdata/fuzz/FuzzFoo/a878c3134fe0404d44eb1e662e5d8d4a24beb05c3d68354903670ff65513ff49
To re-run:
go test -run=FuzzFoo/a878c3134fe0404d44eb1e662e5d8d4a24beb05c3d68354903670ff65513ff49
FAIL
exit status 1
FAIL    foo 0.839s

模糊测试引擎将此失败输入(failing input)写入该模糊测试的种子语料库,同时它将默认使用 go test 再运行`,一旦错误被修复,它将被作为回归测试处理。
下一步将是诊断问题、修复错误、通过重新运行“go test”来验证修复,并使用新的 testdata 文件作为回归测试来提交补丁

用户设置

默认的 go 命令设置应该适用于大多数模糊测试用例。所以通常,在命令行上执行模糊测试如下所示:

$ go test -fuzz={FuzzTestName}

但是,运行模糊测试时,go 命令确实提供了一些设置。这些记录在 cmd/go 软件包文档 中,如下是一些常用的用户设置设置:

  • -fuzztime:模糊目标(fuzz target)在退出前将执行的总时间或迭代次数,默认为无限期

  • -fuzzminimizetime: 在每次最小化尝试执行期间模糊目标的时间或迭代次数,默认为 60 秒。您可以在模糊测试时通过设置 -fuzzminimizetime 0 来完全禁用最小化

  • -parallel: 一次运行的模糊测试进程的数量,默认为$GOMAXPROCS。目前,在 fuzzing 期间设置 -cpu 无效

语料库文件格式

语料库文件以特殊格式编码。采用了和种子语料库(seed corpus)和生成的语料库(generated corpus) 相同的格式
如下是语料库文件的一个样例

go test fuzz v1
[]byte("hello\\xbd\\xb2=\\xbc ⌘")
int64(572293)

第一行用于告知模糊引擎文件的编码版本。虽然目前没有计划未来版本的编码格式,但设计必须支持这种可能性,当前版本为v1。 下面的每一行都是构成语料库条目的值,如果需要,可以直接复制到 Go 代码中。 在上面的示例中,我们有[]byteint64。这些类型必须按顺序与模糊测试参数完全匹配。这些类型的模糊目标如下所示:

f.Fuzz(func(*testing.T, []byte, int64) {})

指定您自己的种子语料库值的最简单方法是使用 (*testing.F).Add 方法。如下所示:

f.Add([]byte("hello\\xbd\\xb2=\\xbc ⌘"), int64(572293))

然而,我们可能不想将大型二进制文件作为代码复制到测试中,而是作为单独的种子语料库条目保留在 testdata/fuzz/{FuzzTestName} 目录中。 golang.org/x/tools/cmd/file2fuzz 上的 file2fuzz 工具可用于转换这些二进制文件到为 []byte 编码的语料库文件。
通过如下命令安装

$ go install golang.org/x/tools/cmd/file2fuzz@latest
$ file2fuzz

术语

  • corpus entry: 语料库中的一个输入,可以在模糊测试时使用。这可以是特殊格式的文件(Corpus file),也可以是通过 [(*testing.F).Add](https://pkg.go.dev/testing#F.Add) 函数调用

  • coverage guidance: 一种模糊测试方法,它使用代码覆盖率的扩展来确定哪些语料库条目值得保留以备将来使用。

  • failing input: 是针对 fuzz target 运行时会导致错误或panic 异常的失败的熟料库输入
  • fuzz target: 模糊测试的函数,用来在模糊测试时执行语料库条目和生成对应的值。它通过向(*testing.F).Fuzz传递函数来提供给模糊测试

  • fuzz test: 测试文件中用于模糊处理的一个函数,其形式为func FuzzXxx(*testing.F)

  • fuzzing: 一种自动测试,它不断地操纵程序的输入,以发现代码潜在问题,如错误或漏洞

  • fuzzing arguments: 传递给模糊目标的类型,并由mutator进行变异处理

  • fuzzing engine: 一个管理模糊处理的工具,包括维护语料库、调用突变器、识别新的覆盖范围和报告错误

  • generated corpus: 一个语料库,它由模糊引擎在模糊处理过程中长期维护,以跟踪进展。它被保存在$GOCACHE/fuzz中

  • mutator: 一个在模糊处理时使用的工具,在将语料库条目传递给模糊处理目标之前,对其进行随机处理

  • seed corpus: 用户为模糊测试提供的语料库,可用于指导模糊测试引擎。它由模糊测试中f.Add调用添加的语料库条目,以及软件包中testdata/fuzz/{FuzzTestName}目录下的文件组成

  • test file: 一个格式为 xxx_test.go 的文件,可以包含测试、基准、例子和模糊测试

  • vulnerability: 一种代码中安全敏感的弱点,可被攻击者所利用

上述内容翻译自 https://go.dev/doc/fuzz/#glos-fuzz-test

教程

本教程介绍了 Go 中模糊测试的基础知识。通过模糊测试,随机数据会针对您的测试运行,以尝试找出漏洞或导致崩溃异常的输入。可以通过模糊测试发现的一些漏洞示例包括 SQL 注入、缓冲区溢出、拒绝服务和跨站点脚本攻击。 在本教程中,您将为一个简单的函数编写一个模糊测试,运行 go 命令,并调试和修复代码中的问题。

1. 创建模糊测试目录

创建一个fuzz 的文件夹

 $ mkdir fuzz
 $ cd fuzz

在fuzz 目录下 创建一个go mudule 项目,

  $ go mod init example/fuzz
  go: creating new go.mod: module example/fuzz

2. 编写代码

编写一个用于翻转字符串功能的函数

func Reverse(s string) string {
    b := []byte(s)
    for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
        b[i], b[j] = b[j], b[i]
    }
    return string(b)
}

此函数将接受一个字符串,一次循环一个字节,并在最后返回反转的字符串。 注意:此代码基于 golang.org/x/example 中的 stringutil.Reverse 函数。 在main函数中调用该函数

func main() {
   input := "The quick brown fox jumped over the lazy dog"
   rev := Reverse(input)
   doubleRev := Reverse(rev)
   fmt.Printf("original: %q\n", input)
   fmt.Printf("reversed: %q\n", rev)
   fmt.Printf("reversed again: %q\n", doubleRev)
}

运行代码如下

$ go run .
original: "The quick brown fox jumped over the lazy dog"
reversed: "god yzal eht revo depmuj xof nworb kciuq ehT"
reversed again: "The quick brown fox jumped over the lazy dog"

3. 添加单元测试

在fuzz 目录中添加reverse_test.go 文件,作为测试文件,并添加单元测试代码如下

package main

import (
    "testing"
)

func TestReverse(t *testing.T) {
    testcases := []struct {
        in, want string
    }{
        {"Hello, world", "dlrow ,olleH"},
        {" ", " "},
        {"!12345", "54321!"},
    }
    for _, tc := range testcases {
        rev := Reverse(tc.in)
        if rev != tc.want {
                t.Errorf("Reverse: %q, want %q", rev, tc.want)
        }
    }
}

这个简单的测试将断言列出的输入字符串是否被正确反转
运行单元测试 如下所示:

$ go test
PASS
ok      example/fuzz  0.013s

4. 添加模糊测试

单元测试是有局限性的,即每个输入都必须由开发人员添加到测试中。模糊测试的一个好处是它可以为你的代码提供输入,并且可以识别你想出的测试用例没有达到的边缘用例。 在本节中,您将单元测试转换为模糊测试,这样您就可以用更少的工作生成更多的输入! 请注意,您可以将单元测试、基准测试和模糊测试保存在同一个 *_test.go 文件中,但对于本示例,将对单元测试转换为模糊测试。 代码如下:

func FuzzReverse(f *testing.F) {
    testcases := []string{"Hello, world", " ", "!12345"}
    for _, tc := range testcases {
        f.Add(tc)  // Use f.Add to provide a seed corpus
    }
    f.Fuzz(func(t *testing.T, orig string) {
        rev := Reverse(orig)
        doubleRev := Reverse(rev)
        if orig != doubleRev {
            t.Errorf("Before: %q, after: %q", orig, doubleRev)
        }
        if utf8.ValidString(orig) && !utf8.ValidString(rev) {
            t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
        }
    })
}

模糊测试(Fuzzing) 也有一些限制。在您的单元测试中,您可以预测 Reverse 函数的预期输出,并验证实际输出是否满足这些预期
例如,在测试用例 Reverse("Hello, world") 中,单元测试将返回指定为“dlrow ,olleH”。

但是在模糊测试时,无法预测预期输出,因为无法控制输入。 但是,可以在模糊测试中验证 Reverse 函数的一些属性。在上面的模糊测试中检查的两个属性是: 1.将字符串反转两次看是否和原始值一致; 2.反转的字符串是否任然为有效的 UTF-8格式。

注意单元测试和模糊测试之间的语法差异:

  • 该函数以 FuzzXxx 而不是 TestXxx 开头,并采用 *testing.F 而不是 *testing.T
  • 在您希望看到 t.Run 执行的地方, 由f.Fuzz代替,它接受一个模糊目标函数,其参数是 *testing.T 和模糊类型(orig string)。单元测试的输入对应使用 f.Add 作为种子语料库作为输入提供给模糊测试。

运行代码:
1.在不进行模糊测试的情况下运行模糊测试,以确保种子输入通过测试。

$ go test
PASS
ok      example/fuzz  0.013s

如果在测试文件中有其他测试,并且只想运行指定的模糊测试,可以运行 go test -run={fuzFuncName},
其中fuzFuncName 就是填写模糊测试函数名称

2.使用 模糊测试运行 FuzzReverse,查看是否有任何随机生成的字符串输入会导致失败。通过标志-fuzz=模糊测试的函数名来指定模糊测试,如下所示

go test -fuzz=FuzzReverse
fuzz: elapsed: 0s, gathering baseline coverage: 0/3 completed
fuzz: elapsed: 0s, gathering baseline coverage: 3/3 completed, now fuzzing with 8 workers
fuzz: minimizing 38-byte failing input file...
--- FAIL: FuzzReverse (0.01s)
    --- FAIL: FuzzReverse (0.00s)
        reverse_test.go:20: Reverse produced invalid UTF-8 string "\x9c\xdd"

    Failing input written to testdata/fuzz/FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217a
    To re-run:
    go test -run=FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217a
FAIL
exit status 1
FAIL    example/fuzz  0.030s

如上所示,在模糊测试时发生失败,导致问题的输入会被写入种子语料库文件,该文件将在下次调用 go test 时运行,即使没有 -fuzz 标志。要查看导致失败的输入,请在文本编辑器中打开写入 testdata/fuzz/FuzzReverse 目录的语料库文件。您的种子语料库文件可能包含不同的字符串,但格式是相同的。
A failure occurred while fuzzing, and the input that caused the problem is written to a seed corpus file that will be run the next time go test is called, even without the -fuzz flag. To view the input that caused the failure, open the corpus file written to the testdata/fuzz/FuzzReverse directory in a text editor. Your seed corpus file may contain a different string, but the format will be the same.

  1. 在没有 -fuzz 标志的情况下再次运行 go test,测试模糊测试还是失败
$ go test
--- FAIL: FuzzReverse (0.00s)
    --- FAIL: FuzzReverse/af69258a12129d6cbba438df5d5f25ba0ec050461c116f777e77ea7c9a0d217a (0.00s)
        reverse_test.go:20: Reverse produced invalid string
FAIL
exit status 1
FAIL    example/fuzz  0.016s

5. 修复发现的bug

在本节中,我们将调试故障并修复错误。

5.1 诊断错误

有几种不同的方法可以调试此错误。如果是使用 VS Code 作为文本编辑器的,则可以设置调试器 进行调查。 在本教程中,我们会将有用的调试信息记录到您的终端。 首先,考虑 utf8.ValidString 的文档。 ValidString 报告字符串 s 是否完全由有效的 UTF-8 编码符文组成。 当前的“Reverse”函数逐字节反转字符串,这就是我们的问题所在。为了保留原始字符串的 UTF-8 编码符文,我们必须逐个符文反转字符串。 要检查输入(在本例中为汉字 )导致 Reverse 在反转时产生无效字符串的原因,您可以检查反转字符串中的符文数。
在原先的代码的基础上,添加了t.logf的调试信息,方便更快的找到bug

f.Fuzz(func(t *testing.T, orig string) {
    rev := Reverse(orig)
    doubleRev := Reverse(rev)
    t.Logf("Number of runes: orig=%d, rev=%d, doubleRev=%d", utf8.RuneCountInString(orig), utf8.RuneCountInString(rev), utf8.RuneCountInString(doubleRev))
    if orig != doubleRev {
        t.Errorf("Before: %q, after: %q", orig, doubleRev)
    }
    if utf8.ValidString(orig) && !utf8.ValidString(rev) {
        t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
    }
})

运行结果如下

$ go test
--- FAIL: FuzzReverse (0.00s)
    --- FAIL: FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0 (0.00s)
        reverse_test.go:16: Number of runes: orig=1, rev=3, doubleRev=1
        reverse_test.go:21: Reverse produced invalid UTF-8 string "\x83\xb3\xe6"
FAIL
exit status 1
FAIL    example/fuzz    0.598s

bug 的原因:整个种子语料库使用字符串,其中每个字符都是一个字节。但是,泃等汉字字符可能需要几个字节。因此,逐字节反转字符串将使多字节字符无效

5.2 bug 修复

了更正 Reverse 函数,我们通过只要符文(rune)而不是字节来遍历字符串,代码如下:

func Reverse(s string) string {
  r := []rune(s)
  for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
      r[i], r[j] = r[j], r[i]
  }
  return string(r)
}

关键区别在于 Reverse 现在遍历字符串中的每个符文,而不是每个字节。
再次进行测试,此时测试通过

$ go test
PASS
ok      example/fuzz  0.016s

使用 go test -fuzz 再次对其进行模糊测试,看看是否有任何新的错误

$ go test -fuzz=Fuzz
fuzz: elapsed: 0s, gathering baseline coverage: 0/37 completed
fuzz: minimizing 506-byte failing input file...
fuzz: elapsed: 0s, gathering baseline coverage: 5/37 completed
--- FAIL: FuzzReverse (0.02s)
    --- FAIL: FuzzReverse (0.00s)
        reverse_test.go:33: Before: "\x91", after: "�"

    Failing input written to testdata/fuzz/FuzzReverse/1ffc28f7538e29d79fce69fef20ce5ea72648529a9ca10bea392bcff28cd015c
    To re-run:
    go test -run=FuzzReverse/1ffc28f7538e29d79fce69fef20ce5ea72648529a9ca10bea392bcff28cd015c
FAIL
exit status 1
FAIL    example/fuzz  0.032s

我们可以看到,经过两次反转后,字符串与原始字符串不同。这次是输入本身无效的 unicode,导致最终反转函数的错误。

在 Go 中,字符串是只读的字节切片,并且可以包含无效的 UTF-8\ 字节。原始字符串是一个带有一个字节的字节切片,'\x91'。当输入字符串设置为 []rune 时,Go 将字节切片编码为 UTF-8,并将字节替换为 UTF-8 字符 �。当我们将替换的 UTF-8 字符与输入字节切片进行比较时,它们显然不相等。

为了调试,在修改reserve 函数如下所示: 增加了原始字符串和转换为[]rune后的输出,来确认string转换 []rune时发生了什么

  func Reverse(s string) string {
        fmt.Printf("input: %q\n", s)
        r := []rune(s)
        fmt.Printf("runes: %q\n", r)
        for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
            r[i], r[j] = r[j], r[i]
        }
        return string(r)
    }

这一次,我们只想运行失败的测试来检查日志。为此,我们将使用``go test -run,要在 FuzzXxx/testdata 中运行特定的语料库条目,您可以将 {FuzzTestName}/{filename} 提供给-run。如下所示

$ go test -run=FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0
input: "\x91"
runes: ['�']
input: "�"
runes: ['�']
--- FAIL: FuzzReverse (0.00s)
    --- FAIL: FuzzReverse/28f36ef487f23e6c7a81ebdaa9feffe2f2b02b4cddaa6252e87f69863046a5e0 (0.00s)
        reverse_test.go:16: Number of runes: orig=1, rev=1, doubleRev=1
        reverse_test.go:18: Before: "\x91", after: "�"
FAIL
exit status 1
FAIL    example/fuzz    0.145s

为了解决上述因为无聊的utf-8 输入导致的bug, 修改代码如下来解决bug:添加了输入string 的utf-8 的校验,如果校验失败,返回错误
```
func Reverse(s string) (string, error) {
if !utf8.ValidString(s) {
return s, errors.New("input is not valid UTF-8")
}
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r), nil
}

```

此时因为函数多了个error 的返回值,修改main 函数代码如下

```
func main() {
    input := "The quick brown fox jumped over the lazy dog"
    rev, revErr := Reverse(input)
    doubleRev, doubleRevErr := Reverse(rev)
    fmt.Printf("original: %q\n", input)
    fmt.Printf("reversed: %q, err: %v\n", rev, revErr)
    fmt.Printf("reversed again: %q, err: %v\n", doubleRev, doubleRevErr)
}

```

最后,修改模糊测试代码如下,可以看到,对于Reverse 直接返回的由于非法输入导致的错误,直接return,当然我们也可以 调用t.Skip()来跳过当前的非法输入,继续下一次输入
```
func FuzzReverse(f *testing.F) {
testcases := []string {"Hello, world", " ", "!12345"}
for _, tc := range testcases {
f.Add(tc) // Use f.Add to provide a seed corpus
}
f.Fuzz(func(t *testing.T, orig string) {
rev, err1 := Reverse(orig)
if err1 != nil {
return
}
doubleRev, err2 := Reverse(rev)
if err2 != nil {
return
}
if orig != doubleRev {
t.Errorf("Before: %q, after: %q", orig, doubleRev)
}
if utf8.ValidString(orig) && !utf8.ValidString(rev) {
t.Errorf("Reverse produced invalid UTF-8 string %q", rev)
}
})
}

```

完成修改后,此时再进行测试

Run the code

  1. Run the test using go test
  $ go test
  PASS
  ok      example/fuzz  0.019s

// 由于没有设置模糊测试时间,会一直进行下去,我们可以测试若干时间后,手动停止`ctrl-C`.
$ go test -fuzz=fuzzReserve
  fuzz: elapsed: 0s, gathering baseline coverage: 0/38 completed
  fuzz: elapsed: 0s, gathering baseline coverage: 38/38 completed, now fuzzing with 4 workers
  fuzz: elapsed: 3s, execs: 86342 (28778/sec), new interesting: 2 (total: 35)
  fuzz: elapsed: 6s, execs: 193490 (35714/sec), new interesting: 4 (total: 37)
  fuzz: elapsed: 9s, execs: 304390 (36961/sec), new interesting: 4 (total: 37)
  ...
  fuzz: elapsed: 3m45s, execs: 7246222 (32357/sec), new interesting: 8 (total: 41)
  ^Cfuzz: elapsed: 3m48s, execs: 7335316 (31648/sec), new interesting: 8 (total: 41)
  PASS
  ok      example/fuzz  228.000s

当然我们也可是自定义设置模糊测试时间, 通过-fuzztime 参数实现,具体如下:

 $ go test -fuzz=Fuzz -fuzztime 30s
 fuzz: elapsed: 0s, gathering baseline coverage: 0/5 completed
 fuzz: elapsed: 0s, gathering baseline coverage: 5/5 completed, now fuzzing with 4 workers
 fuzz: elapsed: 3s, execs: 80290 (26763/sec), new interesting: 12 (total: 12)
 fuzz: elapsed: 6s, execs: 210803 (43501/sec), new interesting: 14 (total: 14)
 fuzz: elapsed: 9s, execs: 292882 (27360/sec), new interesting: 14 (total: 14)
 fuzz: elapsed: 12s, execs: 371872 (26329/sec), new interesting: 14 (total: 14)
 fuzz: elapsed: 15s, execs: 517169 (48433/sec), new interesting: 15 (total: 15)
 fuzz: elapsed: 18s, execs: 663276 (48699/sec), new interesting: 15 (total: 15)
 fuzz: elapsed: 21s, execs: 771698 (36143/sec), new interesting: 15 (total: 15)
 fuzz: elapsed: 24s, execs: 924768 (50990/sec), new interesting: 16 (total: 16)
 fuzz: elapsed: 27s, execs: 1082025 (52427/sec), new interesting: 17 (total: 17)
 fuzz: elapsed: 30s, execs: 1172817 (30281/sec), new interesting: 17 (total: 17)
 fuzz: elapsed: 31s, execs: 1172817 (0/sec), new interesting: 17 (total: 17)
 PASS
 ok      example/fuzz  31.025s

参考翻译:https://go.dev/doc/tutorial/fuzz

相关文章

  • golang - fuzz

    从1.18 版本开始, golang 语言将模糊测试(fuzzing test)集成在其标准工具链中 概述 Fuz...

  • 8.5 Fuzz

    8.5.1. Web Fuzz wfuzz SecLists fuzzdb foospidy payloads 8...

  • Fuzz A Program!

    什么是Fuzz? 嘛这篇blog 还是会是一篇和计算机相关的Blog, 希望有机会我也能写一些和上面图里的Fuzz...

  • AFL测试过程中出现“last new path : none

    在对源码进行重新编译之后,使用如下命令用AFL对其进行fuzz: 其中,fuzz_in为输入数据所在文件夹,@@表...

  • 内核fuzz技术系列——trinity

    这是内核fuzz技术系列的第一篇。 前言 提到linux内核fuzz目前最流行的工具是syzkaller,不过在s...

  • AFL Fuzz安装及完成一次简单的模糊测试

    关于AFL fuzz AFL fuzz是一个模糊测试工具,它封装了一个GCC/CLang编译器,用于对被测代码重新...

  • Test404 -HTTP Fuzzer V3.6【 附50个插

    HTTP Fuzzer是一款为了评估WEB应用而生的Fuzz(Fuzz是爆破的一种手段)工具,它基于一个简单的理念...

  • kernel netlink

    kernel netlink so we can use netlink fuzz general, rout, ...

  • P-Fuzz: A Parallel Grey-Box Fuzz

    最近在看Fuzz相关的文章,然后读到这篇并行化的论文。建议先阅读FUZZ和AFL的相关基础再进行阅读会觉得很容易理...

  • 计算机英语

    penetration 渗透 fuzz 模糊 parameter 参数 valid 有效的 variable 变量...

网友评论

      本文标题:golang - fuzz

      本文链接:https://www.haomeiwen.com/subject/htukjrtx.html