]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.fuzz] internal/fuzz: implement basic mutator and use in worker
authorKatie Hockman <katie@golang.org>
Mon, 19 Oct 2020 17:48:28 +0000 (13:48 -0400)
committerFilippo Valsorda <filippo@golang.org>
Fri, 4 Dec 2020 18:17:29 +0000 (19:17 +0100)
Note that this is an extremely basic mutator, and only
meant to act as a placeholder for future development.

Change-Id: I650691db44f30953345702aac93cbd1cadc21427
Reviewed-on: https://go-review.googlesource.com/c/go/+/263657
Trust: Katie Hockman <katie@golang.org>
Trust: Jay Conrod <jayconrod@google.com>
Run-TryBot: Katie Hockman <katie@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/go/build/deps_test.go
src/internal/fuzz/mutator.go [new file with mode: 0644]
src/internal/fuzz/worker.go

index e5f38d4fbcd674f014f133bc26b85553a1571f66..26f6ab2ec3a1db2cc66e6363241f86db3ecefb4f 100644 (file)
@@ -467,7 +467,7 @@ var depsRules = `
        FMT, flag, runtime/debug, runtime/trace
        < testing;
 
-       FMT, encoding/json
+       FMT, encoding/json, math/rand
        < internal/fuzz;
 
        internal/fuzz, internal/testlog, runtime/pprof, regexp
diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go
new file mode 100644 (file)
index 0000000..229bb31
--- /dev/null
@@ -0,0 +1,18 @@
+// 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
+}
index 543e352e7f93e3c974e898298b85e7aac11d5a74..0aa7015c66c4a1a87600c91af1a01777eed55673 100644 (file)
@@ -81,8 +81,8 @@ func (w *worker) runFuzzing() error {
                        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 {
@@ -282,11 +282,14 @@ type call struct {
 }
 
 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 {
@@ -326,8 +329,19 @@ func (ws *workerServer) serve(fuzzIn io.ReadCloser, fuzzOut io.WriteCloser) erro
 // 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.