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
したシードだけでテストをしてくれる模様。
単純なテストとして実行できるのは良さそう。