网站首页 > 技术文章 正文
在golang 1.18中,新增了模糊测试特性fuzzing。 模糊测试(fuzz testing, fuzzing)是一种软件测试技术, 模糊测试是一种自动测试,它不断地操纵程序的输入来发现错误。Go fuzzing使用覆盖率指导来智能地遍历被模糊处理的代码,以发现bug并向用户报告BUG。由于模糊测试可以触及人类经常错过的边缘情况,因此它对于发现安全漏洞和漏洞尤其有价值。 下面是一个模糊测试的例子,突出显示了它的主要组件。
以下是模糊测试必须遵循的规则:
- 模糊测试必须是一个名为FuzzXxx的函数,它只接受一个*testing.F、 并且没有返回值。
- 模糊测试必须在*_test.go文件中才能运行。
- 模糊目标必须是对(*testing.F)的方法调用。接受测试的引信。T作为第一个参数,然后是模糊参数。没有返回值。
- 每个模糊测试必须只有一个模糊目标。
- 所有种子语料库条目的类型都必须具有与模糊参数相同的类型,顺序相同。对 (*testing.F).Add的调用也是如此。fuzz测试的testdata/fuzz目录中的任何语料库文件。
- 模糊参数只支持以下类型:
- string, []byte
- int, int8, int16, int32/rune, int64
- uint, uint8/byte, uint16, uint32, uint64
- float32, float64
- bool
如何使用Fuzzing
1、创建一个main.go 内容为
package main
import (
"fmt"
)
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)
}
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)
}
2、写一个单元测试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 -v
=== RUN TestReverse
--- PASS: TestReverse (0.00s)
PASS
ok demo 0.030s
接下来,您将把单元测试更改为模糊测试。
3、添加模糊测试
单元测试有局限性,即每个输入都必须由开发人员添加到测试中。模糊化的一个好处就是,它为代码提供了输入,并可能识别出您提出的测试用例没有达到的边缘用例。 在本节中,将把单元测试转换为模糊测试,这样就可以用更少的工作生成更多的输入! 请注意,您可以将单元测试、基准测试和模糊测试保存在同一个*_test.go文件中,但在本例中,您将把单元测试转换为模糊测试。
将reverse_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)
}
})
}
执行模糊测试
$ go test -v -fuzz=Fuzz -fuzztime 10s
=== RUN FuzzReverse
fuzz: elapsed: 0s, gathering baseline coverage: 0/13 completed
failure while testing seed corpus entry: FuzzReverse/31d6dcd7535b857a
fuzz: elapsed: 0s, gathering baseline coverage: 3/13 completed
--- FAIL: FuzzReverse (0.12s)
--- FAIL: FuzzReverse (0.00s)
reverse_test.go:20: Reverse produced invalid UTF-8 string "\xb3\xb3\xef"
=== NAME
FAIL
exit status 1
FAIL demo 0.149s
另一个有用的选项是-fuzztime,它限制了模糊处理所花费的时间。例如,在下面的测试中指定-fuzztime 10s意味着,只要之前没有发生故障,测试将在10秒后默认退出。-fuzz 选项,指执行正则表达式匹配到的测试函数。请参阅cmd/go文档的这一部分,以查看其他测试选项。
注意
- 模糊测试会消耗大量内存,并且可能会影响机器运行时的性能。另请注意,模糊引擎在运行时会将扩展测试覆盖率的值写入模糊缓存目录 $GOCACHE/fuzz。目前对可以写入模糊缓存的文件数量或总字节数没有限制,因此可能会占用大量存储空间(可能为数 GB)。
- 模糊化也有一些局限性。在单元测试中,您可以预测Reverse函数的预期输出,并验证实际输出是否满足这些期望。 例如,在测试用例Reverse(“Hello,world”)中,单元测试将返回指定为“dlrow,olleH”。 当进行模糊处理时,您无法预测预期的输出,因为您无法控制输入。
links
https://go.dev/doc/security/fuzz/
https://go.dev/doc/tutorial/fuzz
https://blog.jetbrains.com/go/2022/12/14/understanding-fuzz-testing-in-go/
猜你喜欢
- 2024-11-02 武汉课工场大数据培训:Java正则表达式入坑指南
- 2024-11-02 Go语言进阶之路:并发爬虫,爬取空姐网所有相册图片
- 2024-11-02 golang常用库:gorilla/mux-http路由库使用
- 2024-11-02 golang 使用pprof和go-torch做性能分析
- 2024-11-02 Golang Gin 入门 (一)(golang官方教程)
- 2024-11-02 日志文件转运工具Filebeat笔记(日志转载)
- 2024-11-02 Linux 命令行下搜索工具大盘点,效率提高不止一倍
- 2024-11-02 SlimTrie:战胜Btree单机百亿文件的极致索引-实现篇
- 2024-11-02 Go的安全编程和防御性编程(输入验证和过滤)
- 2024-11-02 清华学神尹成带你学习golang2021(56)(Go语言测试命令)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)