github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/internal/fuzz/mutator.go (about) 1 // Copyright 2020 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 import ( 8 "encoding/binary" 9 "fmt" 10 "math" 11 "unsafe" 12 ) 13 14 type mutator struct { 15 r mutatorRand 16 scratch []byte // scratch slice to avoid additional allocations 17 } 18 19 func newMutator() *mutator { 20 return &mutator{r: newPcgRand()} 21 } 22 23 func (m *mutator) rand(n int) int { 24 return m.r.intn(n) 25 } 26 27 func (m *mutator) randByteOrder() binary.ByteOrder { 28 if m.r.bool() { 29 return binary.LittleEndian 30 } 31 return binary.BigEndian 32 } 33 34 // chooseLen chooses length of range mutation in range [1,n]. It gives 35 // preference to shorter ranges. 36 func (m *mutator) chooseLen(n int) int { 37 switch x := m.rand(100); { 38 case x < 90: 39 return m.rand(min(8, n)) + 1 40 case x < 99: 41 return m.rand(min(32, n)) + 1 42 default: 43 return m.rand(n) + 1 44 } 45 } 46 47 func min(a, b int) int { 48 if a < b { 49 return a 50 } 51 return b 52 } 53 54 // mutate performs several mutations on the provided values. 55 func (m *mutator) mutate(vals []any, maxBytes int) { 56 // TODO(katiehockman): pull some of these functions into helper methods and 57 // test that each case is working as expected. 58 // TODO(katiehockman): perform more types of mutations for []byte. 59 60 // maxPerVal will represent the maximum number of bytes that each value be 61 // allowed after mutating, giving an equal amount of capacity to each line. 62 // Allow a little wiggle room for the encoding. 63 maxPerVal := maxBytes/len(vals) - 100 64 65 // Pick a random value to mutate. 66 // TODO: consider mutating more than one value at a time. 67 i := m.rand(len(vals)) 68 switch v := vals[i].(type) { 69 case int: 70 vals[i] = int(m.mutateInt(int64(v), maxInt)) 71 case int8: 72 vals[i] = int8(m.mutateInt(int64(v), math.MaxInt8)) 73 case int16: 74 vals[i] = int16(m.mutateInt(int64(v), math.MaxInt16)) 75 case int64: 76 vals[i] = m.mutateInt(v, maxInt) 77 case uint: 78 vals[i] = uint(m.mutateUInt(uint64(v), maxUint)) 79 case uint16: 80 vals[i] = uint16(m.mutateUInt(uint64(v), math.MaxUint16)) 81 case uint32: 82 vals[i] = uint32(m.mutateUInt(uint64(v), math.MaxUint32)) 83 case uint64: 84 vals[i] = m.mutateUInt(uint64(v), maxUint) 85 case float32: 86 vals[i] = float32(m.mutateFloat(float64(v), math.MaxFloat32)) 87 case float64: 88 vals[i] = m.mutateFloat(v, math.MaxFloat64) 89 case bool: 90 if m.rand(2) == 1 { 91 vals[i] = !v // 50% chance of flipping the bool 92 } 93 case rune: // int32 94 vals[i] = rune(m.mutateInt(int64(v), math.MaxInt32)) 95 case byte: // uint8 96 vals[i] = byte(m.mutateUInt(uint64(v), math.MaxUint8)) 97 case string: 98 if len(v) > maxPerVal { 99 panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) 100 } 101 if cap(m.scratch) < maxPerVal { 102 m.scratch = append(make([]byte, 0, maxPerVal), v...) 103 } else { 104 m.scratch = m.scratch[:len(v)] 105 copy(m.scratch, v) 106 } 107 m.mutateBytes(&m.scratch) 108 vals[i] = string(m.scratch) 109 case []byte: 110 if len(v) > maxPerVal { 111 panic(fmt.Sprintf("cannot mutate bytes of length %d", len(v))) 112 } 113 if cap(m.scratch) < maxPerVal { 114 m.scratch = append(make([]byte, 0, maxPerVal), v...) 115 } else { 116 m.scratch = m.scratch[:len(v)] 117 copy(m.scratch, v) 118 } 119 m.mutateBytes(&m.scratch) 120 vals[i] = m.scratch 121 default: 122 panic(fmt.Sprintf("type not supported for mutating: %T", vals[i])) 123 } 124 } 125 126 func (m *mutator) mutateInt(v, maxValue int64) int64 { 127 var max int64 128 for { 129 max = 100 130 switch m.rand(2) { 131 case 0: 132 // Add a random number 133 if v >= maxValue { 134 continue 135 } 136 if v > 0 && maxValue-v < max { 137 // Don't let v exceed maxValue 138 max = maxValue - v 139 } 140 v += int64(1 + m.rand(int(max))) 141 return v 142 case 1: 143 // Subtract a random number 144 if v <= -maxValue { 145 continue 146 } 147 if v < 0 && maxValue+v < max { 148 // Don't let v drop below -maxValue 149 max = maxValue + v 150 } 151 v -= int64(1 + m.rand(int(max))) 152 return v 153 } 154 } 155 } 156 157 func (m *mutator) mutateUInt(v, maxValue uint64) uint64 { 158 var max uint64 159 for { 160 max = 100 161 switch m.rand(2) { 162 case 0: 163 // Add a random number 164 if v >= maxValue { 165 continue 166 } 167 if v > 0 && maxValue-v < max { 168 // Don't let v exceed maxValue 169 max = maxValue - v 170 } 171 172 v += uint64(1 + m.rand(int(max))) 173 return v 174 case 1: 175 // Subtract a random number 176 if v <= 0 { 177 continue 178 } 179 if v < max { 180 // Don't let v drop below 0 181 max = v 182 } 183 v -= uint64(1 + m.rand(int(max))) 184 return v 185 } 186 } 187 } 188 189 func (m *mutator) mutateFloat(v, maxValue float64) float64 { 190 var max float64 191 for { 192 switch m.rand(4) { 193 case 0: 194 // Add a random number 195 if v >= maxValue { 196 continue 197 } 198 max = 100 199 if v > 0 && maxValue-v < max { 200 // Don't let v exceed maxValue 201 max = maxValue - v 202 } 203 v += float64(1 + m.rand(int(max))) 204 return v 205 case 1: 206 // Subtract a random number 207 if v <= -maxValue { 208 continue 209 } 210 max = 100 211 if v < 0 && maxValue+v < max { 212 // Don't let v drop below -maxValue 213 max = maxValue + v 214 } 215 v -= float64(1 + m.rand(int(max))) 216 return v 217 case 2: 218 // Multiply by a random number 219 absV := math.Abs(v) 220 if v == 0 || absV >= maxValue { 221 continue 222 } 223 max = 10 224 if maxValue/absV < max { 225 // Don't let v go beyond the minimum or maximum value 226 max = maxValue / absV 227 } 228 v *= float64(1 + m.rand(int(max))) 229 return v 230 case 3: 231 // Divide by a random number 232 if v == 0 { 233 continue 234 } 235 v /= float64(1 + m.rand(10)) 236 return v 237 } 238 } 239 } 240 241 type byteSliceMutator func(*mutator, []byte) []byte 242 243 var byteSliceMutators = []byteSliceMutator{ 244 byteSliceRemoveBytes, 245 byteSliceInsertRandomBytes, 246 byteSliceDuplicateBytes, 247 byteSliceOverwriteBytes, 248 byteSliceBitFlip, 249 byteSliceXORByte, 250 byteSliceSwapByte, 251 byteSliceArithmeticUint8, 252 byteSliceArithmeticUint16, 253 byteSliceArithmeticUint32, 254 byteSliceArithmeticUint64, 255 byteSliceOverwriteInterestingUint8, 256 byteSliceOverwriteInterestingUint16, 257 byteSliceOverwriteInterestingUint32, 258 byteSliceInsertConstantBytes, 259 byteSliceOverwriteConstantBytes, 260 byteSliceShuffleBytes, 261 byteSliceSwapBytes, 262 } 263 264 func (m *mutator) mutateBytes(ptrB *[]byte) { 265 b := *ptrB 266 defer func() { 267 if unsafe.SliceData(*ptrB) != unsafe.SliceData(b) { 268 panic("data moved to new address") 269 } 270 *ptrB = b 271 }() 272 273 for { 274 mut := byteSliceMutators[m.rand(len(byteSliceMutators))] 275 if mutated := mut(m, b); mutated != nil { 276 b = mutated 277 return 278 } 279 } 280 } 281 282 var ( 283 interesting8 = []int8{-128, -1, 0, 1, 16, 32, 64, 100, 127} 284 interesting16 = []int16{-32768, -129, 128, 255, 256, 512, 1000, 1024, 4096, 32767} 285 interesting32 = []int32{-2147483648, -100663046, -32769, 32768, 65535, 65536, 100663045, 2147483647} 286 ) 287 288 const ( 289 maxUint = uint64(^uint(0)) 290 maxInt = int64(maxUint >> 1) 291 ) 292 293 func init() { 294 for _, v := range interesting8 { 295 interesting16 = append(interesting16, int16(v)) 296 } 297 for _, v := range interesting16 { 298 interesting32 = append(interesting32, int32(v)) 299 } 300 }