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)))
package fuzz
import (
+ "bytes"
"fmt"
"os"
"strconv"
})
}
}
+
+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)
+ }
+}
// 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.