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
5package fuzz
6
7// byteSliceRemoveBytes removes a random chunk of bytes from b.
8func 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.
21func 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.
37func 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.
70func 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.
85func 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.
95func 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.
108func 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.
122func 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.
137func 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.
152func 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.
167func 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.
183func 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.
194func 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.
206func 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.
217func 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.
244func 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.
258func 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.
278func 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