github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/internal/fuzz/mutators_byteslice.go (about) 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 }