1*bc5531deSDag-Erling Smørgrav /* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */ 2a0ee8cc6SDag-Erling Smørgrav /* 3a0ee8cc6SDag-Erling Smørgrav * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 4a0ee8cc6SDag-Erling Smørgrav * 5a0ee8cc6SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6a0ee8cc6SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7a0ee8cc6SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 8a0ee8cc6SDag-Erling Smørgrav * 9a0ee8cc6SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10a0ee8cc6SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11a0ee8cc6SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12a0ee8cc6SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13a0ee8cc6SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14a0ee8cc6SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15a0ee8cc6SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16a0ee8cc6SDag-Erling Smørgrav */ 17a0ee8cc6SDag-Erling Smørgrav 18a0ee8cc6SDag-Erling Smørgrav /* Utility functions/framework for fuzz tests */ 19a0ee8cc6SDag-Erling Smørgrav 20a0ee8cc6SDag-Erling Smørgrav #include "includes.h" 21a0ee8cc6SDag-Erling Smørgrav 22a0ee8cc6SDag-Erling Smørgrav #include <sys/types.h> 23*bc5531deSDag-Erling Smørgrav #include <sys/uio.h> 24a0ee8cc6SDag-Erling Smørgrav 25a0ee8cc6SDag-Erling Smørgrav #include <assert.h> 26a0ee8cc6SDag-Erling Smørgrav #include <ctype.h> 27a0ee8cc6SDag-Erling Smørgrav #include <stdio.h> 28a0ee8cc6SDag-Erling Smørgrav #ifdef HAVE_STDINT_H 29a0ee8cc6SDag-Erling Smørgrav # include <stdint.h> 30a0ee8cc6SDag-Erling Smørgrav #endif 31a0ee8cc6SDag-Erling Smørgrav #include <stdlib.h> 32a0ee8cc6SDag-Erling Smørgrav #include <string.h> 33*bc5531deSDag-Erling Smørgrav #include <signal.h> 34*bc5531deSDag-Erling Smørgrav #include <unistd.h> 35a0ee8cc6SDag-Erling Smørgrav 36a0ee8cc6SDag-Erling Smørgrav #include "test_helper.h" 37*bc5531deSDag-Erling Smørgrav #include "atomicio.h" 38a0ee8cc6SDag-Erling Smørgrav 39a0ee8cc6SDag-Erling Smørgrav /* #define FUZZ_DEBUG */ 40a0ee8cc6SDag-Erling Smørgrav 41a0ee8cc6SDag-Erling Smørgrav #ifdef FUZZ_DEBUG 42a0ee8cc6SDag-Erling Smørgrav # define FUZZ_DBG(x) do { \ 43a0ee8cc6SDag-Erling Smørgrav printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ 44a0ee8cc6SDag-Erling Smørgrav printf x; \ 45a0ee8cc6SDag-Erling Smørgrav printf("\n"); \ 46a0ee8cc6SDag-Erling Smørgrav fflush(stdout); \ 47a0ee8cc6SDag-Erling Smørgrav } while (0) 48a0ee8cc6SDag-Erling Smørgrav #else 49a0ee8cc6SDag-Erling Smørgrav # define FUZZ_DBG(x) 50a0ee8cc6SDag-Erling Smørgrav #endif 51a0ee8cc6SDag-Erling Smørgrav 52a0ee8cc6SDag-Erling Smørgrav /* For brevity later */ 53a0ee8cc6SDag-Erling Smørgrav typedef unsigned long long fuzz_ullong; 54a0ee8cc6SDag-Erling Smørgrav 55a0ee8cc6SDag-Erling Smørgrav /* For base-64 fuzzing */ 56a0ee8cc6SDag-Erling Smørgrav static const char fuzz_b64chars[] = 57a0ee8cc6SDag-Erling Smørgrav "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 58a0ee8cc6SDag-Erling Smørgrav 59a0ee8cc6SDag-Erling Smørgrav struct fuzz { 60a0ee8cc6SDag-Erling Smørgrav /* Fuzz method currently in use */ 61a0ee8cc6SDag-Erling Smørgrav int strategy; 62a0ee8cc6SDag-Erling Smørgrav 63a0ee8cc6SDag-Erling Smørgrav /* Fuzz methods remaining */ 64a0ee8cc6SDag-Erling Smørgrav int strategies; 65a0ee8cc6SDag-Erling Smørgrav 66a0ee8cc6SDag-Erling Smørgrav /* Original seed data blob */ 67a0ee8cc6SDag-Erling Smørgrav void *seed; 68a0ee8cc6SDag-Erling Smørgrav size_t slen; 69a0ee8cc6SDag-Erling Smørgrav 70a0ee8cc6SDag-Erling Smørgrav /* Current working copy of seed with fuzz mutations applied */ 71a0ee8cc6SDag-Erling Smørgrav u_char *fuzzed; 72a0ee8cc6SDag-Erling Smørgrav 73a0ee8cc6SDag-Erling Smørgrav /* Used by fuzz methods */ 74a0ee8cc6SDag-Erling Smørgrav size_t o1, o2; 75a0ee8cc6SDag-Erling Smørgrav }; 76a0ee8cc6SDag-Erling Smørgrav 77a0ee8cc6SDag-Erling Smørgrav static const char * 78a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(u_int n) 79a0ee8cc6SDag-Erling Smørgrav { 80a0ee8cc6SDag-Erling Smørgrav switch (n) { 81a0ee8cc6SDag-Erling Smørgrav case 0: 82a0ee8cc6SDag-Erling Smørgrav return "NONE"; 83a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 84a0ee8cc6SDag-Erling Smørgrav return "FUZZ_1_BIT_FLIP"; 85a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 86a0ee8cc6SDag-Erling Smørgrav return "FUZZ_2_BIT_FLIP"; 87a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 88a0ee8cc6SDag-Erling Smørgrav return "FUZZ_1_BYTE_FLIP"; 89a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 90a0ee8cc6SDag-Erling Smørgrav return "FUZZ_2_BYTE_FLIP"; 91a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 92a0ee8cc6SDag-Erling Smørgrav return "FUZZ_TRUNCATE_START"; 93a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 94a0ee8cc6SDag-Erling Smørgrav return "FUZZ_TRUNCATE_END"; 95a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 96a0ee8cc6SDag-Erling Smørgrav return "FUZZ_BASE64"; 97a0ee8cc6SDag-Erling Smørgrav default: 98a0ee8cc6SDag-Erling Smørgrav abort(); 99a0ee8cc6SDag-Erling Smørgrav } 100a0ee8cc6SDag-Erling Smørgrav } 101a0ee8cc6SDag-Erling Smørgrav 102*bc5531deSDag-Erling Smørgrav static int 103*bc5531deSDag-Erling Smørgrav fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) 104a0ee8cc6SDag-Erling Smørgrav { 105*bc5531deSDag-Erling Smørgrav if (fuzz == NULL) 106*bc5531deSDag-Erling Smørgrav return -1; 107a0ee8cc6SDag-Erling Smørgrav 108a0ee8cc6SDag-Erling Smørgrav switch (fuzz->strategy) { 109a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 110*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n", 111a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 112a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->slen * 8, fuzz->o1); 113*bc5531deSDag-Erling Smørgrav return 0; 114a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 115*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n", 116a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 117a0ee8cc6SDag-Erling Smørgrav (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, 118a0ee8cc6SDag-Erling Smørgrav ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, 119a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->o2); 120*bc5531deSDag-Erling Smørgrav return 0; 121a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 122*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n", 123a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 124a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->slen, fuzz->o1); 125*bc5531deSDag-Erling Smørgrav return 0; 126a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 127*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n", 128a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 129a0ee8cc6SDag-Erling Smørgrav (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, 130a0ee8cc6SDag-Erling Smørgrav ((fuzz_ullong)fuzz->slen) * fuzz->slen, 131a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->o2); 132*bc5531deSDag-Erling Smørgrav return 0; 133a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 134*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", 135a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 136a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->slen, fuzz->o1); 137*bc5531deSDag-Erling Smørgrav return 0; 138a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 139*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", 140a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 141a0ee8cc6SDag-Erling Smørgrav fuzz->o1, fuzz->slen, fuzz->o1); 142*bc5531deSDag-Erling Smørgrav return 0; 143a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 144a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); 145*bc5531deSDag-Erling Smørgrav snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n", 146a0ee8cc6SDag-Erling Smørgrav fuzz_ntop(fuzz->strategy), 147a0ee8cc6SDag-Erling Smørgrav (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, 148a0ee8cc6SDag-Erling Smørgrav fuzz->slen * (fuzz_ullong)64, fuzz->o1, 149a0ee8cc6SDag-Erling Smørgrav fuzz_b64chars[fuzz->o2]); 150*bc5531deSDag-Erling Smørgrav return 0; 151a0ee8cc6SDag-Erling Smørgrav default: 152*bc5531deSDag-Erling Smørgrav return -1; 153a0ee8cc6SDag-Erling Smørgrav abort(); 154a0ee8cc6SDag-Erling Smørgrav } 155*bc5531deSDag-Erling Smørgrav } 156a0ee8cc6SDag-Erling Smørgrav 157*bc5531deSDag-Erling Smørgrav static void 158*bc5531deSDag-Erling Smørgrav dump(u_char *p, size_t len) 159*bc5531deSDag-Erling Smørgrav { 160*bc5531deSDag-Erling Smørgrav size_t i, j; 161*bc5531deSDag-Erling Smørgrav 162a0ee8cc6SDag-Erling Smørgrav for (i = 0; i < len; i += 16) { 163a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, "%.4zd: ", i); 164a0ee8cc6SDag-Erling Smørgrav for (j = i; j < i + 16; j++) { 165a0ee8cc6SDag-Erling Smørgrav if (j < len) 166a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, "%02x ", p[j]); 167a0ee8cc6SDag-Erling Smørgrav else 168a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, " "); 169a0ee8cc6SDag-Erling Smørgrav } 170a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, " "); 171a0ee8cc6SDag-Erling Smørgrav for (j = i; j < i + 16; j++) { 172a0ee8cc6SDag-Erling Smørgrav if (j < len) { 173a0ee8cc6SDag-Erling Smørgrav if (isascii(p[j]) && isprint(p[j])) 174a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, "%c", p[j]); 175a0ee8cc6SDag-Erling Smørgrav else 176a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, "."); 177a0ee8cc6SDag-Erling Smørgrav } 178a0ee8cc6SDag-Erling Smørgrav } 179a0ee8cc6SDag-Erling Smørgrav fprintf(stderr, "\n"); 180a0ee8cc6SDag-Erling Smørgrav } 181a0ee8cc6SDag-Erling Smørgrav } 182a0ee8cc6SDag-Erling Smørgrav 183*bc5531deSDag-Erling Smørgrav void 184*bc5531deSDag-Erling Smørgrav fuzz_dump(struct fuzz *fuzz) 185*bc5531deSDag-Erling Smørgrav { 186*bc5531deSDag-Erling Smørgrav char buf[256]; 187*bc5531deSDag-Erling Smørgrav 188*bc5531deSDag-Erling Smørgrav if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) { 189*bc5531deSDag-Erling Smørgrav fprintf(stderr, "%s: fuzz invalid\n", __func__); 190*bc5531deSDag-Erling Smørgrav abort(); 191*bc5531deSDag-Erling Smørgrav } 192*bc5531deSDag-Erling Smørgrav fputs(buf, stderr); 193*bc5531deSDag-Erling Smørgrav fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen); 194*bc5531deSDag-Erling Smørgrav dump(fuzz->seed, fuzz->slen); 195*bc5531deSDag-Erling Smørgrav fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz)); 196*bc5531deSDag-Erling Smørgrav dump(fuzz_ptr(fuzz), fuzz_len(fuzz)); 197*bc5531deSDag-Erling Smørgrav } 198*bc5531deSDag-Erling Smørgrav 199*bc5531deSDag-Erling Smørgrav #ifdef SIGINFO 200*bc5531deSDag-Erling Smørgrav static struct fuzz *last_fuzz; 201*bc5531deSDag-Erling Smørgrav 202*bc5531deSDag-Erling Smørgrav static void 203*bc5531deSDag-Erling Smørgrav siginfo(int unused __attribute__((__unused__))) 204*bc5531deSDag-Erling Smørgrav { 205*bc5531deSDag-Erling Smørgrav char buf[256]; 206*bc5531deSDag-Erling Smørgrav 207*bc5531deSDag-Erling Smørgrav test_info(buf, sizeof(buf)); 208*bc5531deSDag-Erling Smørgrav atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); 209*bc5531deSDag-Erling Smørgrav if (last_fuzz != NULL) { 210*bc5531deSDag-Erling Smørgrav fuzz_fmt(last_fuzz, buf, sizeof(buf)); 211*bc5531deSDag-Erling Smørgrav atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); 212*bc5531deSDag-Erling Smørgrav } 213*bc5531deSDag-Erling Smørgrav } 214*bc5531deSDag-Erling Smørgrav #endif 215*bc5531deSDag-Erling Smørgrav 216a0ee8cc6SDag-Erling Smørgrav struct fuzz * 217a0ee8cc6SDag-Erling Smørgrav fuzz_begin(u_int strategies, const void *p, size_t l) 218a0ee8cc6SDag-Erling Smørgrav { 219a0ee8cc6SDag-Erling Smørgrav struct fuzz *ret = calloc(sizeof(*ret), 1); 220a0ee8cc6SDag-Erling Smørgrav 221a0ee8cc6SDag-Erling Smørgrav assert(p != NULL); 222a0ee8cc6SDag-Erling Smørgrav assert(ret != NULL); 223a0ee8cc6SDag-Erling Smørgrav ret->seed = malloc(l); 224a0ee8cc6SDag-Erling Smørgrav assert(ret->seed != NULL); 225a0ee8cc6SDag-Erling Smørgrav memcpy(ret->seed, p, l); 226a0ee8cc6SDag-Erling Smørgrav ret->slen = l; 227a0ee8cc6SDag-Erling Smørgrav ret->strategies = strategies; 228a0ee8cc6SDag-Erling Smørgrav 229a0ee8cc6SDag-Erling Smørgrav assert(ret->slen < SIZE_MAX / 8); 230a0ee8cc6SDag-Erling Smørgrav assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); 231a0ee8cc6SDag-Erling Smørgrav 232a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("begin, ret = %p", ret)); 233a0ee8cc6SDag-Erling Smørgrav 234a0ee8cc6SDag-Erling Smørgrav fuzz_next(ret); 235*bc5531deSDag-Erling Smørgrav 236*bc5531deSDag-Erling Smørgrav #ifdef SIGINFO 237*bc5531deSDag-Erling Smørgrav last_fuzz = ret; 238*bc5531deSDag-Erling Smørgrav signal(SIGINFO, siginfo); 239*bc5531deSDag-Erling Smørgrav #endif 240*bc5531deSDag-Erling Smørgrav 241a0ee8cc6SDag-Erling Smørgrav return ret; 242a0ee8cc6SDag-Erling Smørgrav } 243a0ee8cc6SDag-Erling Smørgrav 244a0ee8cc6SDag-Erling Smørgrav void 245a0ee8cc6SDag-Erling Smørgrav fuzz_cleanup(struct fuzz *fuzz) 246a0ee8cc6SDag-Erling Smørgrav { 247a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); 248*bc5531deSDag-Erling Smørgrav #ifdef SIGINFO 249*bc5531deSDag-Erling Smørgrav last_fuzz = NULL; 250*bc5531deSDag-Erling Smørgrav signal(SIGINFO, SIG_DFL); 251*bc5531deSDag-Erling Smørgrav #endif 252a0ee8cc6SDag-Erling Smørgrav assert(fuzz != NULL); 253a0ee8cc6SDag-Erling Smørgrav assert(fuzz->seed != NULL); 254a0ee8cc6SDag-Erling Smørgrav assert(fuzz->fuzzed != NULL); 255a0ee8cc6SDag-Erling Smørgrav free(fuzz->seed); 256a0ee8cc6SDag-Erling Smørgrav free(fuzz->fuzzed); 257a0ee8cc6SDag-Erling Smørgrav free(fuzz); 258a0ee8cc6SDag-Erling Smørgrav } 259a0ee8cc6SDag-Erling Smørgrav 260a0ee8cc6SDag-Erling Smørgrav static int 261a0ee8cc6SDag-Erling Smørgrav fuzz_strategy_done(struct fuzz *fuzz) 262a0ee8cc6SDag-Erling Smørgrav { 263a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", 264a0ee8cc6SDag-Erling Smørgrav fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); 265a0ee8cc6SDag-Erling Smørgrav 266a0ee8cc6SDag-Erling Smørgrav switch (fuzz->strategy) { 267a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 268a0ee8cc6SDag-Erling Smørgrav return fuzz->o1 >= fuzz->slen * 8; 269a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 270a0ee8cc6SDag-Erling Smørgrav return fuzz->o2 >= fuzz->slen * 8; 271a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 272a0ee8cc6SDag-Erling Smørgrav return fuzz->o2 >= fuzz->slen; 273a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 274a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 275a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 276a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 277a0ee8cc6SDag-Erling Smørgrav return fuzz->o1 >= fuzz->slen; 278a0ee8cc6SDag-Erling Smørgrav default: 279a0ee8cc6SDag-Erling Smørgrav abort(); 280a0ee8cc6SDag-Erling Smørgrav } 281a0ee8cc6SDag-Erling Smørgrav } 282a0ee8cc6SDag-Erling Smørgrav 283a0ee8cc6SDag-Erling Smørgrav void 284a0ee8cc6SDag-Erling Smørgrav fuzz_next(struct fuzz *fuzz) 285a0ee8cc6SDag-Erling Smørgrav { 286a0ee8cc6SDag-Erling Smørgrav u_int i; 287a0ee8cc6SDag-Erling Smørgrav 288a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " 289a0ee8cc6SDag-Erling Smørgrav "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), 290a0ee8cc6SDag-Erling Smørgrav (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); 291a0ee8cc6SDag-Erling Smørgrav 292a0ee8cc6SDag-Erling Smørgrav if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { 293a0ee8cc6SDag-Erling Smørgrav /* If we are just starting out, we need to allocate too */ 294a0ee8cc6SDag-Erling Smørgrav if (fuzz->fuzzed == NULL) { 295a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("alloc")); 296a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed = calloc(fuzz->slen, 1); 297a0ee8cc6SDag-Erling Smørgrav } 298a0ee8cc6SDag-Erling Smørgrav /* Pick next strategy */ 299a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("advance")); 300a0ee8cc6SDag-Erling Smørgrav for (i = 1; i <= FUZZ_MAX; i <<= 1) { 301a0ee8cc6SDag-Erling Smørgrav if ((fuzz->strategies & i) != 0) { 302a0ee8cc6SDag-Erling Smørgrav fuzz->strategy = i; 303a0ee8cc6SDag-Erling Smørgrav break; 304a0ee8cc6SDag-Erling Smørgrav } 305a0ee8cc6SDag-Erling Smørgrav } 306a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("selected = %u", fuzz->strategy)); 307a0ee8cc6SDag-Erling Smørgrav if (fuzz->strategy == 0) { 308a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("done, no more strategies")); 309a0ee8cc6SDag-Erling Smørgrav return; 310a0ee8cc6SDag-Erling Smørgrav } 311a0ee8cc6SDag-Erling Smørgrav fuzz->strategies &= ~(fuzz->strategy); 312a0ee8cc6SDag-Erling Smørgrav fuzz->o1 = fuzz->o2 = 0; 313a0ee8cc6SDag-Erling Smørgrav } 314a0ee8cc6SDag-Erling Smørgrav 315a0ee8cc6SDag-Erling Smørgrav assert(fuzz->fuzzed != NULL); 316a0ee8cc6SDag-Erling Smørgrav 317a0ee8cc6SDag-Erling Smørgrav switch (fuzz->strategy) { 318a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 319a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 / 8 < fuzz->slen); 320a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 321a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); 322a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 323a0ee8cc6SDag-Erling Smørgrav break; 324a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 325a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 / 8 < fuzz->slen); 326a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o2 / 8 < fuzz->slen); 327a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 328a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); 329a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); 330a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 331a0ee8cc6SDag-Erling Smørgrav if (fuzz->o1 >= fuzz->slen * 8) { 332a0ee8cc6SDag-Erling Smørgrav fuzz->o1 = 0; 333a0ee8cc6SDag-Erling Smørgrav fuzz->o2++; 334a0ee8cc6SDag-Erling Smørgrav } 335a0ee8cc6SDag-Erling Smørgrav break; 336a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 337a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 < fuzz->slen); 338a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 339a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o1] ^= 0xff; 340a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 341a0ee8cc6SDag-Erling Smørgrav break; 342a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 343a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 < fuzz->slen); 344a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o2 < fuzz->slen); 345a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 346a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o1] ^= 0xff; 347a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o2] ^= 0xff; 348a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 349a0ee8cc6SDag-Erling Smørgrav if (fuzz->o1 >= fuzz->slen) { 350a0ee8cc6SDag-Erling Smørgrav fuzz->o1 = 0; 351a0ee8cc6SDag-Erling Smørgrav fuzz->o2++; 352a0ee8cc6SDag-Erling Smørgrav } 353a0ee8cc6SDag-Erling Smørgrav break; 354a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 355a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 356a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 < fuzz->slen); 357a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 358a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 359a0ee8cc6SDag-Erling Smørgrav break; 360a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 361a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 < fuzz->slen); 362a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); 363a0ee8cc6SDag-Erling Smørgrav memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); 364a0ee8cc6SDag-Erling Smørgrav fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; 365a0ee8cc6SDag-Erling Smørgrav fuzz->o2++; 366a0ee8cc6SDag-Erling Smørgrav if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { 367a0ee8cc6SDag-Erling Smørgrav fuzz->o2 = 0; 368a0ee8cc6SDag-Erling Smørgrav fuzz->o1++; 369a0ee8cc6SDag-Erling Smørgrav } 370a0ee8cc6SDag-Erling Smørgrav break; 371a0ee8cc6SDag-Erling Smørgrav default: 372a0ee8cc6SDag-Erling Smørgrav abort(); 373a0ee8cc6SDag-Erling Smørgrav } 374a0ee8cc6SDag-Erling Smørgrav 375a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " 376a0ee8cc6SDag-Erling Smørgrav "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), 377a0ee8cc6SDag-Erling Smørgrav (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); 378a0ee8cc6SDag-Erling Smørgrav } 379a0ee8cc6SDag-Erling Smørgrav 380a0ee8cc6SDag-Erling Smørgrav int 381*bc5531deSDag-Erling Smørgrav fuzz_matches_original(struct fuzz *fuzz) 382*bc5531deSDag-Erling Smørgrav { 383*bc5531deSDag-Erling Smørgrav if (fuzz_len(fuzz) != fuzz->slen) 384*bc5531deSDag-Erling Smørgrav return 0; 385*bc5531deSDag-Erling Smørgrav return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0; 386*bc5531deSDag-Erling Smørgrav } 387*bc5531deSDag-Erling Smørgrav 388*bc5531deSDag-Erling Smørgrav int 389a0ee8cc6SDag-Erling Smørgrav fuzz_done(struct fuzz *fuzz) 390a0ee8cc6SDag-Erling Smørgrav { 391a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, 392a0ee8cc6SDag-Erling Smørgrav (u_long)fuzz->strategies)); 393a0ee8cc6SDag-Erling Smørgrav 394a0ee8cc6SDag-Erling Smørgrav return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; 395a0ee8cc6SDag-Erling Smørgrav } 396a0ee8cc6SDag-Erling Smørgrav 397a0ee8cc6SDag-Erling Smørgrav size_t 398a0ee8cc6SDag-Erling Smørgrav fuzz_len(struct fuzz *fuzz) 399a0ee8cc6SDag-Erling Smørgrav { 400a0ee8cc6SDag-Erling Smørgrav assert(fuzz->fuzzed != NULL); 401a0ee8cc6SDag-Erling Smørgrav switch (fuzz->strategy) { 402a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 403a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 404a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 405a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 406a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 407a0ee8cc6SDag-Erling Smørgrav return fuzz->slen; 408a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 409a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 410a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 <= fuzz->slen); 411a0ee8cc6SDag-Erling Smørgrav return fuzz->slen - fuzz->o1; 412a0ee8cc6SDag-Erling Smørgrav default: 413a0ee8cc6SDag-Erling Smørgrav abort(); 414a0ee8cc6SDag-Erling Smørgrav } 415a0ee8cc6SDag-Erling Smørgrav } 416a0ee8cc6SDag-Erling Smørgrav 417a0ee8cc6SDag-Erling Smørgrav u_char * 418a0ee8cc6SDag-Erling Smørgrav fuzz_ptr(struct fuzz *fuzz) 419a0ee8cc6SDag-Erling Smørgrav { 420a0ee8cc6SDag-Erling Smørgrav assert(fuzz->fuzzed != NULL); 421a0ee8cc6SDag-Erling Smørgrav switch (fuzz->strategy) { 422a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BIT_FLIP: 423a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP: 424a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP: 425a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP: 426a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64: 427a0ee8cc6SDag-Erling Smørgrav return fuzz->fuzzed; 428a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START: 429a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 <= fuzz->slen); 430a0ee8cc6SDag-Erling Smørgrav return fuzz->fuzzed + fuzz->o1; 431a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END: 432a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o1 <= fuzz->slen); 433a0ee8cc6SDag-Erling Smørgrav return fuzz->fuzzed; 434a0ee8cc6SDag-Erling Smørgrav default: 435a0ee8cc6SDag-Erling Smørgrav abort(); 436a0ee8cc6SDag-Erling Smørgrav } 437a0ee8cc6SDag-Erling Smørgrav } 438a0ee8cc6SDag-Erling Smørgrav 439