/ base / fuzzer.c
fuzzer.c
  1  /*
  2   * Copyright (c) 2011 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Portions Copyright (c) 2011 - 2013 Apple Inc. All rights reserved.
  7   *
  8   * Redistribution and use in source and binary forms, with or without
  9   * modification, are permitted provided that the following conditions
 10   * are met:
 11   *
 12   * 1. Redistributions of source code must retain the above copyright
 13   *    notice, this list of conditions and the following disclaimer.
 14   *
 15   * 2. Redistributions in binary form must reproduce the above copyright
 16   *    notice, this list of conditions and the following disclaimer in the
 17   *    documentation and/or other materials provided with the distribution.
 18   *
 19   * 3. Neither the name of the Institute nor the names of its contributors
 20   *    may be used to endorse or promote products derived from this software
 21   *    without specific prior written permission.
 22   *
 23   * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 24   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 25   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 26   * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 27   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 28   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 29   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 30   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 31   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 32   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 33   * SUCH DAMAGE.
 34   */
 35  
 36  #include <sys/types.h>
 37  #include <inttypes.h>
 38  #include <roken.h>
 39  #define HEIM_FUZZER_INTERNALS 1
 40  #include "fuzzer.h"
 41  
 42  #define SIZE(_array) (sizeof(_array) / sizeof((_array)[0]))
 43  
 44  /*
 45   *
 46   */
 47  
 48  static void
 49  null_free(void *ctx)
 50  {
 51      if (ctx != NULL)
 52  	abort();
 53  }
 54  
 55  /*
 56   *
 57   */
 58  
 59  #define MIN_RANDOM_TRIES 30000
 60  
 61  static unsigned long
 62  random_tries(size_t length)
 63  {
 64      length = length * 12;
 65      if (length < MIN_RANDOM_TRIES)
 66  	length = MIN_RANDOM_TRIES;
 67      return (unsigned long)length;
 68  }
 69  
 70  static int
 71  random_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
 72  {
 73      *ctx = NULL;
 74  
 75      if (iteration > MIN_RANDOM_TRIES && iteration > length * 12)
 76  	return 1;
 77  
 78      data[rk_random() % length] = rk_random();
 79  
 80      return 0;
 81  }
 82  
 83  
 84  const struct heim_fuzz_type_data __heim_fuzz_random = {
 85      "random",
 86      random_tries,
 87      random_fuzz,
 88      null_free
 89  };
 90  
 91  /*
 92   *
 93   */
 94  
 95  static unsigned long
 96  bitflip_tries(size_t length)
 97  {
 98      return length << 3;
 99  }
