Go Fuzzing Beta でよくわからんところをまとめる
The Go Blog の記事『Fuzzing is Beta Ready』で発表された通り、次期 Go のバージョンで導入される公式 Fuzzing について、いろいろと疑問が出てきたのでまとめる。
上記の記事はあくまでも Get Started な記事なので、詳細を知るために元となったプロポーザルも見ていく。
Go 公式としていつ Fuzzing をサポートするの?
go1.17 ではまだ利用できないが、将来的にサポートされる。
現時点ではプロトタイプが開発され、ベータ版が利用できる段階。
Go Modules のときと同じように考えれば、go1.18 で実験的にサポートされ、go1.19で公式サポートされるかもしれない。Go Modules よりは考慮すべきことが少ないから、もしかしたら go1.18 でサポートされるかも?
コーパスってなに?
Fuzzing におけるコーパス(Corpus)は、Fuzzing Engine に入力するデータの集合のこと。Fuzzing 中にコーパスからさらにコーパスを生成する。
コーパスは再利用されるの?
Fuzzing に使用するコーパスはメソッド testing.F.Add
に代入して定義することができる。Fuzzing 中にはその関数で定義したコーパスから新たなコーパスを生成し、さらに Fuzzing していく。
ここで、Fuzzing 中に生成されたコーパスは Fuzzing 終了後に消えてしまうのか?再利用できればコーパスを生成する処理を省略したり、すでに Fuzzing に使用したコーパスの要素がテストに通っているかの判定処理を省略できるのではないか?と疑問が湧いてくる。
Go Fuzzing Beta では、それらをキャッシュとして testdata/corpus/FuzzTarget
配下および $GOCACHE/fuzz
配下に保存し、再利用する仕組みがある。キャッシュは同じ Fuzz Target 内で利用され、他の Fuzz Target からは利用されない。
Fuzzing の時間短縮は可能になったが、キャッシュは無尽蔵に生成されるため、気づいたときにはストレージを圧迫している可能性がある。そのため、定期的にキャッシュはクリアしておこう(キャッシュクリアするサブコマンドが用意されているので、直接キャッシュをいじるのではなく、そのコマンドを使おう)。
testing.F.Add
と testing.F.Fuzz
の関係
testing.F.Add
でコーパスを定義し、testing.F.Fuzz
でそのコーパスを使用した Fuzzing を行う。
コードとしては testing.F.Add
の引数列で1組のコーパスを定義し、testing.F.Fuzz
にそのコーパスを使用して処理する関数を渡す。そのため、1つの Fuzz メソッド FuzzX
内では、testing.F.Add
の引数の形式と testing.F.Fuzz
に渡す関数の引数の形式は同じでなければならない(正確には、testing.F.Fuzz
に渡す関数の第一引数は *testing.T
であるため、第二引数以降で考える)。
Fuzzing に利用できる型
複素数以外の数値型、byte
、string
、rune
、[]byte
、bool
が使用できる。
プロポーザルにはメソッド UnmarshalBinary
や UnmarshalText
を持つ構造体も使用できると記述されているが、ベータ版の実装を見た限りまだ使用できないようである。
Fuzzing Engine はどのようなアルゴリズムでコーパスを生成するの?
プロポーザルには、コードカバレッジを高めるようにコーパスを生成する Fuzzing Engine を新しく開発したとある。ただ、具体的なアルゴリズムについては言及しておらず、ユーザーが技術的な詳細を知らなくても使えるようにすると記述してあるため、ここでもアルゴリズムの詳細は追わない。