FMT, flag, runtime/debug, runtime/trace
< testing;
- FMT, encoding/json
+ FMT, encoding/json, math/rand
< internal/fuzz;
internal/fuzz, internal/testlog, runtime/pprof, regexp
--- /dev/null
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fuzz
+
+import "math/rand"
+
+func mutate(b []byte) []byte {
+ mutated := make([]byte, len(b))
+ copy(mutated, b)
+
+ // Mutate a byte in a random position.
+ pos := rand.Intn(len(mutated))
+ mutated[pos] = byte(rand.Intn(256))
+
+ return mutated
+}
inputC = nil // block new inputs until we finish with this one.
go func() {
args := fuzzArgs{
- Value: input.b,
- DurationSec: workerFuzzDuration.Seconds(),
+ Value: input.b,
+ Duration: workerFuzzDuration,
}
_, err := w.client.fuzz(args)
if err != nil {
}
type fuzzArgs struct {
- Value []byte
- DurationSec float64
+ Value []byte
+ Duration time.Duration
}
-type fuzzResponse struct{}
+type fuzzResponse struct {
+ Crasher []byte
+ Err string
+}
// workerServer is a minimalist RPC server, run in fuzz worker processes.
type workerServer struct {
// a given amount of time. fuzz returns early if it finds an input that crashes
// the fuzz function or an input that expands coverage.
func (ws *workerServer) fuzz(args fuzzArgs) fuzzResponse {
- // TODO(jayconrod, katiehockman): implement
- return fuzzResponse{}
+ t := time.NewTimer(args.Duration)
+ for {
+ select {
+ case <-t.C:
+ return fuzzResponse{}
+ default:
+ b := mutate(args.Value)
+ if err := ws.fn(b); err != nil {
+ return fuzzResponse{Crasher: b, Err: err.Error()}
+ }
+ // TODO(jayconrod,katiehockman): return early if coverage is expanded
+ }
+ }
}
// workerClient is a minimalist RPC client, run in the fuzz coordinator.