100  
101  static int
102  bitflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
103  {
104      *ctx = NULL;
105      if ((iteration >> 3) >= length)
106  	return 1;
107      data[iteration >> 3] ^= (1 << (iteration & 7));
108  
109      return 0;
110  }
111  
112  const struct heim_fuzz_type_data __heim_fuzz_bitflip = {
113      "bitflip",
114      bitflip_tries,
115      bitflip_fuzz,
116      null_free
117  };
118  
119  /*
120   *
121   */
122  
123  static unsigned long
124  byteflip_tries(size_t length)
125  {
126      return length;
127  }
128  
129  static int
130  byteflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
131  {
132      *ctx = NULL;
133      if (iteration >= length)
134  	return 1;
135      data[iteration] ^= 0xff;
136  
137      return 0;
138  }
139  
140  const struct heim_fuzz_type_data __heim_fuzz_byteflip = {
141      "byteflip",
142      byteflip_tries,
143      byteflip_fuzz,
144      null_free
145  };
146  
147  /*
148   *
149   */
150  
151  static unsigned long
152  shortflip_tries(size_t length)
153  {
154      return length / 2;
155  }
156  
157  static int
158  shortflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
159  {
160      *ctx = NULL;
161      if (iteration + 1 >= length / 2)
162  	return 1;
163      data[iteration + 0] ^= 0xff;
164      data[iteration + 1] ^= 0xff;
165  
166      return 0;
167  }
168  
169  const struct heim_fuzz_type_data __heim_fuzz_shortflip = {
170      "shortflip",
171      shortflip_tries,
172      shortflip_fuzz,
173      null_free
174  };
175  
176  /*
177   *
178   */
179  
180  static unsigned long
181  wordflip_tries(size_t length)
182  {
183      return length / 4;
184  }
185  
186  static int
187  wordflip_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
188  {
189      if (ctx)
190  	*ctx = NULL;
191      if (iteration + 3 >= length / 4)
192  	return 1;
193      data[iteration + 0] ^= 0xff;
194      data[iteration + 1] ^= 0xff;
195      data[iteration + 2] ^= 0xff;
196      data[iteration + 3] ^= 0xff;
197  
198      return 0;
199  }
200  
201  const struct heim_fuzz_type_data __heim_fuzz_wordflip = {
202      "wordflip",
203      wordflip_tries,
204      wordflip_fuzz,
205      null_free
206  };
207  
208  /*
209   * interesting values picked from AFL
210   */
211  
212  static uint8_t interesting_u8[] = {
213      -128,
214      -1,
215      0,
216      1,
217      16,
218      32,
219      64,
220      100,
221      127
222  };
223  
224  static uint16_t interesting_u16[] = {
225      (uint16_t)-32768,
226      (uint16_t)-129,
227      128,
228      255,
229      256,
230      512,
231      1000,
232      1024,
233      4096,
234      32767
235  };
236  
237  static uint32_t interesting_u32[] = {
238      (uint32_t)-2147483648LL,
239      (uint32_t)-100000000,
240      (uint32_t)-32769,
241      32768,
242     65535,
243     65536,
244     100000000,
245     2147483647
246  };
247  
248  
249  static unsigned long
250  interesting_tries(size_t length)
251  {
252      return length;
253  }
254  
255  static int
256  interesting8_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
257  {
258      if (length < iteration / SIZE(interesting_u8))
259  	return 1;
260  
261      memcpy(&data[iteration % SIZE(interesting_u8)], &interesting_u8[iteration / SIZE(interesting_u8)], 1);
262      return 0;
263  }
264  
265  const struct heim_fuzz_type_data __heim_fuzz_interesting8 = {
266      "interesting uint8",
267      interesting_tries,
268      interesting8_fuzz,
269      null_free
270  };
271  
272  static int
273  interesting16_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
274  {
275      if (length < 1 + (iteration / SIZE(interesting_u16)))
276  	return 1;
277  
278      memcpy(&data[iteration % SIZE(interesting_u16)], &interesting_u16[iteration / SIZE(interesting_u16)], 2);
279      return 0;
280  }
281  
282  const struct heim_fuzz_type_data __heim_fuzz_interesting16 = {
283      "interesting uint16",
284      interesting_tries,
285      interesting16_fuzz,
286      null_free
287  };
288  
289  static int
290  interesting32_fuzz(void **ctx, unsigned long iteration, uint8_t *data, size_t length)
291  {
292      if (length < 3 + (iteration / SIZE(interesting_u32)))
293  	return 1;
294  
295      memcpy(&data[iteration % SIZE(interesting_u32)], &interesting_u32[iteration / SIZE(interesting_u32)], 4);
296      return 0;
297  }
298  
299  const struct heim_fuzz_type_data __heim_fuzz_interesting32 = {
300      "interesting uint32",
301      interesting_tries,
302      interesting32_fuzz,
303      null_free
304  };
305  
306  /*
307   *
308   */
309  
310  const char *
311  heim_fuzzer_name(heim_fuzz_type_t type)
312  {
313      return type->name;
314  }
315  
316  unsigned long
317  heim_fuzzer_tries(heim_fuzz_type_t type, size_t length)
318  {
319      return type->tries(length);
320  }
321  
322  int
323  heim_fuzzer(heim_fuzz_type_t type,
324  	    void **ctx, 
325  	    unsigned long iteration,
326  	    uint8_t *data,
327  	    size_t length)
328  {
329      if (length == 0)
330  	return 1;
331      return type->fuzz(ctx, iteration, data, length);
332  }
333  
334  void
335  heim_fuzzer_free(heim_fuzz_type_t type,
336  		 void *ctx)
337  {
338      if (ctx != NULL)
339  	type->freectx(ctx);
340  }