comparison fuzz-wrapfd.c @ 1563:1cbb7b3d6703

Merge fuzzing branch
author Matt Johnston <matt@ucc.asn.au>
date Wed, 28 Feb 2018 22:12:05 +0800
parents 92c93b4a3646
children e75dab5bec71
comparison
equal deleted inserted replaced
1560:f5026f7486de 1563:1cbb7b3d6703
1 #define FUZZ_SKIP_WRAP 1
2 #include "includes.h"
3 #include "fuzz-wrapfd.h"
4
5 #include "fuzz.h"
6
7 #define IOWRAP_MAXFD (FD_SETSIZE-1)
8 static const int MAX_RANDOM_IN = 50000;
9 static const double CHANCE_CLOSE = 1.0 / 300;
10 static const double CHANCE_INTR = 1.0 / 200;
11 static const double CHANCE_READ1 = 0.6;
12 static const double CHANCE_READ2 = 0.3;
13 static const double CHANCE_WRITE1 = 0.8;
14 static const double CHANCE_WRITE2 = 0.3;
15
16 struct fdwrap {
17 enum wrapfd_mode mode;
18 buffer *buf;
19 int closein;
20 int closeout;
21 };
22
23 static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
24 /* for quick selection of in-use descriptors */
25 static int wrap_used[IOWRAP_MAXFD+1];
26 static unsigned int nused;
27 static unsigned short rand_state[3];
28
29 void wrapfd_setup() {
30 TRACE(("wrapfd_setup"))
31 nused = 0;
32 memset(wrap_fds, 0x0, sizeof(wrap_fds));
33 memset(wrap_used, 0x0, sizeof(wrap_used));
34
35 memset(rand_state, 0x0, sizeof(rand_state));
36 wrapfd_setseed(50);
37 }
38
39 void wrapfd_setseed(uint32_t seed) {
40 memcpy(rand_state, &seed, sizeof(seed));
41 nrand48(rand_state);
42 }
43
44 void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
45 TRACE(("wrapfd_add %d buf %p mode %d", fd, buf, mode))
46 assert(fd >= 0);
47 assert(fd <= IOWRAP_MAXFD);
48 assert(wrap_fds[fd].mode == UNUSED);
49 assert(buf || mode == RANDOMIN);
50
51 wrap_fds[fd].mode = mode;
52 wrap_fds[fd].buf = buf;
53 wrap_fds[fd].closein = 0;
54 wrap_fds[fd].closeout = 0;
55 wrap_used[nused] = fd;
56
57 nused++;
58 }
59
60 void wrapfd_remove(int fd) {
61 unsigned int i, j;
62 TRACE(("wrapfd_remove %d", fd))
63 assert(fd >= 0);
64 assert(fd <= IOWRAP_MAXFD);
65 assert(wrap_fds[fd].mode != UNUSED);
66 wrap_fds[fd].mode = UNUSED;
67
68
69 /* remove from used list */
70 for (i = 0, j = 0; i < nused; i++) {
71 if (wrap_used[i] != fd) {
72 wrap_used[j] = wrap_used[i];
73 j++;
74 }
75 }
76 nused--;
77 }
78
79 int wrapfd_close(int fd) {
80 if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) {
81 wrapfd_remove(fd);
82 return 0;
83 } else {
84 return close(fd);
85 }
86 }
87
88 int wrapfd_read(int fd, void *out, size_t count) {
89 size_t maxread;
90 buffer *buf;
91
92 if (!fuzz.wrapfds) {
93 return read(fd, out, count);
94 }
95
96 if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
97 /* XXX - assertion failure? */
98 TRACE(("Bad read descriptor %d\n", fd))
99 errno = EBADF;
100 return -1;
101 }
102
103 assert(count != 0);
104
105 if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
106 wrap_fds[fd].closein = 1;
107 errno = ECONNRESET;
108 return -1;
109 }
110
111 if (erand48(rand_state) < CHANCE_INTR) {
112 errno = EINTR;
113 return -1;
114 }
115
116 buf = wrap_fds[fd].buf;
117 if (buf) {
118 maxread = MIN(buf->len - buf->pos, count);
119 /* returns 0 if buf is EOF, as intended */
120 if (maxread > 0) {
121 maxread = nrand48(rand_state) % maxread + 1;
122 }
123 memcpy(out, buf_getptr(buf, maxread), maxread);
124 buf_incrpos(buf, maxread);
125 return maxread;
126 }
127
128 maxread = MIN(MAX_RANDOM_IN, count);
129 maxread = nrand48(rand_state) % maxread + 1;
130 memset(out, 0xef, maxread);
131 return maxread;
132 }
133
134 int wrapfd_write(int fd, const void* in, size_t count) {
135 unsigned const volatile char* volin = in;
136 unsigned int i;
137
138 if (!fuzz.wrapfds) {
139 return write(fd, in, count);
140 }
141
142 if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
143 /* XXX - assertion failure? */
144 TRACE(("Bad read descriptor %d\n", fd))
145 errno = EBADF;
146 return -1;
147 }
148
149 assert(count != 0);
150
151 /* force read to exercise sanitisers */
152 for (i = 0; i < count; i++) {
153 (void)volin[i];
154 }
155
156 if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) {
157 wrap_fds[fd].closeout = 1;
158 errno = ECONNRESET;
159 return -1;
160 }
161
162 if (erand48(rand_state) < CHANCE_INTR) {
163 errno = EINTR;
164 return -1;
165 }
166
167 return nrand48(rand_state) % (count+1);
168 }
169
170 int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
171 fd_set *exceptfds, struct timeval *timeout) {
172 int i, nset, sel;
173 int ret = 0;
174 int fdlist[IOWRAP_MAXFD+1];
175
176 memset(fdlist, 0x0, sizeof(fdlist));
177
178 if (!fuzz.wrapfds) {
179 return select(nfds, readfds, writefds, exceptfds, timeout);
180 }
181
182 assert(nfds <= IOWRAP_MAXFD+1);
183
184 if (erand48(rand_state) < CHANCE_INTR) {
185 errno = EINTR;
186 return -1;
187 }
188
189 /* read */
190 if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) {
191 for (i = 0, nset = 0; i < nfds; i++) {
192 if (FD_ISSET(i, readfds)) {
193 assert(wrap_fds[i].mode != UNUSED);
194 fdlist[nset] = i;
195 nset++;
196 }
197 }
198 FD_ZERO(readfds);
199
200 if (nset > 0) {
201 /* set one */
202 sel = fdlist[nrand48(rand_state) % nset];
203 FD_SET(sel, readfds);
204 ret++;
205
206 if (erand48(rand_state) < CHANCE_READ2) {
207 sel = fdlist[nrand48(rand_state) % nset];
208 if (!FD_ISSET(sel, readfds)) {
209 FD_SET(sel, readfds);
210 ret++;
211 }
212 }
213 }
214 }
215
216 /* write */
217 if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) {
218 for (i = 0, nset = 0; i < nfds; i++) {
219 if (FD_ISSET(i, writefds)) {
220 assert(wrap_fds[i].mode != UNUSED);
221 fdlist[nset] = i;
222 nset++;
223 }
224 }
225 FD_ZERO(writefds);
226
227 /* set one */
228 if (nset > 0) {
229 sel = fdlist[nrand48(rand_state) % nset];
230 FD_SET(sel, writefds);
231 ret++;
232
233 if (erand48(rand_state) < CHANCE_WRITE2) {
234 sel = fdlist[nrand48(rand_state) % nset];
235 if (!FD_ISSET(sel, writefds)) {
236 FD_SET(sel, writefds);
237 ret++;
238 }
239 }
240 }
241 }
242 return ret;
243 }
244