Goブログ

ファジングがベータ版として利用可能になりました

Katie Hockman and Jay Conrod
2021年6月3日

tip でネイティブファジングがベータテストの準備ができたことを発表できることを嬉しく思います!

ファジングは、パニックやバグなどの問題を見つけるために、プログラムへの入力を継続的に操作する自動テストの一種です。 これらの半ランダムなデータの変異は、既存のユニットテストが見逃してしまう可能性のある新しいコードカバレッジを発見し、気付かれずに済む可能性のあるエッジケースのバグを明らかにすることができます。 ファジングはこれらのエッジケースに到達できるため、ファズテストはセキュリティの脆弱性や欠陥を見つけるのに特に役立ちます。

この機能の詳細については、golang.org/s/draft-fuzzing-design を参照してください。

はじめに

始めるには、以下を実行します

$ go install golang.org/dl/gotip@latest
$ gotip download

これは master ブランチから Go ツールチェーンをビルドします。 これを実行した後、gotipgo コマンドの代わりに使用できます。 次のようなコマンドを実行できるようになりました

$ 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」ラベルが付いた issue トラッカー を確認してください。

ファジングは大量のメモリを消費する可能性があり、実行中にマシンのパフォーマンスに影響を与える可能性があることに注意してください。 go test -fuzz は、デフォルトで $GOMAXPROCS プロセスで並列にファジングを実行します。 go test-parallel フラグを明示的に設定することで、ファジング中に使用されるプロセスの数を減らすことができます。 詳細については、gotip help testflag を実行して go test コマンドのドキュメントを読んでください。

また、ファジングエンジンは、実行中にテストカバレッジを拡張する値を $GOCACHE/fuzz 内のファズキャッシュディレクトリに書き込むことにも注意してください。 現在、ファズキャッシュに書き込むことができるファイル数または合計バイト数に制限がないため、大量のストレージ(数GBなど)を占有する可能性があります。 gotip clean -fuzzcache を実行することで、ファズキャッシュをクリアできます。

次は何ですか?

この機能は Go 1.18 から利用可能になります。

問題が発生した場合、または機能のアイデアがある場合は、issue を提出してください

機能に関する議論や一般的なフィードバックについては、Gophers Slack の #fuzzing チャンネル にも参加できます。

楽しいファジングを!

次の記事:Stack Overflow の Go Collective
前の記事:Go開発者調査2020の結果
ブログインデックス