static int fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) { if (fuzz == NULL) return -1; switch (fuzz->strategy) { case FUZZ_1_BIT_FLIP: snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen * 8, fuzz->o1); return 0; case FUZZ_2_BIT_FLIP: snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n", fuzz_ntop(fuzz->strategy), (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, fuzz->o1, fuzz->o2); return 0; case FUZZ_1_BYTE_FLIP: snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); return 0; case FUZZ_2_BYTE_FLIP: snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n", fuzz_ntop(fuzz->strategy), (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, ((fuzz_ullong)fuzz->slen) * fuzz->slen, fuzz->o1, fuzz->o2); return 0; case FUZZ_TRUNCATE_START: snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); return 0; case FUZZ_TRUNCATE_END: snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); return 0; case FUZZ_BASE64: assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n", fuzz_ntop(fuzz->strategy), (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, fuzz->slen * (fuzz_ullong)64, fuzz->o1, fuzz_b64chars[fuzz->o2]); return 0; default: return -1; abort(); } }
static int fuzz_strategy_done(struct fuzz *fuzz) { FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); switch (fuzz->strategy) { case FUZZ_1_BIT_FLIP: return fuzz->o1 >= fuzz->slen * 8; case FUZZ_2_BIT_FLIP: return fuzz->o2 >= fuzz->slen * 8; case FUZZ_2_BYTE_FLIP: return fuzz->o2 >= fuzz->slen; case FUZZ_1_BYTE_FLIP: case FUZZ_TRUNCATE_START: case FUZZ_TRUNCATE_END: case FUZZ_BASE64: return fuzz->o1 >= fuzz->slen; default: abort(); } }
void fuzz_dump(struct fuzz *fuzz) { u_char *p = fuzz_ptr(fuzz); size_t i, j, len = fuzz_len(fuzz); switch (fuzz->strategy) { case FUZZ_1_BIT_FLIP: fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen * 8, fuzz->o1); break; case FUZZ_2_BIT_FLIP: fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n", fuzz_ntop(fuzz->strategy), (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, fuzz->o1, fuzz->o2); break; case FUZZ_1_BYTE_FLIP: fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); break; case FUZZ_2_BYTE_FLIP: fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n", fuzz_ntop(fuzz->strategy), (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, ((fuzz_ullong)fuzz->slen) * fuzz->slen, fuzz->o1, fuzz->o2); break; case FUZZ_TRUNCATE_START: fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); break; case FUZZ_TRUNCATE_END: fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->slen, fuzz->o1); break; case FUZZ_BASE64: assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n", fuzz_ntop(fuzz->strategy), (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, fuzz->slen * (fuzz_ullong)64, fuzz->o1, fuzz_b64chars[fuzz->o2]); break; default: abort(); } fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len); for (i = 0; i < len; i += 16) { fprintf(stderr, "%.4zd: ", i); for (j = i; j < i + 16; j++) { if (j < len) fprintf(stderr, "%02x ", p[j]); else fprintf(stderr, " "); } fprintf(stderr, " "); for (j = i; j < i + 16; j++) { if (j < len) { if (isascii(p[j]) && isprint(p[j])) fprintf(stderr, "%c", p[j]); else fprintf(stderr, "."); } } fprintf(stderr, "\n"); } }
void fuzz_next(struct fuzz *fuzz) { u_int i; FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { /* If we are just starting out, we need to allocate too */ if (fuzz->fuzzed == NULL) { FUZZ_DBG(("alloc")); fuzz->fuzzed = calloc(fuzz->slen, 1); } /* Pick next strategy */ FUZZ_DBG(("advance")); for (i = 1; i <= FUZZ_MAX; i <<= 1) { if ((fuzz->strategies & i) != 0) { fuzz->strategy = i; break; } } FUZZ_DBG(("selected = %u", fuzz->strategy)); if (fuzz->strategy == 0) { FUZZ_DBG(("done, no more strategies")); return; } fuzz->strategies &= ~(fuzz->strategy); fuzz->o1 = fuzz->o2 = 0; } assert(fuzz->fuzzed != NULL); switch (fuzz->strategy) { case FUZZ_1_BIT_FLIP: assert(fuzz->o1 / 8 < fuzz->slen); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); fuzz->o1++; break; case FUZZ_2_BIT_FLIP: assert(fuzz->o1 / 8 < fuzz->slen); assert(fuzz->o2 / 8 < fuzz->slen); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); fuzz->o1++; if (fuzz->o1 >= fuzz->slen * 8) { fuzz->o1 = 0; fuzz->o2++; } break; case FUZZ_1_BYTE_FLIP: assert(fuzz->o1 < fuzz->slen); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->fuzzed[fuzz->o1] ^= 0xff; fuzz->o1++; break; case FUZZ_2_BYTE_FLIP: assert(fuzz->o1 < fuzz->slen); assert(fuzz->o2 < fuzz->slen); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->fuzzed[fuzz->o1] ^= 0xff; fuzz->fuzzed[fuzz->o2] ^= 0xff; fuzz->o1++; if (fuzz->o1 >= fuzz->slen) { fuzz->o1 = 0; fuzz->o2++; } break; case FUZZ_TRUNCATE_START: case FUZZ_TRUNCATE_END: assert(fuzz->o1 < fuzz->slen); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->o1++; break; case FUZZ_BASE64: assert(fuzz->o1 < fuzz->slen); assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; fuzz->o2++; if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { fuzz->o2 = 0; fuzz->o1++; } break; default: abort(); } FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); }