xref: /openbsd-src/regress/usr.bin/ssh/unittests/test_helper/fuzz.c (revision 6bcae15aab4145cf4c6b363386594a0c5835f11f)
1*6bcae15aSdjm /*	$OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $	*/
229518ea0Sdjm /*
329518ea0Sdjm  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
429518ea0Sdjm  *
529518ea0Sdjm  * Permission to use, copy, modify, and distribute this software for any
629518ea0Sdjm  * purpose with or without fee is hereby granted, provided that the above
729518ea0Sdjm  * copyright notice and this permission notice appear in all copies.
829518ea0Sdjm  *
929518ea0Sdjm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1029518ea0Sdjm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1129518ea0Sdjm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1229518ea0Sdjm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1329518ea0Sdjm  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1429518ea0Sdjm  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1529518ea0Sdjm  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1629518ea0Sdjm  */
1729518ea0Sdjm 
1829518ea0Sdjm /* Utility functions/framework for fuzz tests */
1929518ea0Sdjm 
2029518ea0Sdjm #include <sys/types.h>
21d531405cSdjm #include <sys/uio.h>
2229518ea0Sdjm 
2329518ea0Sdjm #include <assert.h>
2429518ea0Sdjm #include <ctype.h>
2529518ea0Sdjm #include <stdio.h>
2629518ea0Sdjm #include <stdint.h>
2729518ea0Sdjm #include <stdlib.h>
2829518ea0Sdjm #include <string.h>
29d531405cSdjm #include <signal.h>
30d531405cSdjm #include <unistd.h>
3129518ea0Sdjm 
3229518ea0Sdjm #include "test_helper.h"
33d531405cSdjm #include "atomicio.h"
3429518ea0Sdjm 
3529518ea0Sdjm /* #define FUZZ_DEBUG */
3629518ea0Sdjm 
3729518ea0Sdjm #ifdef FUZZ_DEBUG
3829518ea0Sdjm # define FUZZ_DBG(x) do { \
3929518ea0Sdjm 		printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
4029518ea0Sdjm 		printf x; \
4129518ea0Sdjm 		printf("\n"); \
4229518ea0Sdjm 		fflush(stdout); \
4329518ea0Sdjm 	} while (0)
4429518ea0Sdjm #else
4529518ea0Sdjm # define FUZZ_DBG(x)
4629518ea0Sdjm #endif
4729518ea0Sdjm 
4829518ea0Sdjm /* For brevity later */
4929518ea0Sdjm typedef unsigned long long fuzz_ullong;
5029518ea0Sdjm 
5129518ea0Sdjm /* For base-64 fuzzing */
5229518ea0Sdjm static const char fuzz_b64chars[] =
5329518ea0Sdjm     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5429518ea0Sdjm 
5529518ea0Sdjm struct fuzz {
5629518ea0Sdjm 	/* Fuzz method currently in use */
5729518ea0Sdjm 	int strategy;
5829518ea0Sdjm 
5929518ea0Sdjm 	/* Fuzz methods remaining */
6029518ea0Sdjm 	int strategies;
6129518ea0Sdjm 
6229518ea0Sdjm 	/* Original seed data blob */
6329518ea0Sdjm 	void *seed;
6429518ea0Sdjm 	size_t slen;
6529518ea0Sdjm 
6629518ea0Sdjm 	/* Current working copy of seed with fuzz mutations applied */
6729518ea0Sdjm 	u_char *fuzzed;
6829518ea0Sdjm 
6929518ea0Sdjm 	/* Used by fuzz methods */
7029518ea0Sdjm 	size_t o1, o2;
7129518ea0Sdjm };
7229518ea0Sdjm 
7329518ea0Sdjm static const char *
fuzz_ntop(u_int n)7429518ea0Sdjm fuzz_ntop(u_int n)
7529518ea0Sdjm {
7629518ea0Sdjm 	switch (n) {
7729518ea0Sdjm 	case 0:
7829518ea0Sdjm 		return "NONE";
7929518ea0Sdjm 	case FUZZ_1_BIT_FLIP:
8029518ea0Sdjm 		return "FUZZ_1_BIT_FLIP";
8129518ea0Sdjm 	case FUZZ_2_BIT_FLIP:
8229518ea0Sdjm 		return "FUZZ_2_BIT_FLIP";
8329518ea0Sdjm 	case FUZZ_1_BYTE_FLIP:
8429518ea0Sdjm 		return "FUZZ_1_BYTE_FLIP";
8529518ea0Sdjm 	case FUZZ_2_BYTE_FLIP:
8629518ea0Sdjm 		return "FUZZ_2_BYTE_FLIP";
8729518ea0Sdjm 	case FUZZ_TRUNCATE_START:
8829518ea0Sdjm 		return "FUZZ_TRUNCATE_START";
8929518ea0Sdjm 	case FUZZ_TRUNCATE_END:
9029518ea0Sdjm 		return "FUZZ_TRUNCATE_END";
9129518ea0Sdjm 	case FUZZ_BASE64:
9229518ea0Sdjm 		return "FUZZ_BASE64";
9329518ea0Sdjm 	default:
9429518ea0Sdjm 		abort();
9529518ea0Sdjm 	}
9629518ea0Sdjm }
9729518ea0Sdjm 
98d531405cSdjm static int
fuzz_fmt(struct fuzz * fuzz,char * s,size_t n)99d531405cSdjm fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
100d531405cSdjm {
101d531405cSdjm 	if (fuzz == NULL)
102d531405cSdjm 		return -1;
103d531405cSdjm 
104d531405cSdjm 	switch (fuzz->strategy) {
105d531405cSdjm 	case FUZZ_1_BIT_FLIP:
106d531405cSdjm 		snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
107d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
108d531405cSdjm 		    fuzz->o1, fuzz->slen * 8, fuzz->o1);
109d531405cSdjm 		return 0;
110d531405cSdjm 	case FUZZ_2_BIT_FLIP:
111d531405cSdjm 		snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
112d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
113d531405cSdjm 		    (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
114d531405cSdjm 		    ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
115d531405cSdjm 		    fuzz->o1, fuzz->o2);
116d531405cSdjm 		return 0;
117d531405cSdjm 	case FUZZ_1_BYTE_FLIP:
118d531405cSdjm 		snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
119d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
120d531405cSdjm 		    fuzz->o1, fuzz->slen, fuzz->o1);
121d531405cSdjm 		return 0;
122d531405cSdjm 	case FUZZ_2_BYTE_FLIP:
123d531405cSdjm 		snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
124d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
125d531405cSdjm 		    (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
126d531405cSdjm 		    ((fuzz_ullong)fuzz->slen) * fuzz->slen,
127d531405cSdjm 		    fuzz->o1, fuzz->o2);
128d531405cSdjm 		return 0;
129d531405cSdjm 	case FUZZ_TRUNCATE_START:
130d531405cSdjm 		snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
131d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
132d531405cSdjm 		    fuzz->o1, fuzz->slen, fuzz->o1);
133d531405cSdjm 		return 0;
134d531405cSdjm 	case FUZZ_TRUNCATE_END:
135d531405cSdjm 		snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
136d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
137d531405cSdjm 		    fuzz->o1, fuzz->slen, fuzz->o1);
138d531405cSdjm 		return 0;
139d531405cSdjm 	case FUZZ_BASE64:
140d531405cSdjm 		assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
141d531405cSdjm 		snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
142d531405cSdjm 		    fuzz_ntop(fuzz->strategy),
143d531405cSdjm 		    (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
144d531405cSdjm 		    fuzz->slen * (fuzz_ullong)64, fuzz->o1,
145d531405cSdjm 		    fuzz_b64chars[fuzz->o2]);
146d531405cSdjm 		return 0;
147d531405cSdjm 	default:
148d531405cSdjm 		return -1;
149d531405cSdjm 		abort();
150d531405cSdjm 	}
151d531405cSdjm }
152d531405cSdjm 
15387cf98b2Sdjm static void
dump(u_char * p,size_t len)15487cf98b2Sdjm dump(u_char *p, size_t len)
15529518ea0Sdjm {
15687cf98b2Sdjm 	size_t i, j;
15729518ea0Sdjm 
15829518ea0Sdjm 	for (i = 0; i < len; i += 16) {
15929518ea0Sdjm 		fprintf(stderr, "%.4zd: ", i);
16029518ea0Sdjm 		for (j = i; j < i + 16; j++) {
16129518ea0Sdjm 			if (j < len)
16229518ea0Sdjm 				fprintf(stderr, "%02x ", p[j]);
16329518ea0Sdjm 			else
16429518ea0Sdjm 				fprintf(stderr, "   ");
16529518ea0Sdjm 		}
16629518ea0Sdjm 		fprintf(stderr, " ");
16729518ea0Sdjm 		for (j = i; j < i + 16; j++) {
16829518ea0Sdjm 			if (j < len) {
16929518ea0Sdjm 				if  (isascii(p[j]) && isprint(p[j]))
17029518ea0Sdjm 					fprintf(stderr, "%c", p[j]);
17129518ea0Sdjm 				else
17229518ea0Sdjm 					fprintf(stderr, ".");
17329518ea0Sdjm 			}
17429518ea0Sdjm 		}
17529518ea0Sdjm 		fprintf(stderr, "\n");
17629518ea0Sdjm 	}
17729518ea0Sdjm }
17829518ea0Sdjm 
17987cf98b2Sdjm void
fuzz_dump(struct fuzz * fuzz)18087cf98b2Sdjm fuzz_dump(struct fuzz *fuzz)
18187cf98b2Sdjm {
18287cf98b2Sdjm 	char buf[256];
18387cf98b2Sdjm 
18487cf98b2Sdjm 	if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
18587cf98b2Sdjm 		fprintf(stderr, "%s: fuzz invalid\n", __func__);
18687cf98b2Sdjm 		abort();
18787cf98b2Sdjm 	}
18887cf98b2Sdjm 	fputs(buf, stderr);
18987cf98b2Sdjm 	fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
19087cf98b2Sdjm 	dump(fuzz->seed, fuzz->slen);
19187cf98b2Sdjm 	fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
19287cf98b2Sdjm 	dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
19387cf98b2Sdjm }
19487cf98b2Sdjm 
195d531405cSdjm #ifdef SIGINFO
196d531405cSdjm static struct fuzz *last_fuzz;
197d531405cSdjm 
198d531405cSdjm static void
siginfo(int unused)199*6bcae15aSdjm siginfo(int unused __attribute__((__unused__)))
200d531405cSdjm {
201d531405cSdjm 	char buf[256];
202d531405cSdjm 
203d531405cSdjm 	test_info(buf, sizeof(buf));
204d531405cSdjm 	atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
205d531405cSdjm 	if (last_fuzz != NULL) {
206d531405cSdjm 		fuzz_fmt(last_fuzz, buf, sizeof(buf));
207d531405cSdjm 		atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
208d531405cSdjm 	}
209d531405cSdjm }
210d531405cSdjm #endif
211d531405cSdjm 
21229518ea0Sdjm struct fuzz *
fuzz_begin(u_int strategies,const void * p,size_t l)21393107337Sdjm fuzz_begin(u_int strategies, const void *p, size_t l)
21429518ea0Sdjm {
21529518ea0Sdjm 	struct fuzz *ret = calloc(sizeof(*ret), 1);
21629518ea0Sdjm 
21729518ea0Sdjm 	assert(p != NULL);
21829518ea0Sdjm 	assert(ret != NULL);
21929518ea0Sdjm 	ret->seed = malloc(l);
22029518ea0Sdjm 	assert(ret->seed != NULL);
22129518ea0Sdjm 	memcpy(ret->seed, p, l);
22229518ea0Sdjm 	ret->slen = l;
22329518ea0Sdjm 	ret->strategies = strategies;
22429518ea0Sdjm 
22529518ea0Sdjm 	assert(ret->slen < SIZE_MAX / 8);
22629518ea0Sdjm 	assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
22729518ea0Sdjm 
22829518ea0Sdjm 	FUZZ_DBG(("begin, ret = %p", ret));
22929518ea0Sdjm 
23029518ea0Sdjm 	fuzz_next(ret);
231d531405cSdjm 
232d531405cSdjm #ifdef SIGINFO
233d531405cSdjm 	last_fuzz = ret;
234d531405cSdjm 	signal(SIGINFO, siginfo);
235d531405cSdjm #endif
236d531405cSdjm 
23729518ea0Sdjm 	return ret;
23829518ea0Sdjm }
23929518ea0Sdjm 
24029518ea0Sdjm void
fuzz_cleanup(struct fuzz * fuzz)24129518ea0Sdjm fuzz_cleanup(struct fuzz *fuzz)
24229518ea0Sdjm {
24329518ea0Sdjm 	FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
244d531405cSdjm #ifdef SIGINFO
245d531405cSdjm 	last_fuzz = NULL;
246d531405cSdjm 	signal(SIGINFO, SIG_DFL);
247d531405cSdjm #endif
24829518ea0Sdjm 	assert(fuzz != NULL);
24929518ea0Sdjm 	assert(fuzz->seed != NULL);
25029518ea0Sdjm 	assert(fuzz->fuzzed != NULL);
25129518ea0Sdjm 	free(fuzz->seed);
25229518ea0Sdjm 	free(fuzz->fuzzed);
25329518ea0Sdjm 	free(fuzz);
25429518ea0Sdjm }
25529518ea0Sdjm 
25629518ea0Sdjm static int
fuzz_strategy_done(struct fuzz * fuzz)25729518ea0Sdjm fuzz_strategy_done(struct fuzz *fuzz)
25829518ea0Sdjm {
25929518ea0Sdjm 	FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
26029518ea0Sdjm 	    fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
26129518ea0Sdjm 
26229518ea0Sdjm 	switch (fuzz->strategy) {
26329518ea0Sdjm 	case FUZZ_1_BIT_FLIP:
26429518ea0Sdjm 		return fuzz->o1 >= fuzz->slen * 8;
26529518ea0Sdjm 	case FUZZ_2_BIT_FLIP:
26629518ea0Sdjm 		return fuzz->o2 >= fuzz->slen * 8;
26729518ea0Sdjm 	case FUZZ_2_BYTE_FLIP:
26829518ea0Sdjm 		return fuzz->o2 >= fuzz->slen;
26929518ea0Sdjm 	case FUZZ_1_BYTE_FLIP:
27029518ea0Sdjm 	case FUZZ_TRUNCATE_START:
27129518ea0Sdjm 	case FUZZ_TRUNCATE_END:
27229518ea0Sdjm 	case FUZZ_BASE64:
27329518ea0Sdjm 		return fuzz->o1 >= fuzz->slen;
27429518ea0Sdjm 	default:
27529518ea0Sdjm 		abort();
27629518ea0Sdjm 	}
27729518ea0Sdjm }
27829518ea0Sdjm 
27929518ea0Sdjm void
fuzz_next(struct fuzz * fuzz)28029518ea0Sdjm fuzz_next(struct fuzz *fuzz)
28129518ea0Sdjm {
28229518ea0Sdjm 	u_int i;
28329518ea0Sdjm 
28429518ea0Sdjm 	FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
28529518ea0Sdjm 	    "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
28629518ea0Sdjm 	    (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
28729518ea0Sdjm 
28829518ea0Sdjm 	if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
28929518ea0Sdjm 		/* If we are just starting out, we need to allocate too */
29029518ea0Sdjm 		if (fuzz->fuzzed == NULL) {
29129518ea0Sdjm 			FUZZ_DBG(("alloc"));
29229518ea0Sdjm 			fuzz->fuzzed = calloc(fuzz->slen, 1);
29329518ea0Sdjm 		}
29429518ea0Sdjm 		/* Pick next strategy */
29529518ea0Sdjm 		FUZZ_DBG(("advance"));
29629518ea0Sdjm 		for (i = 1; i <= FUZZ_MAX; i <<= 1) {
29729518ea0Sdjm 			if ((fuzz->strategies & i) != 0) {
29829518ea0Sdjm 				fuzz->strategy = i;
29929518ea0Sdjm 				break;
30029518ea0Sdjm 			}
30129518ea0Sdjm 		}
30229518ea0Sdjm 		FUZZ_DBG(("selected = %u", fuzz->strategy));
30329518ea0Sdjm 		if (fuzz->strategy == 0) {
30429518ea0Sdjm 			FUZZ_DBG(("done, no more strategies"));
30529518ea0Sdjm 			return;
30629518ea0Sdjm 		}
30729518ea0Sdjm 		fuzz->strategies &= ~(fuzz->strategy);
30829518ea0Sdjm 		fuzz->o1 = fuzz->o2 = 0;
30929518ea0Sdjm 	}
31029518ea0Sdjm 
31129518ea0Sdjm 	assert(fuzz->fuzzed != NULL);
31229518ea0Sdjm 
31329518ea0Sdjm 	switch (fuzz->strategy) {
31429518ea0Sdjm 	case FUZZ_1_BIT_FLIP:
31529518ea0Sdjm 		assert(fuzz->o1 / 8 < fuzz->slen);
31629518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
31729518ea0Sdjm 		fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
31829518ea0Sdjm 		fuzz->o1++;
31929518ea0Sdjm 		break;
32029518ea0Sdjm 	case FUZZ_2_BIT_FLIP:
32129518ea0Sdjm 		assert(fuzz->o1 / 8 < fuzz->slen);
32229518ea0Sdjm 		assert(fuzz->o2 / 8 < fuzz->slen);
32329518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
32429518ea0Sdjm 		fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
32529518ea0Sdjm 		fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
32629518ea0Sdjm 		fuzz->o1++;
32729518ea0Sdjm 		if (fuzz->o1 >= fuzz->slen * 8) {
32829518ea0Sdjm 			fuzz->o1 = 0;
32929518ea0Sdjm 			fuzz->o2++;
33029518ea0Sdjm 		}
33129518ea0Sdjm 		break;
33229518ea0Sdjm 	case FUZZ_1_BYTE_FLIP:
33329518ea0Sdjm 		assert(fuzz->o1 < fuzz->slen);
33429518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
33529518ea0Sdjm 		fuzz->fuzzed[fuzz->o1] ^= 0xff;
33629518ea0Sdjm 		fuzz->o1++;
33729518ea0Sdjm 		break;
33829518ea0Sdjm 	case FUZZ_2_BYTE_FLIP:
33929518ea0Sdjm 		assert(fuzz->o1 < fuzz->slen);
34029518ea0Sdjm 		assert(fuzz->o2 < fuzz->slen);
34129518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
34229518ea0Sdjm 		fuzz->fuzzed[fuzz->o1] ^= 0xff;
34329518ea0Sdjm 		fuzz->fuzzed[fuzz->o2] ^= 0xff;
34429518ea0Sdjm 		fuzz->o1++;
34529518ea0Sdjm 		if (fuzz->o1 >= fuzz->slen) {
34629518ea0Sdjm 			fuzz->o1 = 0;
34729518ea0Sdjm 			fuzz->o2++;
34829518ea0Sdjm 		}
34929518ea0Sdjm 		break;
35029518ea0Sdjm 	case FUZZ_TRUNCATE_START:
35129518ea0Sdjm 	case FUZZ_TRUNCATE_END:
35229518ea0Sdjm 		assert(fuzz->o1 < fuzz->slen);
35329518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
35429518ea0Sdjm 		fuzz->o1++;
35529518ea0Sdjm 		break;
35629518ea0Sdjm 	case FUZZ_BASE64:
35729518ea0Sdjm 		assert(fuzz->o1 < fuzz->slen);
35829518ea0Sdjm 		assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
35929518ea0Sdjm 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
36029518ea0Sdjm 		fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
36129518ea0Sdjm 		fuzz->o2++;
36229518ea0Sdjm 		if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
36329518ea0Sdjm 			fuzz->o2 = 0;
36429518ea0Sdjm 			fuzz->o1++;
36529518ea0Sdjm 		}
36629518ea0Sdjm 		break;
36729518ea0Sdjm 	default:
36829518ea0Sdjm 		abort();
36929518ea0Sdjm 	}
37029518ea0Sdjm 
37129518ea0Sdjm 	FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
37229518ea0Sdjm 	    "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
37329518ea0Sdjm 	    (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
37429518ea0Sdjm }
37529518ea0Sdjm 
37629518ea0Sdjm int
fuzz_matches_original(struct fuzz * fuzz)37760d08003Sdjm fuzz_matches_original(struct fuzz *fuzz)
37860d08003Sdjm {
37960d08003Sdjm 	if (fuzz_len(fuzz) != fuzz->slen)
38060d08003Sdjm 		return 0;
38160d08003Sdjm 	return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
38260d08003Sdjm }
38360d08003Sdjm 
38460d08003Sdjm int
fuzz_done(struct fuzz * fuzz)38529518ea0Sdjm fuzz_done(struct fuzz *fuzz)
38629518ea0Sdjm {
38729518ea0Sdjm 	FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
38829518ea0Sdjm 	    (u_long)fuzz->strategies));
38929518ea0Sdjm 
39029518ea0Sdjm 	return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
39129518ea0Sdjm }
39229518ea0Sdjm 
39329518ea0Sdjm size_t
fuzz_len(struct fuzz * fuzz)39429518ea0Sdjm fuzz_len(struct fuzz *fuzz)
39529518ea0Sdjm {
39629518ea0Sdjm 	assert(fuzz->fuzzed != NULL);
39729518ea0Sdjm 	switch (fuzz->strategy) {
39829518ea0Sdjm 	case FUZZ_1_BIT_FLIP:
39929518ea0Sdjm 	case FUZZ_2_BIT_FLIP:
40029518ea0Sdjm 	case FUZZ_1_BYTE_FLIP:
40129518ea0Sdjm 	case FUZZ_2_BYTE_FLIP:
40229518ea0Sdjm 	case FUZZ_BASE64:
40329518ea0Sdjm 		return fuzz->slen;
40429518ea0Sdjm 	case FUZZ_TRUNCATE_START:
40529518ea0Sdjm 	case FUZZ_TRUNCATE_END:
40629518ea0Sdjm 		assert(fuzz->o1 <= fuzz->slen);
40729518ea0Sdjm 		return fuzz->slen - fuzz->o1;
40829518ea0Sdjm 	default:
40929518ea0Sdjm 		abort();
41029518ea0Sdjm 	}
41129518ea0Sdjm }
41229518ea0Sdjm 
41329518ea0Sdjm u_char *
fuzz_ptr(struct fuzz * fuzz)41429518ea0Sdjm fuzz_ptr(struct fuzz *fuzz)
41529518ea0Sdjm {
41629518ea0Sdjm 	assert(fuzz->fuzzed != NULL);
41729518ea0Sdjm 	switch (fuzz->strategy) {
41829518ea0Sdjm 	case FUZZ_1_BIT_FLIP:
41929518ea0Sdjm 	case FUZZ_2_BIT_FLIP:
42029518ea0Sdjm 	case FUZZ_1_BYTE_FLIP:
42129518ea0Sdjm 	case FUZZ_2_BYTE_FLIP:
42229518ea0Sdjm 	case FUZZ_BASE64:
42329518ea0Sdjm 		return fuzz->fuzzed;
42429518ea0Sdjm 	case FUZZ_TRUNCATE_START:
42529518ea0Sdjm 		assert(fuzz->o1 <= fuzz->slen);
42629518ea0Sdjm 		return fuzz->fuzzed + fuzz->o1;
42729518ea0Sdjm 	case FUZZ_TRUNCATE_END:
42829518ea0Sdjm 		assert(fuzz->o1 <= fuzz->slen);
42929518ea0Sdjm 		return fuzz->fuzzed;
43029518ea0Sdjm 	default:
43129518ea0Sdjm 		abort();
43229518ea0Sdjm 	}
43329518ea0Sdjm }
43429518ea0Sdjm 
435