From 4224d54eaff59e1979d85bde723ab0d583d8d896 Mon Sep 17 00:00:00 2001 From: Eyal Posener Date: Thu, 23 Jan 2020 23:11:25 +0200 Subject: [PATCH] Add NewFromGoFuzz Add a helper function that enables using gofuzz (this project) with go-fuzz (https://github.com/dvyukov/go-fuzz) for continuose fuzzing. Essentially, it enables translating the fuzzing bytes from go-fuzz to any Go object using this library. This change will enable using this project with fuzzing websites such as fuzzit.dev or fuzzbuzz.io. I've created an example in: https://github.com/posener/fuzzme Fixes #33 --- fuzz.go | 29 +++++++++++++++++++++++++++++ fuzz_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/fuzz.go b/fuzz.go index da0a5f9..98d2906 100644 --- a/fuzz.go +++ b/fuzz.go @@ -18,6 +18,8 @@ package fuzz import ( "fmt" + "math" + "math/big" "math/rand" "reflect" "regexp" @@ -61,6 +63,33 @@ func NewWithSeed(seed int64) *Fuzzer { return f } +// NewFromGoFuzz is a helper function that enables using gofuzz (this +// project) with go-fuzz (https://github.com/dvyukov/go-fuzz) for continuous +// fuzzing. Essentially, it enables translating the fuzzing bytes from +// go-fuzz to any Go object using this library. +// +// Example: use go-fuzz to test the function `MyFunc(int)` in the package +// `mypackage`. Add the file: "mypacakge_fuzz.go" with the content: +// +// // +build gofuzz +// package mypacakge +// import "github.com/google/go-fuzz" +// func Fuzz(data []byte) int { +// var i int +// fuzz.NewFromGoFuzz(data).Fuzz(&i) +// MyFunc(i) +// return 0 +// } +func NewFromGoFuzz(data []byte) *Fuzzer { + maxint := big.NewInt(math.MaxInt64) + seed := big.NewInt(1) + for _, b := range data { + seed.Mul(seed, big.NewInt(int64(b))) + seed.Mod(seed, maxint) + } + return NewWithSeed(seed.Int64()) +} + // Funcs adds each entry in fuzzFuncs as a custom fuzzing function. // // Each entry in fuzzFuncs must be a function taking two parameters. diff --git a/fuzz_test.go b/fuzz_test.go index 86ad2fa..6105380 100644 --- a/fuzz_test.go +++ b/fuzz_test.go @@ -504,3 +504,28 @@ func TestFuzz_SkipPattern(t *testing.T) { return 5, true }) } + +func TestNewFromGoFuzz(t *testing.T) { + tests := []struct { + data []byte + want int + }{ + // Tests consistant fuzzing for the same input. + {data: []byte("a"), want: 943890139707072619}, + // Tests that different input corresponds in different output. + {data: []byte("b"), want: -7308824908432364150}, + // Tests long input. + { + data: []byte("123jhasd0128931`3kljahsdlkasb,mxznbcqlsjerqwporu108378091237ksdjhlakshz"), + want: 3588769380299097370, + }, + } + + for _, tt := range tests { + var got int + NewFromGoFuzz(tt.data).Fuzz(&got) + if tt.want != got { + t.Errorf("Fuzz(%q) = %d, want: %d", tt.data, got, tt.want) + } + } +}