The Go Blog
ファジングがベータ版対応
ネイティブファジングがtipでベータテストの準備が整ったことを発表でき、大変嬉しく思います!
ファジングとは、プログラムへの入力を継続的に操作して、パニックやバグなどの問題を見つける自動テストの一種です。これらの半ランダムなデータ変更は、既存の単体テストでは見逃される可能性のある新しいコードカバレッジを発見し、見過ごされがちなエッジケースのバグを明らかにします。ファジングはこれらのエッジケースに到達できるため、ファズテストはセキュリティエクスプロイトや脆弱性の発見に特に価値があります。
この機能の詳細については、golang.org/s/draft-fuzzing-design を参照してください。
入門
開始するには、以下を実行してください。
$ go install golang.org/dl/gotip@latest
$ gotip download
これは、Goツールチェーンをマスターブランチからビルドします。これを実行した後、gotipはgoコマンドのドロップイン代替として機能します。これで、次のようなコマンドを実行できます。
$ gotip test -fuzz=Fuzz
ファズテストの記述
ファズテストは、FuzzXxxという形式の関数として*_test.goファイルに記述する必要があります。この関数には、TestXxx関数に*testing.T引数が渡されるのと同様に、*testing.F引数を渡す必要があります。
以下は、net/urlパッケージの動作をテストするファズテストの例です。
//go:build go1.18
// +build go1.18
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)
}
})
}
pkg.go.devでファジングの詳細を読むことができます。Goでのファジングの概要や、新しいtesting.F型に関するgodocが含まれています。
期待されること
これはまだベータ版の新しい機能であるため、いくつかのバグや不完全な機能があることを予想してください。既存のバグや欠けている機能に関する最新情報は、「fuzz」とラベル付けされた問題のイシュートラッカーを確認してください。
ファジングは大量のメモリを消費し、実行中にマシンのパフォーマンスに影響を与える可能性があることに注意してください。go test -fuzzは、デフォルトで$GOMAXPROCSプロセスで並列にファジングを実行します。go testで明示的に-parallelフラグを設定することで、ファジング中に使用されるプロセスの数を減らすことができます。詳細については、gotip help testflagを実行してgo testコマンドのドキュメントを読んでください。
また、ファジングエンジンは、テストカバレッジを拡大する値を、実行中に$GOCACHE/fuzz内のファズキャッシュディレクトリに書き込むことにも注意してください。現在、ファズキャッシュに書き込まれるファイルの数や合計バイト数に制限はないため、大量のストレージ(数GBなど)を占める可能性があります。gotip clean -fuzzcacheを実行することで、ファズキャッシュをクリアできます。
次は何ですか?
この機能はGo 1.18から利用可能になります。
問題が発生した場合や機能のアイデアがある場合は、問題を報告してください。
この機能に関する議論や一般的なフィードバックについては、Gophers Slackの#fuzzingチャンネルに参加することもできます。
ハッピーファジング!