From: Roland Shoemaker Date: Sun, 25 Apr 2021 15:46:42 +0000 (-0700) Subject: [dev.fuzz] internal/fuzz: add extra []byte mutators X-Git-Tag: go1.18beta1~1282^2~65 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=dd7529408412ec94a454d8455f7547327ee0d64d;p=gostls13.git [dev.fuzz] internal/fuzz: add extra []byte mutators Adds four []byte mutators which: * insert a chunk of constant bytes * overwirtes a chunk with constant bytes * shuffle a range of bytes * swaps two chunks Also updates the 'set byte to random value' mutator to use XOR in order to avoid a no-op. Additionally updates the rng call which chooses the []byte mutators so all the available mutators are used. Change-Id: I0703518922952f4b1c81b19b196ee91c73b0d5f8 Reviewed-on: https://go-review.googlesource.com/c/go/+/313270 Trust: Roland Shoemaker Trust: Katie Hockman Run-TryBot: Roland Shoemaker TryBot-Result: Go Bot Reviewed-by: Katie Hockman --- diff --git a/src/internal/fuzz/mutator.go b/src/internal/fuzz/mutator.go index 88cb7b4e03..eda0128300 100644 --- a/src/internal/fuzz/mutator.go +++ b/src/internal/fuzz/mutator.go @@ -255,7 +255,7 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { numIters := 1 + m.r.exp2() for iter := 0; iter < numIters; iter++ { - switch m.rand(10) { + switch m.rand(18) { case 0: // Remove a range of bytes. if len(b) <= 1 { @@ -280,7 +280,8 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { b[pos+i] = byte(m.rand(256)) } case 2: - // Duplicate a range of bytes. + // Duplicate a range of bytes and insert it into + // a random position if len(b) <= 1 { iter-- continue @@ -301,7 +302,8 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { copy(b[dst+n:], b[dst:]) copy(b[dst:], tmp) case 3: - // Copy a range of bytes. + // Overwrite a range of bytes with a randomly selected + // chunk if len(b) <= 1 { iter-- continue @@ -328,7 +330,10 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { continue } pos := m.rand(len(b)) - b[pos] = byte(m.rand(256)) + // In order to avoid a no-op (where the random value matches + // the existing value), use XOR instead of just setting to + // the random value. + b[pos] ^= byte(1 + m.rand(255)) case 6: // Swap 2 bytes. if len(b) <= 1 { @@ -419,6 +424,82 @@ func (m *mutator) mutateBytes(ptrB *[]byte) { pos := m.rand(len(b) - 3) v := uint32(interesting32[m.rand(len(interesting32))]) m.randByteOrder().PutUint32(b[pos:], v) + case 14: + // Insert a range of constant bytes. + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + // TODO(rolandshoemaker,katiehockman): 4096 was mainly picked + // randomly. We may want to either pick a much larger value + // (AFL uses 32768, paired with a similar impl to chooseLen + // which biases towards smaller lengths that grow over time), + // or set the max based on characteristics of the corpus + // (libFuzzer sets a min/max based on the min/max size of + // entries in the corpus and then picks uniformly from + // that range). + n := m.chooseLen(4096) + if len(b)+n >= cap(b) { + iter-- + continue + } + b = b[:len(b)+n] + copy(b[dst+n:], b[dst:]) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + case 15: + // Overwrite a range of bytes with a chunk of + // constant bytes. + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + rb := byte(m.rand(256)) + for i := dst; i < dst+n; i++ { + b[i] = rb + } + case 16: + // Shuffle a range of bytes + if len(b) <= 1 { + iter-- + continue + } + dst := m.rand(len(b)) + n := m.chooseLen(len(b) - dst) + if n <= 2 { + iter-- + continue + } + // Start at the end of the range, and iterate backwards + // to dst, swapping each element with another element in + // dst:dst+n (Fisher-Yates shuffle). + for i := n - 1; i > 0; i-- { + j := m.rand(i + 1) + b[dst+i], b[dst+j] = b[dst+j], b[dst+i] + } + case 17: + // Swap two chunks + if len(b) <= 1 { + iter-- + continue + } + src := m.rand(len(b)) + dst := m.rand(len(b)) + for dst == src { + dst = m.rand(len(b)) + } + n := m.chooseLen(len(b) - src) + tmp := make([]byte, n) + copy(tmp, b[dst:]) + copy(b[dst:], b[src:src+n]) + copy(b[src:], tmp) + default: + panic("unknown mutator") } } }