1
0
mirror of https://github.com/golang/go synced 2024-11-24 03:40:16 -07:00

internal/fuzz: allocate memory for mutated strings

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 golang/go#48308

Change-Id: Iee9bed1a536fdc4188180e8e7c1c722f641271d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/351312
Trust: Roland Shoemaker <roland@golang.org>
Trust: Katie Hockman <katie@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
Reviewed-by: Katie Hockman <katie@golang.org>
This commit is contained in:
Roland Shoemaker 2021-09-14 12:40:10 -07:00
parent 91c2318e67
commit ccf140f3d7
3 changed files with 21 additions and 7 deletions

View File

@ -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)))

View File

@ -5,6 +5,7 @@
package fuzz
import (
"bytes"
"fmt"
"os"
"strconv"
@ -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)
}
}

View File

@ -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.