thepudds/fzgo

GitHub: thepudds/fzgo

fzgo 是一个将 go-fuzz 模糊测试能力集成到 go test 命令中的原型工具,旨在推动 fuzzing 成为 Go 语言一等公民的测试方式。

Stars: 115 | Forks: 4

[![Build Status](https://travis-ci.org/thepudds/fzgo.svg?branch=master)](https://travis-ci.org/thepudds/fzgo) [![Go Report Card](https://goreportcard.com/badge/github.com/thepudds/fzgo)](https://goreportcard.com/report/github.com/thepudds/fzgo) ## fzgo: go-fuzz + 'go test' = 更少的 bug 如果您对 fuzzing 还不熟悉,这份[动机](http://tiny.cc/why-go-fuzz)文档提供了一页简短的介绍。 `fzgo` 是 [golang/go#19109](https://golang.org/issue/19109) **"cmd/go: 让 fuzzing 成为像测试或基准测试一样的一等公民"** 的一个原型。 `fzgo` 支持一些便捷功能,例如对丰富签名的 fuzzing 以及自动生成 fuzzing 函数。 基本方法是 `fzgo` 将 [dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz) 集成到 `go test` 中,繁重的工作由 `go-fuzz`、`go-fuzz-build` 和 `go` 工具完成。重点 是 [#19109](https://golang.org/issue/19109) 上[这条评论](https://github.com/golang/go/issues/19109#issuecomment-441442080)中列出的“原型的草案目标”暂定清单中的第 1 步: _第 1 步。为提议的 CLI 建立原型,包括与现有 'go test' 的交互。_ `fzgo` 支持 `-fuzz` 标志以及 2017 年 3 月 [#19109 提案文档](https://github.com/golang/go/issues/19109#issuecomment-285456008)中提议的几个其他相关标志。`fzgo` 还支持典型的 `go` 命令, 例如 `fzgo build`、`fzgo test` 或 `fzgo env`(它们是通过封装 `go` 工具来实现的)。 欢迎任何和所有的反馈! ### 功能 * 支持像 `FuzzRegexp(re string, input []byte, posix bool)` 这样的丰富签名,也支持 `go-fuzz` 使用的经典 `Fuzz(data []byte) int` 形式。 * 在运行普通的 `go test` 时,语料库会自动用作单元测试的确定性输入。 * 可以通过 `fzgo test -fuzz=. -run=TestCorpus/` 对单个语料库文件进行单元测试。 * `go-fuzz` 需要两个步骤的过程。`fzgo` 省去了单独的手动准备步骤。 * `fzgo` 自动将检测过的二进制文件缓存在 `GOPATH/pkg/fuzz` 中,并尽可能重用它们。 * fuzzing 语料库默认为 `GOPATH/pkg/fuzz/corpus`。 * `-fuzzdir=/some/path` 标志允许将语料库存储在其他地方(例如,单独的语料库仓库);`-fuzzdir=testdata` 将语料库存储在 `/testdata/fuzz/fuzzname` 下(因此通常与被测代码一起在 VCS 中)。 * 允许使用 `fuzz` 和 `gofuzz` 构建标签,但这并不是必须的。 * 一个可选的 [genfuzzfuncs](https://github.com/thepudds/fzgo/blob/master/genfuzzfuncs/README.md) 实用程序可以自动为您感兴趣的包中的所有公共函数和方法创建 fuzzing 函数。这使得开始 fuzzing 变得更快捷、更容易。 ## 用法 ``` Usage: fzgo test [build/test flags] [packages] [build/test flags] Examples: fzgo test # normal 'go test' of current package, plus run any corpus as unit tests fzgo test -fuzz=. # fuzz the current package with a function starting with 'Fuzz' fzgo test -fuzz=FuzzFoo # fuzz the current package with a function matching 'FuzzFoo' fzgo test ./... -fuzz=FuzzFoo # fuzz a package in ./... with a function matching 'FuzzFoo' fzgo test sample/pkg -fuzz=FuzzFoo # fuzz 'sample/pkg' with a function matching 'FuzzFoo' Rich signatures like Fuzz(re string, input []byte, posix bool)` are supported, as well Fuzz(data []byte) int. Fuzz functions must start with 'Fuzz'. The following flags work with 'fzgo test -fuzz': -fuzz regexp fuzz at most one function matching regexp -fuzzdir dir store fuzz artifacts in dir (default pkgpath/testdata/fuzz) -fuzztime d fuzz for duration d (default unlimited) -parallel n start n fuzzing operations (default GOMAXPROCS) -timeout d fail an individual call to a fuzz function after duration d (default 10s, minimum 1s) -c compile the instrumented code but do not run it -v verbose: print additional output ``` ## 安装 ``` $ go get -u github.com/thepudds/fzgo/... $ go get -u github.com/dvyukov/go-fuzz/... ``` 注意:如果您已经有一个旧版本的 `dvyukov/go-fuzz`,您可能需要先按照 [dvyukov/go-fuzz](https://github.com/dvyukov/go-fuzz#history-rewrite) 仓库中的说明将其从 GOPATH 中删除。 `go-fuzz` 源代码必须位于您的 GOPATH 中,并且 `go-fuzz` 和 `go-fuzz-build` 二进制文件必须 位于您的 path 环境变量中。 **注意**:不支持模块模式([#15](https://github.com/thepudds/fzgo/issues/15)),但是只要被测代码位于 GOPATH 中并且您设置了 `GO111MODULE=off` 环境变量,您就可以使用 `fzgo` 对模块进行 fuzzing。 ## 状态 这是一个简单的原型。不要期望太高。 ;-) 话虽如此,这里有合理的测试覆盖率,希望 `fzgo` 已经达到了 beta 质量。自动生成 fuzz 函数的功能是在一个单独的 [genfuzzfuncs](https://github.com/thepudds/fzgo/blob/master/genfuzzfuncs/README.md) 实用程序中实现的,它更偏向于 alpha 质量。 测试主要是使用 Go 核心团队用来测试 `go` 工具的优秀的内部 `testscripts` 包完成的, 该包提取自 [rogpeppe/go-internal/testscript](https://github.com/rogpeppe/go-internal/tree/master/testscript)。 #### 相对于提案文档的变更 当前 fzgo 原型与 2017 年 3 月的[提案文档](https://github.com/golang/go/issues/19109#issuecomment-285456008)之间的主要区别: 1. fzgo 支持丰富的签名。 2. 语料库位置不默认为 `/testdata/fuzz`,而是遵循[这里](https://groups.google.com/d/msg/golang-fuzzing-proposal/WVyRXx7AsO4/CXzvbMT1CgAJ)概述并在 [PR #7](https://github.com/thepudds/fzgo/pull/7) 中更准确描述的方法。 3. 最初,fzgo 不允许匹配多个 fuzz 函数(根据 2017 年 3 月的提案), 但作为一项实验,fzgo 现在允许匹配多个 fuzz 函数,以便 在跨多个包存在多个 fuzz 函数时支持类似 'go test -fuzz=. ./...' 的操作。如果匹配到多个 fuzz 函数,将以轮询方式进行 fuzzing。 4. 提案文档建议使用 `GOPATH/pkg/GOOS_GOARCH_fuzz/` 作为缓存,但原型 使用的是 `GOPATH/pkg/fuzz/GOOS_GOARCH/`。 5. 最初的提案文档建议在未指定 `-fuzz` 时在 `go test` 期间生成新的基于变异的输入。为了保持 `go test` 的确定性,`fzgo` 没有这样做,但现在在未指定 `-fuzz` 时确实将语料库作为 `go test` 期间的确定性输入集。此外,提案文档建议使用 `-fuzzinput` 作为指定语料库中文件以作为单元测试执行的方式。`fzgo` 则使用了传递给 `go test` 的常规 `-run` 参数。例如,`fzgo test -run=TestCorpus/4fa128cf066f2a31 some/pkg` 会运行 `some/pkg` 语料库中文件名匹配 `4fa128cf066f2a31` 的任何文件。 6. [#19109](https://golang.org/issue/19109) 的一些评论者建议使用 `-fuzztime duration` 作为 控制何时停止 fuzzing 的方式。提案文档不包含 `-fuzztime`,`go-fuzz` 也不支持它,但它通常看起来很有用,所以 `-fuzztime` 被包含在原型中(并且在测试原型时证明 很有用)。这可能会在以后被移除。 7. 为了进行实验,`FZGOFLAGSBUILD` 和 `FZGOFLAGSFUZZ` 环境变量可以选择性地包含以空格分隔的参数列表,分别传递给 `go-fuzz-build` 和 `go-fuzz`。 #### 提案文档中未在此原型中实现的部分 * 用于 fuzzing 函数的 `fuzz.F` 或 `testing.F` 签名。 * 允许 fuzzing 函数驻留在 `*_test.go` 文件中。 * 任何关于与编译器更深度的集成以实现更强大检测的内容。这个 原型不关注该领域。 * 更大范围的现有构建标志,如 `-ldflags`、`-coverprofile` 等。 * 2017 年 3 月的[提案文档](https://github.com/golang/go/issues/19109#issuecomment-285456008)中涵盖的领域, 除了本原型重点关注的直接面向用户的行为之外。话虽如此,提案文档中提到的大多数面向用户的行为要么已在原型中实现,要么已在此列表中明确指出未实现。 'go test' 中的参数解析是定制的,而 `fzgo` 中的参数解析是对此的近似。 这对于早期原型来说可能没问题。正确的做法可能是提取 [src/cmd/go/internal/test/testflag.go](https://golang.org/src/cmd/go/internal/test/testflag.go), 其中包括这条注释: ``` // The flag handling part of go test is large and distracting. // We can't use the flag package because some of the flags from // our command line are for us, and some are for 6.out, and // some are for both. ```
标签:EVTX分析, Go, Ruby工具, SOC Prime, 代码测试, 开发工具, 日志审计