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 }