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