]> Cypherpunks repositories - gostls13.git/commitdiff
internal/fuzz: fix chunk swap mutator
authorRoland Shoemaker <roland@golang.org>
Thu, 18 Nov 2021 19:40:48 +0000 (11:40 -0800)
committerRoland Shoemaker <roland@golang.org>
Fri, 19 Nov 2021 18:23:43 +0000 (18:23 +0000)
When swapping two chunks of bytes in a slice, don't pick chunks which
extend beyond the end of the slice. Also don't pick chunks which
intersect with each other.

Fixes #49047

Change-Id: I070eb1888d05ae849ec6122d01c40c45e602019f
Reviewed-on: https://go-review.googlesource.com/c/go/+/365175
Trust: Roland Shoemaker <roland@golang.org>
Trust: Bryan C. Mills <bcmills@google.com>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Katie Hockman <katie@golang.org>
src/internal/fuzz/mutators_byteslice.go
src/internal/fuzz/mutators_byteslice_test.go

index 7c96b5920ea02632ff96b629f52e2cb36ad9c072..d9dab1df9f4e859c114d28a3ae1867c035dfb392 100644 (file)
@@ -284,7 +284,19 @@ func byteSliceSwapBytes(m *mutator, b []byte) []byte {
        for dst == src {
                dst = m.rand(len(b))
        }
-       n := m.chooseLen(len(b) - src - 1)
+       // Choose the random length as len(b) - max(src, dst)
+       // so that we don't attempt to swap a chunk that extends
+       // beyond the end of the slice
+       max := dst
+       if src > max {
+               max = src
+       }
+       n := m.chooseLen(len(b) - max - 1)
+       // Check that neither chunk intersect, so that we don't end up
+       // duplicating parts of the input, rather than swapping them
+       if src > dst && dst+n >= src || dst > src && src+n >= dst {
+               return nil
+       }
        // Use the end of the slice as scratch space to avoid doing an
        // allocation. If the slice is too small abort and try something
        // else.
index 50a39a9a5b5fa6cf6caee4515a7e877c99127f14..788696788187247c23e07793e084541cddd09875 100644 (file)
@@ -10,30 +10,31 @@ import (
 )
 
 type mockRand struct {
+       values  []int
        counter int
        b       bool
 }
 
 func (mr *mockRand) uint32() uint32 {
-       c := mr.counter
+       c := mr.values[mr.counter]
        mr.counter++
        return uint32(c)
 }
 
 func (mr *mockRand) intn(n int) int {
-       c := mr.counter
+       c := mr.values[mr.counter]
        mr.counter++
        return c % n
 }
 
 func (mr *mockRand) uint32n(n uint32) uint32 {
-       c := mr.counter
+       c := mr.values[mr.counter]
        mr.counter++
        return uint32(c) % n
 }
 
 func (mr *mockRand) exp2() int {
-       c := mr.counter
+       c := mr.values[mr.counter]
        mr.counter++
        return c
 }
@@ -56,6 +57,7 @@ func TestByteSliceMutators(t *testing.T) {
        for _, tc := range []struct {
                name     string
                mutator  func(*mutator, []byte) []byte
+               randVals []int
                input    []byte
                expected []byte
        }{
@@ -164,12 +166,17 @@ func TestByteSliceMutators(t *testing.T) {
                {
                        name:     "byteSliceSwapBytes",
                        mutator:  byteSliceSwapBytes,
+                       randVals: []int{0, 2, 0, 2},
                        input:    append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...),
-                       expected: []byte{2, 1, 3, 4},
+                       expected: []byte{3, 2, 1, 4},
                },
        } {
                t.Run(tc.name, func(t *testing.T) {
-                       m := &mutator{r: &mockRand{}}
+                       r := &mockRand{values: []int{0, 1, 2, 3, 4, 5}}
+                       if tc.randVals != nil {
+                               r.values = tc.randVals
+                       }
+                       m := &mutator{r: r}
                        b := tc.mutator(m, tc.input)
                        if !bytes.Equal(b, tc.expected) {
                                t.Errorf("got %x, want %x", b, tc.expected)