1 /*
2 *
3 * honggfuzz - buffer mangling routines
4 * -----------------------------------------
5 *
6 * Author:
7 * Robert Swiecki <swiecki@google.com>
8 *
9 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
12 * not use this file except in compliance with the License. You may obtain
13 * a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
20 * implied. See the License for the specific language governing
21 * permissions and limitations under the License.
22 *
23 */
24
25 #include "common.h"
26 #include "mangle.h"
27
28 #include <inttypes.h>
29 #include <math.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/mman.h>
33 #include <unistd.h>
34
35 #include "log.h"
36 #include "util.h"
37
mangle_Overwrite(uint8_t * dst,const uint8_t * src,size_t dstSz,size_t off,size_t sz)38 static inline void mangle_Overwrite(uint8_t * dst, const uint8_t * src, size_t dstSz, size_t off,
39 size_t sz)
40 {
41 size_t maxToCopy = dstSz - off;
42 if (sz > maxToCopy) {
43 sz = maxToCopy;
44 }
45
46 memcpy(&dst[off], src, sz);
47 }
48
mangle_Byte(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz UNUSED,size_t off)49 static void mangle_Byte(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz UNUSED, size_t off)
50 {
51 buf[off] = (uint8_t) util_rndGet(0, UINT8_MAX);
52 }
53
mangle_Bytes(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)54 static void mangle_Bytes(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
55 {
56 uint32_t val = (uint32_t) util_rndGet(0, UINT32_MAX);
57
58 /* Overwrite with random 2,3,4-byte values */
59 size_t toCopy = util_rndGet(2, 4);
60 mangle_Overwrite(buf, (uint8_t *) & val, bufSz, off, toCopy);
61 }
62
mangle_Bit(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz UNUSED,size_t off)63 static void mangle_Bit(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz UNUSED, size_t off)
64 {
65 buf[off] ^= (uint8_t) (1U << util_rndGet(0, 7));
66 }
67
mangle_Dictionary(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)68 static void mangle_Dictionary(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
69 {
70 if (hfuzz->dictionaryCnt == 0) {
71 mangle_Bit(hfuzz, buf, bufSz, off);
72 return;
73 }
74
75 uint64_t choice = util_rndGet(0, hfuzz->dictionaryCnt - 1);
76 mangle_Overwrite(buf, (uint8_t *) hfuzz->dictionary[choice], bufSz, off,
77 strlen(hfuzz->dictionary[choice]));
78 }
79
mangle_Magic(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)80 static void mangle_Magic(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
81 {
82 /* *INDENT-OFF* */
83 static const struct {
84 const uint8_t val[8];
85 const size_t size;
86 } mangleMagicVals[] = {
87 /* 1B - No endianness */
88 { "\x00\x00\x00\x00\x00\x00\x00\x00", 1},
89 { "\x01\x00\x00\x00\x00\x00\x00\x00", 1},
90 { "\x02\x00\x00\x00\x00\x00\x00\x00", 1},
91 { "\x03\x00\x00\x00\x00\x00\x00\x00", 1},
92 { "\x04\x00\x00\x00\x00\x00\x00\x00", 1},
93 { "\x7E\x00\x00\x00\x00\x00\x00\x00", 1},
94 { "\x7F\x00\x00\x00\x00\x00\x00\x00", 1},
95 { "\x80\x00\x00\x00\x00\x00\x00\x00", 1},
96 { "\x81\x00\x00\x00\x00\x00\x00\x00", 1},
97 { "\xFE\x00\x00\x00\x00\x00\x00\x00", 1},
98 { "\xFF\x00\x00\x00\x00\x00\x00\x00", 1},
99 /* 2B - NE */
100 { "\x00\x00\x00\x00\x00\x00\x00\x00", 2},
101 { "\x01\x01\x00\x00\x00\x00\x00\x00", 2},
102 { "\x80\x80\x00\x00\x00\x00\x00\x00", 2},
103 { "\xFF\xFF\x00\x00\x00\x00\x00\x00", 2},
104 /* 2B - BE */
105 { "\x00\x01\x00\x00\x00\x00\x00\x00", 2},
106 { "\x00\x02\x00\x00\x00\x00\x00\x00", 2},
107 { "\x00\x03\x00\x00\x00\x00\x00\x00", 2},
108 { "\x00\x04\x00\x00\x00\x00\x00\x00", 2},
109 { "\x7E\xFF\x00\x00\x00\x00\x00\x00", 2},
110 { "\x7F\xFF\x00\x00\x00\x00\x00\x00", 2},
111 { "\x80\x00\x00\x00\x00\x00\x00\x00", 2},
112 { "\x80\x01\x00\x00\x00\x00\x00\x00", 2},
113 { "\xFF\xFE\x00\x00\x00\x00\x00\x00", 2},
114 /* 2B - LE */
115 { "\x01\x00\x00\x00\x00\x00\x00\x00", 2},
116 { "\x02\x00\x00\x00\x00\x00\x00\x00", 2},
117 { "\x03\x00\x00\x00\x00\x00\x00\x00", 2},
118 { "\x04\x00\x00\x00\x00\x00\x00\x00", 2},
119 { "\xFF\x7E\x00\x00\x00\x00\x00\x00", 2},
120 { "\xFF\x7F\x00\x00\x00\x00\x00\x00", 2},
121 { "\x00\x80\x00\x00\x00\x00\x00\x00", 2},
122 { "\x01\x80\x00\x00\x00\x00\x00\x00", 2},
123 { "\xFE\xFF\x00\x00\x00\x00\x00\x00", 2},
124 /* 4B - NE */
125 { "\x00\x00\x00\x00\x00\x00\x00\x00", 4},
126 { "\x01\x01\x01\x01\x00\x00\x00\x00", 4},
127 { "\x80\x80\x80\x80\x00\x00\x00\x00", 4},
128 { "\xFF\xFF\xFF\xFF\x00\x00\x00\x00", 4},
129 /* 4B - BE */
130 { "\x00\x00\x00\x01\x00\x00\x00\x00", 4},
131 { "\x00\x00\x00\x02\x00\x00\x00\x00", 4},
132 { "\x00\x00\x00\x03\x00\x00\x00\x00", 4},
133 { "\x00\x00\x00\x04\x00\x00\x00\x00", 4},
134 { "\x7E\xFF\xFF\xFF\x00\x00\x00\x00", 4},
135 { "\x7F\xFF\xFF\xFF\x00\x00\x00\x00", 4},
136 { "\x80\x00\x00\x00\x00\x00\x00\x00", 4},
137 { "\x80\x00\x00\x01\x00\x00\x00\x00", 4},
138 { "\xFF\xFF\xFF\xFE\x00\x00\x00\x00", 4},
139 /* 4B - LE */
140 { "\x01\x00\x00\x00\x00\x00\x00\x00", 4},
141 { "\x02\x00\x00\x00\x00\x00\x00\x00", 4},
142 { "\x03\x00\x00\x00\x00\x00\x00\x00", 4},
143 { "\x04\x00\x00\x00\x00\x00\x00\x00", 4},
144 { "\xFF\xFF\xFF\x7E\x00\x00\x00\x00", 4},
145 { "\xFF\xFF\xFF\x7F\x00\x00\x00\x00", 4},
146 { "\x00\x00\x00\x80\x00\x00\x00\x00", 4},
147 { "\x01\x00\x00\x80\x00\x00\x00\x00", 4},
148 { "\xFE\xFF\xFF\xFF\x00\x00\x00\x00", 4},
149 /* 8B - NE */
150 { "\x00\x00\x00\x00\x00\x00\x00\x00", 8},
151 { "\x01\x01\x01\x01\x01\x01\x01\x01", 8},
152 { "\x80\x80\x80\x80\x80\x80\x80\x80", 8},
153 { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
154 /* 8B - BE */
155 { "\x00\x00\x00\x00\x00\x00\x00\x01", 8},
156 { "\x00\x00\x00\x00\x00\x00\x00\x02", 8},
157 { "\x00\x00\x00\x00\x00\x00\x00\x03", 8},
158 { "\x00\x00\x00\x00\x00\x00\x00\x04", 8},
159 { "\x7E\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
160 { "\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
161 { "\x80\x00\x00\x00\x00\x00\x00\x00", 8},
162 { "\x80\x00\x00\x00\x00\x00\x00\x01", 8},
163 { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE", 8},
164 /* 8B - LE */
165 { "\x01\x00\x00\x00\x00\x00\x00\x00", 8},
166 { "\x02\x00\x00\x00\x00\x00\x00\x00", 8},
167 { "\x03\x00\x00\x00\x00\x00\x00\x00", 8},
168 { "\x04\x00\x00\x00\x00\x00\x00\x00", 8},
169 { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7E", 8},
170 { "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F", 8},
171 { "\x00\x00\x00\x00\x00\x00\x00\x80", 8},
172 { "\x01\x00\x00\x00\x00\x00\x00\x80", 8},
173 { "\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
174 };
175 /* *INDENT-ON* */
176
177 uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
178 mangle_Overwrite(buf, mangleMagicVals[choice].val, bufSz, off, mangleMagicVals[choice].size);
179 }
180
mangle_MemSet(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)181 static void mangle_MemSet(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
182 {
183 uint64_t sz = util_rndGet(1, bufSz - off);
184 int val = (int)util_rndGet(0, UINT8_MAX);
185
186 memset(&buf[off], val, sz);
187 }
188
mangle_MemMove(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)189 static void mangle_MemMove(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
190 {
191 uint64_t mangleTo = util_rndGet(0, bufSz - 1);
192 uint64_t mangleSzTo = bufSz - mangleTo;
193
194 uint64_t mangleSzFrom = util_rndGet(1, bufSz - off);
195 uint64_t mangleSz = mangleSzFrom < mangleSzTo ? mangleSzFrom : mangleSzTo;
196
197 memmove(&buf[mangleTo], &buf[off], mangleSz);
198 }
199
mangle_Random(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)200 static void mangle_Random(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
201 {
202 uint64_t sz = util_rndGet(1, bufSz - off);
203 util_rndBuf(&buf[off], sz);
204 }
205
mangle_AddSub(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz,size_t off)206 static void mangle_AddSub(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz, size_t off)
207 {
208 /* 1,2,4 */
209 uint64_t varLen = 1ULL << util_rndGet(0, 2);
210 if ((bufSz - off) < varLen) {
211 varLen = 1;
212 }
213
214 int delta = (int)util_rndGet(0, 64);
215 delta -= 32;
216
217 switch (varLen) {
218 case 1:
219 {
220 buf[off] += delta;
221 return;
222 break;
223 }
224 case 2:
225 {
226 uint16_t val = *((uint16_t *) & buf[off]);
227 if (util_rndGet(0, 1) == 0) {
228 /* BE */
229 val = util_ToFromBE16(val);
230 val += delta;
231 val = util_ToFromBE16(val);
232 } else {
233 /* LE */
234 val = util_ToFromLE16(val);
235 val += delta;
236 val = util_ToFromLE16(val);
237 }
238 mangle_Overwrite(buf, (uint8_t *) & val, bufSz, off, varLen);
239 return;
240 break;
241 }
242 case 4:
243 {
244 uint32_t val = *((uint32_t *) & buf[off]);
245 if (util_rndGet(0, 1) == 0) {
246 /* BE */
247 val = util_ToFromBE32(val);
248 val += delta;
249 val = util_ToFromBE32(val);
250 } else {
251 /* LE */
252 val = util_ToFromLE32(val);
253 val += delta;
254 val = util_ToFromLE32(val);
255 }
256 mangle_Overwrite(buf, (uint8_t *) & val, bufSz, off, varLen);
257 return;
258 break;
259 }
260 default:
261 {
262 LOG_F("Unknown variable length size: %" PRIu64, varLen);
263 break;
264 }
265 }
266 }
267
mangle_IncByte(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz UNUSED,size_t off)268 static void mangle_IncByte(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz UNUSED,
269 size_t off)
270 {
271 buf[off] += (uint8_t) 1UL;
272 }
273
mangle_DecByte(honggfuzz_t * hfuzz UNUSED,uint8_t * buf,size_t bufSz UNUSED,size_t off)274 static void mangle_DecByte(honggfuzz_t * hfuzz UNUSED, uint8_t * buf, size_t bufSz UNUSED,
275 size_t off)
276 {
277 buf[off] -= (uint8_t) 1UL;
278 }
279
mangle_mangleContent(honggfuzz_t * hfuzz,fuzzer_t * fuzzer)280 void mangle_mangleContent(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
281 {
282 /* *INDENT-OFF* */
283 static void (*const mangleFuncs[]) (honggfuzz_t * hfuzz, uint8_t * buf, size_t bufSz, size_t off) = {
284 mangle_Byte,
285 mangle_Byte,
286 mangle_Byte,
287 mangle_Byte,
288 mangle_Bit,
289 mangle_Bit,
290 mangle_Bytes,
291 mangle_Bytes,
292 mangle_Magic,
293 mangle_Magic,
294 mangle_IncByte,
295 mangle_DecByte,
296 mangle_AddSub,
297 mangle_Dictionary,
298 mangle_MemMove,
299 mangle_MemSet,
300 mangle_Random,
301 };
302 /* *INDENT-ON* */
303
304 /*
305 * Minimal number of changes is 1
306 */
307 uint64_t changesCnt = fuzzer->dynamicFileSz * fuzzer->flipRate;
308 if (changesCnt == 0ULL) {
309 changesCnt = 1;
310 }
311 changesCnt = util_rndGet(1, changesCnt);
312
313 for (uint64_t x = 0; x < changesCnt; x++) {
314 size_t offset = util_rndGet(0, fuzzer->dynamicFileSz - 1);
315 uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
316 mangleFuncs[choice] (hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz, offset);
317 }
318 }
319
mangle_ExpDist(void)320 static double mangle_ExpDist(void)
321 {
322 double rnd = (double)util_rndGet(1, UINT32_MAX) / (double)(UINT32_MAX);
323 return pow(rnd, 4.0L);
324 }
325
326 /* Gauss-like distribution */
mangle_Resize(honggfuzz_t * hfuzz,uint8_t * buf,size_t * bufSz)327 bool mangle_Resize(honggfuzz_t * hfuzz, uint8_t * buf, size_t * bufSz)
328 {
329 const uint64_t chance_one_in_x = 5;
330 if (util_rndGet(1, chance_one_in_x) != 1) {
331 return true;
332 }
333 ssize_t newSz = *bufSz;
334 int delta = 0;
335 unsigned int val = (unsigned int)util_rndGet(1, 64);
336
337 /* *INDENT-OFF* */
338 switch (val) {
339 case 1 ... 16:
340 delta = -val;
341 break;
342 case 17 ... 32:
343 delta = val - 16;
344 break;
345 case 33 ... 48:
346 delta += (int)(mangle_ExpDist() * (double)((hfuzz->maxFileSz - *bufSz)));
347 break;
348 case 49 ... 64:
349 delta -= (int)(mangle_ExpDist() * (double)(*bufSz));
350 break;
351 default:
352 LOG_F("Random value out of scope %u", val);
353 break;
354 }
355 /* *INDENT-ON* */
356
357 newSz += delta;
358
359 if (newSz < 1) {
360 newSz = 1;
361 }
362 if (newSz > (ssize_t) hfuzz->maxFileSz) {
363 newSz = (ssize_t) hfuzz->maxFileSz;
364 }
365
366 if ((size_t) newSz > *bufSz) {
367 util_rndBuf(&buf[*bufSz], newSz - *bufSz);
368 }
369
370 LOG_D("Current size: %zu, Maximal size: %zu, New Size: %zu, Delta: %d", *bufSz,
371 hfuzz->maxFileSz, newSz, delta);
372
373 *bufSz = (size_t) newSz;
374 return true;
375 }
376