Go 1.17(?)で入るFuzzingについて調べるぞ!
Fuzzingについて
・https://ymotongpoo.hatenablog.com/entry/2020/12/19/225831
・https://deeeet.com/writing/2015/12/21/go-fuzz/
dvyukov/go-fuzzが有名
google/gofuzzもある
環境を準備するのが面倒というのでGoネイティブ実装があると便利という話
現在はdev.fuzzブランチで開発が進んでいる。
現在はdev.fuzzブランチで開発が進んでいる。
Goのツールチェインをクローンしてきて以下でビルドできる。
all.bashよりmake.bashの方が早い(テストしないから)。
$ git checkout dev.fuzz
$ cd src
$ ./make.bash
Fuzzで始まる関数を作る。引数は*testing.Fにする。
func FuzzHoge(f *testing.F) {
}
f.Addでコーパスのシードを設定する。
Addできるのは、組み込み型(おそらくエラーは除く)、構造体(たぶんフィールドが対応する型の)とBinaryMarshalerインタフェースとBinaryUnmarshalerインタフェースまたはTextMarshalerインタフェースとTextUnmarshalerインタフェースを実装した型。
Addメソッドは可変長引数。
go doc testing.F.Add
package testing // import "testing"
func (f *F) Add(args ...interface{})
Add will add the arguments to the seed corpus for the fuzz target. This will
be a no-op if called after or within the Fuzz function. The args must match
those in the Fuzz function.
f.Fuzzメソッドでテストを実行する。
引数はテスト関数。
テスト関数の引数は第1引数が*testing.Tで残りがFuzzing対象の機能の入力となるもの。
↓の例では、Addメソッドでint型とstring型を指定してるからこの2つの型になっている。
func FuzzHoge(f *testing.F) {
f.Add(10, "hoge")
f.Add(-1, "fuga")
f.Fuzz(func(t *testing.T, n int, s string) {
})
}
与えたシードを基に入力データをミューテーションしていく。
入り口
FuzzXxxxどうかのチェック
f.Fuzzの中にはいる。
まだインタフェースの実装してるかどうかはチェックしてないのか。
testdata/corpusにコーパスをおいておけば勝手に読み込むのか。
f.AddでコーパスのSeedをappendしてる
1回のテスト関数の実行がこれかな
ちょいちょい出てくるfuzzContext
別のプロセスなのか
go testだけ実行するとf.Addしたシードだけでテストをしてくれる模様。
単純なテストとして実行できるのは良さそう。