13f7f5e6cSdjm@openbsd.org /*	$OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $	*/
2def1de08SDamien Miller /*
3def1de08SDamien Miller  * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4def1de08SDamien Miller  *
5def1de08SDamien Miller  * Permission to use, copy, modify, and distribute this software for any
6def1de08SDamien Miller  * purpose with or without fee is hereby granted, provided that the above
7def1de08SDamien Miller  * copyright notice and this permission notice appear in all copies.
8def1de08SDamien Miller  *
9def1de08SDamien Miller  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10def1de08SDamien Miller  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11def1de08SDamien Miller  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12def1de08SDamien Miller  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13def1de08SDamien Miller  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14def1de08SDamien Miller  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15def1de08SDamien Miller  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16def1de08SDamien Miller  */
17def1de08SDamien Miller 
18def1de08SDamien Miller /* Utility functions/framework for fuzz tests */
19def1de08SDamien Miller 
20e7429f2bSDamien Miller #include "includes.h"
21e7429f2bSDamien Miller 
22def1de08SDamien Miller #include <sys/types.h>
23771bb47aSdjm@openbsd.org #include <sys/uio.h>
24def1de08SDamien Miller 
25def1de08SDamien Miller #include <assert.h>
26def1de08SDamien Miller #include <ctype.h>
27def1de08SDamien Miller #include <stdio.h>
28985ee2cbSDarren Tucker #ifdef HAVE_STDINT_H
29def1de08SDamien Miller # include <stdint.h>
30985ee2cbSDarren Tucker #endif
31def1de08SDamien Miller #include <stdlib.h>
32def1de08SDamien Miller #include <string.h>
33771bb47aSdjm@openbsd.org #include <signal.h>
34771bb47aSdjm@openbsd.org #include <unistd.h>
35def1de08SDamien Miller 
36def1de08SDamien Miller #include "test_helper.h"
37771bb47aSdjm@openbsd.org #include "atomicio.h"
38def1de08SDamien Miller 
39def1de08SDamien Miller /* #define FUZZ_DEBUG */
40def1de08SDamien Miller 
41def1de08SDamien Miller #ifdef FUZZ_DEBUG
42def1de08SDamien Miller # define FUZZ_DBG(x) do { \
43def1de08SDamien Miller 		printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
44def1de08SDamien Miller 		printf x; \
45def1de08SDamien Miller 		printf("\n"); \
46def1de08SDamien Miller 		fflush(stdout); \
47def1de08SDamien Miller 	} while (0)
48def1de08SDamien Miller #else
49def1de08SDamien Miller # define FUZZ_DBG(x)
50def1de08SDamien Miller #endif
51def1de08SDamien Miller 
52def1de08SDamien Miller /* For brevity later */
53def1de08SDamien Miller typedef unsigned long long fuzz_ullong;
54def1de08SDamien Miller 
55def1de08SDamien Miller /* For base-64 fuzzing */
56def1de08SDamien Miller static const char fuzz_b64chars[] =
57def1de08SDamien Miller     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
58def1de08SDamien Miller 
59def1de08SDamien Miller struct fuzz {
60def1de08SDamien Miller 	/* Fuzz method currently in use */
61def1de08SDamien Miller 	int strategy;
62def1de08SDamien Miller 
63def1de08SDamien Miller 	/* Fuzz methods remaining */
64def1de08SDamien Miller 	int strategies;
65def1de08SDamien Miller 
66def1de08SDamien Miller 	/* Original seed data blob */
67def1de08SDamien Miller 	void *seed;
68def1de08SDamien Miller 	size_t slen;
69def1de08SDamien Miller 
70def1de08SDamien Miller 	/* Current working copy of seed with fuzz mutations applied */
71def1de08SDamien Miller 	u_char *fuzzed;
72def1de08SDamien Miller 
73def1de08SDamien Miller 	/* Used by fuzz methods */
74def1de08SDamien Miller 	size_t o1, o2;
75def1de08SDamien Miller };
76def1de08SDamien Miller 
77def1de08SDamien Miller static const char *
fuzz_ntop(u_int n)78def1de08SDamien Miller fuzz_ntop(u_int n)
79def1de08SDamien Miller {
80def1de08SDamien Miller 	switch (n) {
81def1de08SDamien Miller 	case 0:
82def1de08SDamien Miller 		return "NONE";
83def1de08SDamien Miller 	case FUZZ_1_BIT_FLIP:
84def1de08SDamien Miller 		return "FUZZ_1_BIT_FLIP";
85def1de08SDamien Miller 	case FUZZ_2_BIT_FLIP:
86def1de08SDamien Miller 		return "FUZZ_2_BIT_FLIP";
87def1de08SDamien Miller 	case FUZZ_1_BYTE_FLIP:
88def1de08SDamien Miller 		return "FUZZ_1_BYTE_FLIP";
89def1de08SDamien Miller 	case FUZZ_2_BYTE_FLIP:
90def1de08SDamien Miller 		return "FUZZ_2_BYTE_FLIP";
91def1de08SDamien Miller 	case FUZZ_TRUNCATE_START:
92def1de08SDamien Miller 		return "FUZZ_TRUNCATE_START";
93def1de08SDamien Miller 	case FUZZ_TRUNCATE_END:
94def1de08SDamien Miller 		return "FUZZ_TRUNCATE_END";
95def1de08SDamien Miller 	case FUZZ_BASE64:
96def1de08SDamien Miller 		return "FUZZ_BASE64";
97def1de08SDamien Miller 	default:
98def1de08SDamien Miller 		abort();
99def1de08SDamien Miller 	}
100def1de08SDamien Miller }
101def1de08SDamien Miller 
102771bb47aSdjm@openbsd.org static int
fuzz_fmt(struct fuzz * fuzz,char * s,size_t n)103771bb47aSdjm@openbsd.org fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
104771bb47aSdjm@openbsd.org {
105771bb47aSdjm@openbsd.org 	if (fuzz == NULL)
106771bb47aSdjm@openbsd.org 		return -1;
107771bb47aSdjm@openbsd.org 
108771bb47aSdjm@openbsd.org 	switch (fuzz->strategy) {
109771bb47aSdjm@openbsd.org 	case FUZZ_1_BIT_FLIP:
110771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
111771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
112771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->slen * 8, fuzz->o1);
113771bb47aSdjm@openbsd.org 		return 0;
114771bb47aSdjm@openbsd.org 	case FUZZ_2_BIT_FLIP:
115771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
116771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
117771bb47aSdjm@openbsd.org 		    (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
118771bb47aSdjm@openbsd.org 		    ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
119771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->o2);
120771bb47aSdjm@openbsd.org 		return 0;
121771bb47aSdjm@openbsd.org 	case FUZZ_1_BYTE_FLIP:
122771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
123771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
124771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->slen, fuzz->o1);
125771bb47aSdjm@openbsd.org 		return 0;
126771bb47aSdjm@openbsd.org 	case FUZZ_2_BYTE_FLIP:
127771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
128771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
129771bb47aSdjm@openbsd.org 		    (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
130771bb47aSdjm@openbsd.org 		    ((fuzz_ullong)fuzz->slen) * fuzz->slen,
131771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->o2);
132771bb47aSdjm@openbsd.org 		return 0;
133771bb47aSdjm@openbsd.org 	case FUZZ_TRUNCATE_START:
134771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
135771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
136771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->slen, fuzz->o1);
137771bb47aSdjm@openbsd.org 		return 0;
138771bb47aSdjm@openbsd.org 	case FUZZ_TRUNCATE_END:
139771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
140771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
141771bb47aSdjm@openbsd.org 		    fuzz->o1, fuzz->slen, fuzz->o1);
142771bb47aSdjm@openbsd.org 		return 0;
143771bb47aSdjm@openbsd.org 	case FUZZ_BASE64:
144771bb47aSdjm@openbsd.org 		assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
145771bb47aSdjm@openbsd.org 		snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
146771bb47aSdjm@openbsd.org 		    fuzz_ntop(fuzz->strategy),
147771bb47aSdjm@openbsd.org 		    (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
148771bb47aSdjm@openbsd.org 		    fuzz->slen * (fuzz_ullong)64, fuzz->o1,
149771bb47aSdjm@openbsd.org 		    fuzz_b64chars[fuzz->o2]);
150771bb47aSdjm@openbsd.org 		return 0;
151771bb47aSdjm@openbsd.org 	default:
152771bb47aSdjm@openbsd.org 		return -1;
153771bb47aSdjm@openbsd.org 		abort();
154771bb47aSdjm@openbsd.org 	}
155771bb47aSdjm@openbsd.org }
156771bb47aSdjm@openbsd.org 
15787d5495bSdjm@openbsd.org static void
dump(u_char * p,size_t len)15887d5495bSdjm@openbsd.org dump(u_char *p, size_t len)
159def1de08SDamien Miller {
16087d5495bSdjm@openbsd.org 	size_t i, j;
161def1de08SDamien Miller 
162def1de08SDamien Miller 	for (i = 0; i < len; i += 16) {
163def1de08SDamien Miller 		fprintf(stderr, "%.4zd: ", i);
164def1de08SDamien Miller 		for (j = i; j < i + 16; j++) {
165def1de08SDamien Miller 			if (j < len)
166def1de08SDamien Miller 				fprintf(stderr, "%02x ", p[j]);
167def1de08SDamien Miller 			else
168def1de08SDamien Miller 				fprintf(stderr, "   ");
169def1de08SDamien Miller 		}
170def1de08SDamien Miller 		fprintf(stderr, " ");
171def1de08SDamien Miller 		for (j = i; j < i + 16; j++) {
172def1de08SDamien Miller 			if (j < len) {
173def1de08SDamien Miller 				if  (isascii(p[j]) && isprint(p[j]))
174def1de08SDamien Miller 					fprintf(stderr, "%c", p[j]);
175def1de08SDamien Miller 				else
176def1de08SDamien Miller 					fprintf(stderr, ".");
177def1de08SDamien Miller 			}
178def1de08SDamien Miller 		}
179def1de08SDamien Miller 		fprintf(stderr, "\n");
180def1de08SDamien Miller 	}
181def1de08SDamien Miller }
182def1de08SDamien Miller 
18387d5495bSdjm@openbsd.org void
fuzz_dump(struct fuzz * fuzz)18487d5495bSdjm@openbsd.org fuzz_dump(struct fuzz *fuzz)
18587d5495bSdjm@openbsd.org {
18687d5495bSdjm@openbsd.org 	char buf[256];
18787d5495bSdjm@openbsd.org 
18887d5495bSdjm@openbsd.org 	if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
18987d5495bSdjm@openbsd.org 		fprintf(stderr, "%s: fuzz invalid\n", __func__);
19087d5495bSdjm@openbsd.org 		abort();
19187d5495bSdjm@openbsd.org 	}
19287d5495bSdjm@openbsd.org 	fputs(buf, stderr);
19387d5495bSdjm@openbsd.org 	fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
19487d5495bSdjm@openbsd.org 	dump(fuzz->seed, fuzz->slen);
19587d5495bSdjm@openbsd.org 	fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
19687d5495bSdjm@openbsd.org 	dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
19787d5495bSdjm@openbsd.org }
19887d5495bSdjm@openbsd.org 
199771bb47aSdjm@openbsd.org static struct fuzz *last_fuzz;
200771bb47aSdjm@openbsd.org 
201771bb47aSdjm@openbsd.org static void
siginfo(int unused)2023f7f5e6cSdjm@openbsd.org siginfo(int unused __attribute__((__unused__)))
203771bb47aSdjm@openbsd.org {
204771bb47aSdjm@openbsd.org 	char buf[256];
205771bb47aSdjm@openbsd.org 
206771bb47aSdjm@openbsd.org 	test_info(buf, sizeof(buf));
207771bb47aSdjm@openbsd.org 	atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
208771bb47aSdjm@openbsd.org 	if (last_fuzz != NULL) {
209771bb47aSdjm@openbsd.org 		fuzz_fmt(last_fuzz, buf, sizeof(buf));
210771bb47aSdjm@openbsd.org 		atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
211771bb47aSdjm@openbsd.org 	}
212771bb47aSdjm@openbsd.org }
213771bb47aSdjm@openbsd.org 
214def1de08SDamien Miller struct fuzz *
fuzz_begin(u_int strategies,const void * p,size_t l)215def1de08SDamien Miller fuzz_begin(u_int strategies, const void *p, size_t l)
216def1de08SDamien Miller {
217def1de08SDamien Miller 	struct fuzz *ret = calloc(sizeof(*ret), 1);
218def1de08SDamien Miller 
219def1de08SDamien Miller 	assert(p != NULL);
220def1de08SDamien Miller 	assert(ret != NULL);
221def1de08SDamien Miller 	ret->seed = malloc(l);
222def1de08SDamien Miller 	assert(ret->seed != NULL);
223def1de08SDamien Miller 	memcpy(ret->seed, p, l);
224def1de08SDamien Miller 	ret->slen = l;
225def1de08SDamien Miller 	ret->strategies = strategies;
226def1de08SDamien Miller 
227def1de08SDamien Miller 	assert(ret->slen < SIZE_MAX / 8);
228def1de08SDamien Miller 	assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
229def1de08SDamien Miller 
230def1de08SDamien Miller 	FUZZ_DBG(("begin, ret = %p", ret));
231def1de08SDamien Miller 
232def1de08SDamien Miller 	fuzz_next(ret);
233771bb47aSdjm@openbsd.org 
234771bb47aSdjm@openbsd.org 	last_fuzz = ret;
235*0aa1f230SDamien Miller #ifdef SIGINFO
236771bb47aSdjm@openbsd.org 	signal(SIGINFO, siginfo);
237771bb47aSdjm@openbsd.org #endif
238*0aa1f230SDamien Miller 	signal(SIGUSR1, siginfo);
239771bb47aSdjm@openbsd.org 
240def1de08SDamien Miller 	return ret;
241def1de08SDamien Miller }
242def1de08SDamien Miller 
243def1de08SDamien Miller void
fuzz_cleanup(struct fuzz * fuzz)244def1de08SDamien Miller fuzz_cleanup(struct fuzz *fuzz)
245def1de08SDamien Miller {
246def1de08SDamien Miller 	FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
247771bb47aSdjm@openbsd.org 	last_fuzz = NULL;
248*0aa1f230SDamien Miller #ifdef SIGINFO
249771bb47aSdjm@openbsd.org 	signal(SIGINFO, SIG_DFL);
250771bb47aSdjm@openbsd.org #endif
251*0aa1f230SDamien Miller 	signal(SIGUSR1, SIG_DFL);
252def1de08SDamien Miller 	assert(fuzz != NULL);
253def1de08SDamien Miller 	assert(fuzz->seed != NULL);
254def1de08SDamien Miller 	assert(fuzz->fuzzed != NULL);
255def1de08SDamien Miller 	free(fuzz->seed);
256def1de08SDamien Miller 	free(fuzz->fuzzed);
257def1de08SDamien Miller 	free(fuzz);
258def1de08SDamien Miller }
259def1de08SDamien Miller 
260def1de08SDamien Miller static int
fuzz_strategy_done(struct fuzz * fuzz)261def1de08SDamien Miller fuzz_strategy_done(struct fuzz *fuzz)
262def1de08SDamien Miller {
263def1de08SDamien Miller 	FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
264def1de08SDamien Miller 	    fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
265def1de08SDamien Miller 
266def1de08SDamien Miller 	switch (fuzz->strategy) {
267def1de08SDamien Miller 	case FUZZ_1_BIT_FLIP:
268def1de08SDamien Miller 		return fuzz->o1 >= fuzz->slen * 8;
269def1de08SDamien Miller 	case FUZZ_2_BIT_FLIP:
270def1de08SDamien Miller 		return fuzz->o2 >= fuzz->slen * 8;
271def1de08SDamien Miller 	case FUZZ_2_BYTE_FLIP:
272def1de08SDamien Miller 		return fuzz->o2 >= fuzz->slen;
273def1de08SDamien Miller 	case FUZZ_1_BYTE_FLIP:
274def1de08SDamien Miller 	case FUZZ_TRUNCATE_START:
275def1de08SDamien Miller 	case FUZZ_TRUNCATE_END:
276def1de08SDamien Miller 	case FUZZ_BASE64:
277def1de08SDamien Miller 		return fuzz->o1 >= fuzz->slen;
278def1de08SDamien Miller 	default:
279def1de08SDamien Miller 		abort();
280def1de08SDamien Miller 	}
281def1de08SDamien Miller }
282def1de08SDamien Miller 
283def1de08SDamien Miller void
fuzz_next(struct fuzz * fuzz)284def1de08SDamien Miller fuzz_next(struct fuzz *fuzz)
285def1de08SDamien Miller {
286def1de08SDamien Miller 	u_int i;
287def1de08SDamien Miller 
288def1de08SDamien Miller 	FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
289def1de08SDamien Miller 	    "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
290def1de08SDamien Miller 	    (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
291def1de08SDamien Miller 
292def1de08SDamien Miller 	if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
293def1de08SDamien Miller 		/* If we are just starting out, we need to allocate too */
294def1de08SDamien Miller 		if (fuzz->fuzzed == NULL) {
295def1de08SDamien Miller 			FUZZ_DBG(("alloc"));
296def1de08SDamien Miller 			fuzz->fuzzed = calloc(fuzz->slen, 1);
297def1de08SDamien Miller 		}
298def1de08SDamien Miller 		/* Pick next strategy */
299def1de08SDamien Miller 		FUZZ_DBG(("advance"));
300def1de08SDamien Miller 		for (i = 1; i <= FUZZ_MAX; i <<= 1) {
301def1de08SDamien Miller 			if ((fuzz->strategies & i) != 0) {
302def1de08SDamien Miller 				fuzz->strategy = i;
303def1de08SDamien Miller 				break;
304def1de08SDamien Miller 			}
305def1de08SDamien Miller 		}
306def1de08SDamien Miller 		FUZZ_DBG(("selected = %u", fuzz->strategy));
307def1de08SDamien Miller 		if (fuzz->strategy == 0) {
308def1de08SDamien Miller 			FUZZ_DBG(("done, no more strategies"));
309def1de08SDamien Miller 			return;
310def1de08SDamien Miller 		}
311def1de08SDamien Miller 		fuzz->strategies &= ~(fuzz->strategy);
312def1de08SDamien Miller 		fuzz->o1 = fuzz->o2 = 0;
313def1de08SDamien Miller 	}
314def1de08SDamien Miller 
315def1de08SDamien Miller 	assert(fuzz->fuzzed != NULL);
316def1de08SDamien Miller 
317def1de08SDamien Miller 	switch (fuzz->strategy) {
318def1de08SDamien Miller 	case FUZZ_1_BIT_FLIP:
319def1de08SDamien Miller 		assert(fuzz->o1 / 8 < fuzz->slen);
320def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
321def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
322def1de08SDamien Miller 		fuzz->o1++;
323def1de08SDamien Miller 		break;
324def1de08SDamien Miller 	case FUZZ_2_BIT_FLIP:
325def1de08SDamien Miller 		assert(fuzz->o1 / 8 < fuzz->slen);
326def1de08SDamien Miller 		assert(fuzz->o2 / 8 < fuzz->slen);
327def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
328def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
329def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
330def1de08SDamien Miller 		fuzz->o1++;
331def1de08SDamien Miller 		if (fuzz->o1 >= fuzz->slen * 8) {
332def1de08SDamien Miller 			fuzz->o1 = 0;
333def1de08SDamien Miller 			fuzz->o2++;
334def1de08SDamien Miller 		}
335def1de08SDamien Miller 		break;
336def1de08SDamien Miller 	case FUZZ_1_BYTE_FLIP:
337def1de08SDamien Miller 		assert(fuzz->o1 < fuzz->slen);
338def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
339def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o1] ^= 0xff;
340def1de08SDamien Miller 		fuzz->o1++;
341def1de08SDamien Miller 		break;
342def1de08SDamien Miller 	case FUZZ_2_BYTE_FLIP:
343def1de08SDamien Miller 		assert(fuzz->o1 < fuzz->slen);
344def1de08SDamien Miller 		assert(fuzz->o2 < fuzz->slen);
345def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
346def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o1] ^= 0xff;
347def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o2] ^= 0xff;
348def1de08SDamien Miller 		fuzz->o1++;
349def1de08SDamien Miller 		if (fuzz->o1 >= fuzz->slen) {
350def1de08SDamien Miller 			fuzz->o1 = 0;
351def1de08SDamien Miller 			fuzz->o2++;
352def1de08SDamien Miller 		}
353def1de08SDamien Miller 		break;
354def1de08SDamien Miller 	case FUZZ_TRUNCATE_START:
355def1de08SDamien Miller 	case FUZZ_TRUNCATE_END:
356def1de08SDamien Miller 		assert(fuzz->o1 < fuzz->slen);
357def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
358def1de08SDamien Miller 		fuzz->o1++;
359def1de08SDamien Miller 		break;
360def1de08SDamien Miller 	case FUZZ_BASE64:
361def1de08SDamien Miller 		assert(fuzz->o1 < fuzz->slen);
362def1de08SDamien Miller 		assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
363def1de08SDamien Miller 		memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
364def1de08SDamien Miller 		fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
365def1de08SDamien Miller 		fuzz->o2++;
366def1de08SDamien Miller 		if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
367def1de08SDamien Miller 			fuzz->o2 = 0;
368def1de08SDamien Miller 			fuzz->o1++;
369def1de08SDamien Miller 		}
370def1de08SDamien Miller 		break;
371def1de08SDamien Miller 	default:
372def1de08SDamien Miller 		abort();
373def1de08SDamien Miller 	}
374def1de08SDamien Miller 
375def1de08SDamien Miller 	FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
376def1de08SDamien Miller 	    "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
377def1de08SDamien Miller 	    (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
378def1de08SDamien Miller }
379def1de08SDamien Miller 
380def1de08SDamien Miller int
fuzz_matches_original(struct fuzz * fuzz)38180603c0dSdjm@openbsd.org fuzz_matches_original(struct fuzz *fuzz)
38280603c0dSdjm@openbsd.org {
38380603c0dSdjm@openbsd.org 	if (fuzz_len(fuzz) != fuzz->slen)
38480603c0dSdjm@openbsd.org 		return 0;
38580603c0dSdjm@openbsd.org 	return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
38680603c0dSdjm@openbsd.org }
38780603c0dSdjm@openbsd.org 
38880603c0dSdjm@openbsd.org int
fuzz_done(struct fuzz * fuzz)389def1de08SDamien Miller fuzz_done(struct fuzz *fuzz)
390def1de08SDamien Miller {
391def1de08SDamien Miller 	FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
392def1de08SDamien Miller 	    (u_long)fuzz->strategies));
393def1de08SDamien Miller 
394def1de08SDamien Miller 	return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
395def1de08SDamien Miller }
396def1de08SDamien Miller 
397def1de08SDamien Miller size_t
fuzz_len(struct fuzz * fuzz)398def1de08SDamien Miller fuzz_len(struct fuzz *fuzz)
399def1de08SDamien Miller {
400def1de08SDamien Miller 	assert(fuzz->fuzzed != NULL);
401def1de08SDamien Miller 	switch (fuzz->strategy) {
402def1de08SDamien Miller 	case FUZZ_1_BIT_FLIP:
403def1de08SDamien Miller 	case FUZZ_2_BIT_FLIP:
404def1de08SDamien Miller 	case FUZZ_1_BYTE_FLIP:
405def1de08SDamien Miller 	case FUZZ_2_BYTE_FLIP:
406def1de08SDamien Miller 	case FUZZ_BASE64:
407def1de08SDamien Miller 		return fuzz->slen;
408def1de08SDamien Miller 	case FUZZ_TRUNCATE_START:
409def1de08SDamien Miller 	case FUZZ_TRUNCATE_END:
410def1de08SDamien Miller 		assert(fuzz->o1 <= fuzz->slen);
411def1de08SDamien Miller 		return fuzz->slen - fuzz->o1;
412def1de08SDamien Miller 	default:
413def1de08SDamien Miller 		abort();
414def1de08SDamien Miller 	}
415def1de08SDamien Miller }
416def1de08SDamien Miller 
417def1de08SDamien Miller u_char *
fuzz_ptr(struct fuzz * fuzz)418def1de08SDamien Miller fuzz_ptr(struct fuzz *fuzz)
419def1de08SDamien Miller {
420def1de08SDamien Miller 	assert(fuzz->fuzzed != NULL);
421def1de08SDamien Miller 	switch (fuzz->strategy) {
422def1de08SDamien Miller 	case FUZZ_1_BIT_FLIP:
423def1de08SDamien Miller 	case FUZZ_2_BIT_FLIP:
424def1de08SDamien Miller 	case FUZZ_1_BYTE_FLIP:
425def1de08SDamien Miller 	case FUZZ_2_BYTE_FLIP:
426def1de08SDamien Miller 	case FUZZ_BASE64:
427def1de08SDamien Miller 		return fuzz->fuzzed;
428def1de08SDamien Miller 	case FUZZ_TRUNCATE_START:
429def1de08SDamien Miller 		assert(fuzz->o1 <= fuzz->slen);
430def1de08SDamien Miller 		return fuzz->fuzzed + fuzz->o1;
431def1de08SDamien Miller 	case FUZZ_TRUNCATE_END:
432def1de08SDamien Miller 		assert(fuzz->o1 <= fuzz->slen);
433def1de08SDamien Miller 		return fuzz->fuzzed;
434def1de08SDamien Miller 	default:
435def1de08SDamien Miller 		abort();
436def1de08SDamien Miller 	}
437def1de08SDamien Miller }
438def1de08SDamien Miller 
439