...

Source file src/internal/fuzz/mutators_byteslice.go

Documentation: internal/fuzz

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package fuzz
     6  
     7  // byteSliceRemoveBytes removes a random chunk of bytes from b.
     8  func byteSliceRemoveBytes(m *mutator, b []byte) []byte {
     9  	if len(b) <= 1 {
    10  		return nil
    11  	}
    12  	pos0 := m.rand(len(b))
    13  	pos1 := pos0 + m.chooseLen(len(b)-pos0)
    14  	copy(b[pos0:], b[pos1:])
    15  	b = b[:len(b)-(pos1-pos0)]
    16  	return b
    17  }
    18  
    19  // byteSliceInsertRandomBytes inserts a chunk of random bytes into b at a random
    20  // position.
    21  func byteSliceInsertRandomBytes(m *mutator, b []byte) []byte {
    22  	pos := m.rand(len(b) + 1)
    23  	n := m.chooseLen(1024)
    24  	if len(b)+n >= cap(b) {
    25  		return nil
    26  	}
    27  	b = b[:len(b)+n]
    28  	copy(b[pos+n:], b[pos:])
    29  	for i := 0; i < n; i++ {
    30  		b[pos+i] = byte(m.rand(256))
    31  	}
    32  	return b
    33  }
    34  
    35  // byteSliceDuplicateBytes duplicates a chunk of bytes in b and inserts it into
    36  // a random position.
    37  func byteSliceDuplicateBytes(m *mutator, b []byte) []byte {
    38  	if len(b) <= 1 {
    39  		return nil
    40  	}
    41  	src := m.rand(len(b))
    42  	dst := m.rand(len(b))
    43  	for dst == src {
    44  		dst = m.rand(len(b))
    45  	}
    46  	n := m.chooseLen(len(b) - src)
    47  	// Use the end of the slice as scratch space to avoid doing an
    48  	// allocation. If the slice is too small abort and try something
    49  	// else.
    50  	if len(b)+(n*2) >= cap(b) {
    51  		return nil
    52  	}
    53  	end := len(b)
    54  	// Increase the size of b to fit the duplicated block as well as
    55  	// some extra working space
    56  	b = b[:end+(n*2)]
    57  	// Copy the block of bytes we want to duplicate to the end of the
    58  	// slice
    59  	copy(b[end+n:], b[src:src+n])
    60  	// Shift the bytes after the splice point n positions to the right
    61  	// to make room for the new block
    62  	copy(b[dst+n:end+n], b[dst:end])
    63  	// Insert the duplicate block into the splice point
    64  	copy(b[dst:], b[end+n:])
    65  	b = b[:end+n]
    66  	return b
    67  }
    68  
    69  // byteSliceOverwriteBytes overwrites a chunk of b with another chunk of b.
    70  func byteSliceOverwriteBytes(m *mutator, b []byte) []byte {
    71  	if len(b) <= 1 {
    72  		return nil
    73  	}
    74  	src := m.rand(len(b))
    75  	dst := m.rand(len(b))
    76  	for dst == src {
    77  		dst = m.rand(len(b))
    78  	}
    79  	n := m.chooseLen(len(b) - src - 1)
    80  	copy(b[dst:], b[src:src+n])
    81  	return b
    82  }
    83  
    84  // byteSliceBitFlip flips a random bit in a random byte in b.
    85  func byteSliceBitFlip(m *mutator, b []byte) []byte {
    86  	if len(b) == 0 {
    87  		return nil
    88  	}
    89  	pos := m.rand(len(b))
    90  	b[pos] ^= 1 << uint(m.rand(8))
    91  	return b
    92  }
    93  
    94  // byteSliceXORByte XORs a random byte in b with a random value.
    95  func byteSliceXORByte(m *mutator, b []byte) []byte {
    96  	if len(b) == 0 {
    97  		return nil
    98  	}
    99  	pos := m.rand(len(b))
   100  	// In order to avoid a no-op (where the random value matches
   101  	// the existing value), use XOR instead of just setting to
   102  	// the random value.
   103  	b[pos] ^= byte(1 + m.rand(255))
   104  	return b
   105  }
   106  
   107  // byteSliceSwapByte swaps two random bytes in b.
   108  func byteSliceSwapByte(m *mutator, b []byte) []byte {
   109  	if len(b) <= 1 {
   110  		return nil
   111  	}
   112  	src := m.rand(len(b))
   113  	dst := m.rand(len(b))
   114  	for dst == src {
   115  		dst = m.rand(len(b))
   116  	}
   117  	b[src], b[dst] = b[dst], b[src]
   118  	return b
   119  }
   120  
   121  // byteSliceArithmeticUint8 adds/subtracts from a random byte in b.
   122  func byteSliceArithmeticUint8(m *mutator, b []byte) []byte {
   123  	if len(b) == 0 {
   124  		return nil
   125  	}
   126  	pos := m.rand(len(b))
   127  	v := byte(m.rand(35) + 1)
   128  	if m.r.bool() {
   129  		b[pos] += v
   130  	} else {
   131  		b[pos] -= v
   132  	}
   133  	return b
   134  }
   135  
   136  // byteSliceArithmeticUint16 adds/subtracts from a random uint16 in b.
   137  func byteSliceArithmeticUint16(m *mutator, b []byte) []byte {
   138  	if len(b) < 2 {
   139  		return nil
   140  	}
   141  	v := uint16(m.rand(35) + 1)
   142  	if m.r.bool() {
   143  		v = 0 - v
   144  	}
   145  	pos := m.rand(len(b) - 1)
   146  	enc := m.randByteOrder()
   147  	enc.PutUint16(b[pos:], enc.Uint16(b[pos:])+v)
   148  	return b
   149  }
   150  
   151  // byteSliceArithmeticUint32 adds/subtracts from a random uint32 in b.
   152  func byteSliceArithmeticUint32(m *mutator, b []byte) []byte {
   153  	if len(b) < 4 {
   154  		return nil
   155  	}
   156  	v := uint32(m.rand(35) + 1)
   157  	if m.r.bool() {
   158  		v = 0 - v
   159  	}
   160  	pos := m.rand(len(b) - 3)
   161  	enc := m.randByteOrder()
   162  	enc.PutUint32(b[pos:], enc.Uint32(b[pos:])+v)
   163  	return b
   164  }
   165  
   166  // byteSliceArithmeticUint64 adds/subtracts from a random uint64 in b.
   167  func byteSliceArithmeticUint64(m *mutator, b []byte) []byte {
   168  	if len(b) < 8 {
   169  		return nil
   170  	}
   171  	v := uint64(m.rand(35) + 1)
   172  	if m.r.bool() {
   173  		v = 0 - v
   174  	}
   175  	pos := m.rand(len(b) - 7)
   176  	enc := m.randByteOrder()
   177  	enc.PutUint64(b[pos:], enc.Uint64(b[pos:])+v)
   178  	return b
   179  }
   180  
   181  // byteSliceOverwriteInterestingUint8 overwrites a random byte in b with an interesting
   182  // value.
   183  func byteSliceOverwriteInterestingUint8(m *mutator, b []byte) []byte {
   184  	if len(b) == 0 {
   185  		return nil
   186  	}
   187  	pos := m.rand(len(b))
   188  	b[pos] = byte(interesting8[m.rand(len(interesting8))])
   189  	return b
   190  }
   191  
   192  // byteSliceOverwriteInterestingUint16 overwrites a random uint16 in b with an interesting
   193  // value.
   194  func byteSliceOverwriteInterestingUint16(m *mutator, b []byte) []byte {
   195  	if len(b) < 2 {
   196  		return nil
   197  	}
   198  	pos := m.rand(len(b) - 1)
   199  	v := uint16(interesting16[m.rand(len(interesting16))])
   200  	m.randByteOrder().PutUint16(b[pos:], v)
   201  	return b
   202  }
   203  
   204  // byteSliceOverwriteInterestingUint32 overwrites a random uint16 in b with an interesting
   205  // value.
   206  func byteSliceOverwriteInterestingUint32(m *mutator, b []byte) []byte {
   207  	if len(b) < 4 {
   208  		return nil
   209  	}
   210  	pos := m.rand(len(b) - 3)
   211  	v := uint32(interesting32[m.rand(len(interesting32))])
   212  	m.randByteOrder().PutUint32(b[pos:], v)
   213  	return b
   214  }
   215  
   216  // byteSliceInsertConstantBytes inserts a chunk of constant bytes into a random position in b.
   217  func byteSliceInsertConstantBytes(m *mutator, b []byte) []byte {
   218  	if len(b) <= 1 {
   219  		return nil
   220  	}
   221  	dst := m.rand(len(b))
   222  	// TODO(rolandshoemaker,katiehockman): 4096 was mainly picked
   223  	// randomly. We may want to either pick a much larger value
   224  	// (AFL uses 32768, paired with a similar impl to chooseLen
   225  	// which biases towards smaller lengths that grow over time),
   226  	// or set the max based on characteristics of the corpus
   227  	// (libFuzzer sets a min/max based on the min/max size of
   228  	// entries in the corpus and then picks uniformly from
   229  	// that range).
   230  	n := m.chooseLen(4096)
   231  	if len(b)+n >= cap(b) {
   232  		return nil
   233  	}
   234  	b = b[:len(b)+n]
   235  	copy(b[dst+n:], b[dst:])
   236  	rb := byte(m.rand(256))
   237  	for i := dst; i < dst+n; i++ {
   238  		b[i] = rb
   239  	}
   240  	return b
   241  }
   242  
   243  // byteSliceOverwriteConstantBytes overwrites a chunk of b with constant bytes.
   244  func byteSliceOverwriteConstantBytes(m *mutator, b []byte) []byte {
   245  	if len(b) <= 1 {
   246  		return nil
   247  	}
   248  	dst := m.rand(len(b))
   249  	n := m.chooseLen(len(b) - dst)
   250  	rb := byte(m.rand(256))
   251  	for i := dst; i < dst+n; i++ {
   252  		b[i] = rb
   253  	}
   254  	return b
   255  }
   256  
   257  // byteSliceShuffleBytes shuffles a chunk of bytes in b.
   258  func byteSliceShuffleBytes(m *mutator, b []byte) []byte {
   259  	if len(b) <= 1 {
   260  		return nil
   261  	}
   262  	dst := m.rand(len(b))
   263  	n := m.chooseLen(len(b) - dst)
   264  	if n <= 2 {
   265  		return nil
   266  	}
   267  	// Start at the end of the range, and iterate backwards
   268  	// to dst, swapping each element with another element in
   269  	// dst:dst+n (Fisher-Yates shuffle).
   270  	for i := n - 1; i > 0; i-- {
   271  		j := m.rand(i + 1)
   272  		b[dst+i], b[dst+j] = b[dst+j], b[dst+i]
   273  	}
   274  	return b
   275  }
   276  
   277  // byteSliceSwapBytes swaps two chunks of bytes in b.
   278  func byteSliceSwapBytes(m *mutator, b []byte) []byte {
   279  	if len(b) <= 1 {
   280  		return nil
   281  	}
   282  	src := m.rand(len(b))
   283  	dst := m.rand(len(b))
   284  	for dst == src {
   285  		dst = m.rand(len(b))
   286  	}
   287  	// Choose the random length as len(b) - max(src, dst)
   288  	// so that we don't attempt to swap a chunk that extends
   289  	// beyond the end of the slice
   290  	max := dst
   291  	if src > max {
   292  		max = src
   293  	}
   294  	n := m.chooseLen(len(b) - max - 1)
   295  	// Check that neither chunk intersect, so that we don't end up
   296  	// duplicating parts of the input, rather than swapping them
   297  	if src > dst && dst+n >= src || dst > src && src+n >= dst {
   298  		return nil
   299  	}
   300  	// Use the end of the slice as scratch space to avoid doing an
   301  	// allocation. If the slice is too small abort and try something
   302  	// else.
   303  	if len(b)+n >= cap(b) {
   304  		return nil
   305  	}
   306  	end := len(b)
   307  	b = b[:end+n]
   308  	copy(b[end:], b[dst:dst+n])
   309  	copy(b[dst:], b[src:src+n])
   310  	copy(b[src:], b[end:])
   311  	b = b[:end]
   312  	return b
   313  }
   314  

View as plain text