Goチームは、ベータテストでファジングがサポートされるようになったことを発表した。プロジェクトの主な目標は、堅牢なモジュールサポート、go
コマンドとの統合、新しいコンパイラインストルメンテーションなど、言語の開発者とユーザ向けに統一されたエンドツーエンドのエクスペリエンスを作成することである。
ファジング設計ドラフトの作成者であるGoogleエンジニアのKatie Hockman氏によると、このプロジェクトはファジングを、単体テストを実行するのと同じくらい簡単にGoプログラムをテストするための最高の選択肢とすることを目的としている。
ファジングは、人間が見逃しがちなエッジケースをカバーできるため、ファジングテストは、セキュリティの悪用や脆弱性を見つけるのに特に役立ちます。ファズテストはこれまで主にセキュリティエンジニアによって作成されており、ハッカーは同様の方法で悪意を持って脆弱性を見つける可能性があります。ただし、ファズターゲットの作成は、セキュリティの専門知識を持つ開発者に限定する必要はありません。
ファジングはGoコミュニティと関係ないものではなく、go-fuzzやその派生のfzgoなどのツールがあるとHockmanは説明している。ただし、非標準のツールを使ったり、テストファイルを分離したりタグを作成したりする必要があるため、堅牢なモジュールのサポートがないため、開発者に不要なオーバーヘッドが発生していた。
以下は、net/urlパッケージの動作をテストするファジングターゲットのGoogleが提供する例である。
// +build gofuzzbeta
package fuzz
import (
"net/url"
"reflect"
"testing"
)
func FuzzParseQuery(f *testing.F) {
f.Add("x=1&y=2")
f.Fuzz(func(t *testing.T, queryStr string) {
query, err := url.ParseQuery(queryStr)
if err != nil {
t.Skip()
}
queryStr2 := query.Encode()
query2, err := url.ParseQuery(queryStr2)
if err != nil {
t.Fatalf("ParseQuery failed to decode a valid encoded query %s: %v", queryStr2, err)
}
if !reflect.DeepEqual(query, query2) {
t.Errorf("ParseQuery gave different query after being encoded\nbefore: %v\nafter: %v", query, query2)
}
})
}
ファズターゲットは、*testing.F
引数を受け取るFuzzXyz
関数の形式で提供される。f.Add
関数を使って、ファズターゲットへのユーザが指定する入力セットであるシードコーパスを設定できる。f.Fuzz
関数は、コーパス内のアイテムごとに実行される。シードコーパスに加えて、f.Fuzz
はtestdata/corpus/FuzzTarget
で提供される入力もテストする。
開発者がgoテスト
で-fuzz
フラグを使うと、Goファジングエンジンは生成されたコーパスに対してテスト機能を実行する。一方で、ミューテーターはバグやクラッシャーを発見するために新しい入力を生成する。
GoファジングベータはGo開発ブランチで入手できる。残念ながら、安定版のGoリリースにいつ含まれるかについてはまだスケジュールがなく、Hockman氏はGo 1.17にリリースされることはないとしている。
ベータ版であるため、Goファジングはまだ完了しておらず、変更される可能性がある。Hockman氏によるとすでに取り組み中の追加機能もいくつかある。例えば、複数のターゲットを一度にテスト、辞書のサポート、ミューテーター用のカスタムジェネレーターの追加である。