1bc5531deSDag-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>
23bc5531deSDag-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>
33bc5531deSDag-Erling Smørgrav #include <signal.h>
34bc5531deSDag-Erling Smørgrav #include <unistd.h>
35a0ee8cc6SDag-Erling Smørgrav
36a0ee8cc6SDag-Erling Smørgrav #include "test_helper.h"
37bc5531deSDag-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 *
fuzz_ntop(u_int n)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
102bc5531deSDag-Erling Smørgrav static int
fuzz_fmt(struct fuzz * fuzz,char * s,size_t n)103bc5531deSDag-Erling Smørgrav fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
104a0ee8cc6SDag-Erling Smørgrav {
105bc5531deSDag-Erling Smørgrav if (fuzz == NULL)
106bc5531deSDag-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:
110bc5531deSDag-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);
113bc5531deSDag-Erling Smørgrav return 0;
114a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BIT_FLIP:
115bc5531deSDag-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);
120bc5531deSDag-Erling Smørgrav return 0;
121a0ee8cc6SDag-Erling Smørgrav case FUZZ_1_BYTE_FLIP:
122bc5531deSDag-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);
125bc5531deSDag-Erling Smørgrav return 0;
126a0ee8cc6SDag-Erling Smørgrav case FUZZ_2_BYTE_FLIP:
127bc5531deSDag-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);
132bc5531deSDag-Erling Smørgrav return 0;
133a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_START:
134bc5531deSDag-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);
137bc5531deSDag-Erling Smørgrav return 0;
138a0ee8cc6SDag-Erling Smørgrav case FUZZ_TRUNCATE_END:
139bc5531deSDag-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);
142bc5531deSDag-Erling Smørgrav return 0;
143a0ee8cc6SDag-Erling Smørgrav case FUZZ_BASE64:
144a0ee8cc6SDag-Erling Smørgrav assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
145bc5531deSDag-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]);
150bc5531deSDag-Erling Smørgrav return 0;
151a0ee8cc6SDag-Erling Smørgrav default:
152bc5531deSDag-Erling Smørgrav return -1;
153a0ee8cc6SDag-Erling Smørgrav abort();
154a0ee8cc6SDag-Erling Smørgrav }
155bc5531deSDag-Erling Smørgrav }
156a0ee8cc6SDag-Erling Smørgrav
157bc5531deSDag-Erling Smørgrav static void
dump(u_char * p,size_t len)158bc5531deSDag-Erling Smørgrav dump(u_char *p, size_t len)
159bc5531deSDag-Erling Smørgrav {
160bc5531deSDag-Erling Smørgrav size_t i, j;
161bc5531deSDag-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
183bc5531deSDag-Erling Smørgrav void
fuzz_dump(struct fuzz * fuzz)184bc5531deSDag-Erling Smørgrav fuzz_dump(struct fuzz *fuzz)
185bc5531deSDag-Erling Smørgrav {
186bc5531deSDag-Erling Smørgrav char buf[256];
187bc5531deSDag-Erling Smørgrav
188bc5531deSDag-Erling Smørgrav if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
189bc5531deSDag-Erling Smørgrav fprintf(stderr, "%s: fuzz invalid\n", __func__);
190bc5531deSDag-Erling Smørgrav abort();
191bc5531deSDag-Erling Smørgrav }
192bc5531deSDag-Erling Smørgrav fputs(buf, stderr);
193bc5531deSDag-Erling Smørgrav fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
194bc5531deSDag-Erling Smørgrav dump(fuzz->seed, fuzz->slen);
195bc5531deSDag-Erling Smørgrav fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
196bc5531deSDag-Erling Smørgrav dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
197bc5531deSDag-Erling Smørgrav }
198bc5531deSDag-Erling Smørgrav
199bc5531deSDag-Erling Smørgrav static struct fuzz *last_fuzz;
200bc5531deSDag-Erling Smørgrav
201bc5531deSDag-Erling Smørgrav static void
siginfo(int unused)202bc5531deSDag-Erling Smørgrav siginfo(int unused __attribute__((__unused__)))
203bc5531deSDag-Erling Smørgrav {
204bc5531deSDag-Erling Smørgrav char buf[256];
205bc5531deSDag-Erling Smørgrav
206bc5531deSDag-Erling Smørgrav test_info(buf, sizeof(buf));
207bc5531deSDag-Erling Smørgrav atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
208bc5531deSDag-Erling Smørgrav if (last_fuzz != NULL) {
209bc5531deSDag-Erling Smørgrav fuzz_fmt(last_fuzz, buf, sizeof(buf));
210bc5531deSDag-Erling Smørgrav atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
211bc5531deSDag-Erling Smørgrav }
212bc5531deSDag-Erling Smørgrav }
213bc5531deSDag-Erling Smørgrav
214a0ee8cc6SDag-Erling Smørgrav struct fuzz *
fuzz_begin(u_int strategies,const void * p,size_t l)215a0ee8cc6SDag-Erling Smørgrav fuzz_begin(u_int strategies, const void *p, size_t l)
216a0ee8cc6SDag-Erling Smørgrav {
217a0ee8cc6SDag-Erling Smørgrav struct fuzz *ret = calloc(sizeof(*ret), 1);
218a0ee8cc6SDag-Erling Smørgrav
219a0ee8cc6SDag-Erling Smørgrav assert(p != NULL);
220a0ee8cc6SDag-Erling Smørgrav assert(ret != NULL);
221a0ee8cc6SDag-Erling Smørgrav ret->seed = malloc(l);
222a0ee8cc6SDag-Erling Smørgrav assert(ret->seed != NULL);
223a0ee8cc6SDag-Erling Smørgrav memcpy(ret->seed, p, l);
224a0ee8cc6SDag-Erling Smørgrav ret->slen = l;
225a0ee8cc6SDag-Erling Smørgrav ret->strategies = strategies;
226a0ee8cc6SDag-Erling Smørgrav
227a0ee8cc6SDag-Erling Smørgrav assert(ret->slen < SIZE_MAX / 8);
228a0ee8cc6SDag-Erling Smørgrav assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
229a0ee8cc6SDag-Erling Smørgrav
230a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("begin, ret = %p", ret));
231a0ee8cc6SDag-Erling Smørgrav
232a0ee8cc6SDag-Erling Smørgrav fuzz_next(ret);
233bc5531deSDag-Erling Smørgrav
234bc5531deSDag-Erling Smørgrav last_fuzz = ret;
235*2f513db7SEd Maste #ifdef SIGINFO
236bc5531deSDag-Erling Smørgrav signal(SIGINFO, siginfo);
237bc5531deSDag-Erling Smørgrav #endif
238*2f513db7SEd Maste signal(SIGUSR1, siginfo);
239bc5531deSDag-Erling Smørgrav
240a0ee8cc6SDag-Erling Smørgrav return ret;
241a0ee8cc6SDag-Erling Smørgrav }
242a0ee8cc6SDag-Erling Smørgrav
243a0ee8cc6SDag-Erling Smørgrav void
fuzz_cleanup(struct fuzz * fuzz)244a0ee8cc6SDag-Erling Smørgrav fuzz_cleanup(struct fuzz *fuzz)
245a0ee8cc6SDag-Erling Smørgrav {
246a0ee8cc6SDag-Erling Smørgrav FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
247bc5531deSDag-Erling Smørgrav last_fuzz = NULL;
248*2f513db7SEd Maste #ifdef SIGINFO
249bc5531deSDag-Erling Smørgrav signal(SIGINFO, SIG_DFL);
250bc5531deSDag-Erling Smørgrav #endif
251*2f513db7SEd Maste signal(SIGUSR1, SIG_DFL);
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
fuzz_strategy_done(struct fuzz * fuzz)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
fuzz_next(struct fuzz * fuzz)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
fuzz_matches_original(struct fuzz * fuzz)381bc5531deSDag-Erling Smørgrav fuzz_matches_original(struct fuzz *fuzz)
382bc5531deSDag-Erling Smørgrav {
383bc5531deSDag-Erling Smørgrav if (fuzz_len(fuzz) != fuzz->slen)
384bc5531deSDag-Erling Smørgrav return 0;
385bc5531deSDag-Erling Smørgrav return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
386bc5531deSDag-Erling Smørgrav }
387bc5531deSDag-Erling Smørgrav
388bc5531deSDag-Erling Smørgrav int
fuzz_done(struct fuzz * fuzz)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
fuzz_len(struct fuzz * fuzz)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 *
fuzz_ptr(struct fuzz * fuzz)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