Skip to content

Commit

Permalink
internal/fuzz: allocate memory for mutated strings
Browse files Browse the repository at this point in the history
Rather than directly pointing at the underlying scratch slice, allocate
memory for strings. This prevents mutation of previous values we've
passed to the fuzz function, which may be retained by something that
expects them to be immutable.

Fixes #48308

Change-Id: Iee9bed1a536fdc4188180e8e7c1c722f641271d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/351312
Trust: Roland Shoemaker <[email protected]>
Trust: Katie Hockman <[email protected]>
Run-TryBot: Roland Shoemaker <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Jay Conrod <[email protected]>
Reviewed-by: Katie Hockman <[email protected]>
  • Loading branch information
rolandshoemaker committed Sep 22, 2021
1 parent 91c2318 commit ccf140f
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
7 changes: 1 addition & 6 deletions src/internal/fuzz/mutator.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,7 @@ func (m *mutator) mutate(vals []interface{}, maxBytes int) {
copy(m.scratch, v)
}
m.mutateBytes(&m.scratch)
var s string
shdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
bhdr := (*reflect.SliceHeader)(unsafe.Pointer(&m.scratch))
shdr.Data = bhdr.Data
shdr.Len = bhdr.Len
vals[i] = s
vals[i] = string(m.scratch)
case []byte:
if len(v) > maxPerVal {
panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v)))
Expand Down
16 changes: 16 additions & 0 deletions src/internal/fuzz/mutator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package fuzz

import (
"bytes"
"fmt"
"os"
"strconv"
Expand Down Expand Up @@ -99,3 +100,18 @@ func BenchmarkMutatorAllBasicTypes(b *testing.B) {
})
}
}

func TestStringImmutability(t *testing.T) {
v := []interface{}{"hello"}
m := newMutator()
m.mutate(v, 1024)
original := v[0].(string)
originalCopy := make([]byte, len(original))
copy(originalCopy, []byte(original))
for i := 0; i < 25; i++ {
m.mutate(v, 1024)
}
if !bytes.Equal([]byte(original), originalCopy) {
t.Fatalf("string was mutated: got %x, want %x", []byte(original), originalCopy)
}
}
5 changes: 4 additions & 1 deletion src/testing/fuzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,10 @@ var supportedTypes = map[reflect.Type]bool{
// f.Fuzz(func(t *testing.T, b []byte, i int) { ... })
//
// This function should be fast, deterministic, and stateless.
// None of the pointers to any input data should be retained between executions.
//
// No mutatable input arguments, or pointers to them, should be retained between
// executions of the fuzz function, as the memory backing them may be mutated
// during a subsequent invocation.
//
// This is a terminal function which will terminate the currently running fuzz
// target by calling runtime.Goexit.
Expand Down

0 comments on commit ccf140f

Please sign in to comment.