Mercurial > dropbear
comparison fuzz/fuzz-wrapfd.c @ 1756:d5680e12ac33
Move fuzzing code to fuzz/ subdirectory, improve Makefile.in
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 23 Oct 2020 23:10:20 +0800 |
parents | fuzz-wrapfd.c@28ab2cdb84bf |
children | 97ad26e397a5 |
comparison
equal
deleted
inserted
replaced
1753:7c0fcd19e492 | 1756:d5680e12ac33 |
---|---|
1 #define FUZZ_SKIP_WRAP 1 | |
2 #include "includes.h" | |
3 #include "fuzz-wrapfd.h" | |
4 | |
5 #include "dbutil.h" | |
6 | |
7 #include "fuzz.h" | |
8 | |
9 #define IOWRAP_MAXFD (FD_SETSIZE-1) | |
10 static const int MAX_RANDOM_IN = 50000; | |
11 static const double CHANCE_CLOSE = 1.0 / 600; | |
12 static const double CHANCE_INTR = 1.0 / 900; | |
13 static const double CHANCE_READ1 = 0.96; | |
14 static const double CHANCE_READ2 = 0.5; | |
15 static const double CHANCE_WRITE1 = 0.96; | |
16 static const double CHANCE_WRITE2 = 0.5; | |
17 | |
18 struct fdwrap { | |
19 enum wrapfd_mode mode; | |
20 int closein; | |
21 int closeout; | |
22 }; | |
23 | |
24 static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}}; | |
25 static int wrapfd_maxfd = -1; | |
26 static unsigned short rand_state[3]; | |
27 static buffer *input_buf; | |
28 static int devnull_fd = -1; | |
29 | |
30 static void wrapfd_remove(int fd); | |
31 | |
32 void wrapfd_setup(buffer *buf) { | |
33 TRACE(("wrapfd_setup")) | |
34 | |
35 // clean old ones | |
36 int i; | |
37 for (i = 0; i <= wrapfd_maxfd; i++) { | |
38 if (wrap_fds[i].mode == COMMONBUF) { | |
39 wrapfd_remove(i); | |
40 } | |
41 } | |
42 wrapfd_maxfd = -1; | |
43 | |
44 memset(rand_state, 0x0, sizeof(rand_state)); | |
45 wrapfd_setseed(50); | |
46 input_buf = buf; | |
47 } | |
48 | |
49 void wrapfd_setseed(uint32_t seed) { | |
50 memcpy(rand_state, &seed, sizeof(seed)); | |
51 nrand48(rand_state); | |
52 } | |
53 | |
54 int wrapfd_new() { | |
55 if (devnull_fd == -1) { | |
56 devnull_fd = open("/dev/null", O_RDONLY); | |
57 assert(devnull_fd != -1); | |
58 } | |
59 | |
60 int fd = dup(devnull_fd); | |
61 assert(fd != -1); | |
62 assert(wrap_fds[fd].mode == UNUSED); | |
63 wrap_fds[fd].mode = COMMONBUF; | |
64 wrap_fds[fd].closein = 0; | |
65 wrap_fds[fd].closeout = 0; | |
66 wrapfd_maxfd = MAX(fd, wrapfd_maxfd); | |
67 | |
68 return fd; | |
69 } | |
70 | |
71 static void wrapfd_remove(int fd) { | |
72 TRACE(("wrapfd_remove %d", fd)) | |
73 assert(fd >= 0); | |
74 assert(fd <= IOWRAP_MAXFD); | |
75 assert(wrap_fds[fd].mode != UNUSED); | |
76 wrap_fds[fd].mode = UNUSED; | |
77 m_close(fd); | |
78 } | |
79 | |
80 int wrapfd_close(int fd) { | |
81 if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) { | |
82 wrapfd_remove(fd); | |
83 return 0; | |
84 } else { | |
85 return close(fd); | |
86 } | |
87 } | |
88 | |
89 int wrapfd_read(int fd, void *out, size_t count) { | |
90 size_t maxread; | |
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 if (input_buf) { | |
117 maxread = MIN(input_buf->len - input_buf->pos, count); | |
118 /* returns 0 if buf is EOF, as intended */ | |
119 if (maxread > 0) { | |
120 maxread = nrand48(rand_state) % maxread + 1; | |
121 } | |
122 memcpy(out, buf_getptr(input_buf, maxread), maxread); | |
123 buf_incrpos(input_buf, maxread); | |
124 return maxread; | |
125 } | |
126 | |
127 maxread = MIN(MAX_RANDOM_IN, count); | |
128 maxread = nrand48(rand_state) % maxread + 1; | |
129 memset(out, 0xef, maxread); | |
130 return maxread; | |
131 } | |
132 | |
133 int wrapfd_write(int fd, const void* in, size_t count) { | |
134 unsigned const volatile char* volin = in; | |
135 unsigned int i; | |
136 | |
137 if (!fuzz.wrapfds) { | |
138 return write(fd, in, count); | |
139 } | |
140 | |
141 if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) { | |
142 /* XXX - assertion failure? */ | |
143 TRACE(("Bad read descriptor %d\n", fd)) | |
144 errno = EBADF; | |
145 return -1; | |
146 } | |
147 | |
148 assert(count != 0); | |
149 | |
150 /* force read to exercise sanitisers */ | |
151 for (i = 0; i < count; i++) { | |
152 (void)volin[i]; | |
153 } | |
154 | |
155 if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) { | |
156 wrap_fds[fd].closeout = 1; | |
157 errno = ECONNRESET; | |
158 return -1; | |
159 } | |
160 | |
161 if (erand48(rand_state) < CHANCE_INTR) { | |
162 errno = EINTR; | |
163 return -1; | |
164 } | |
165 | |
166 return nrand48(rand_state) % (count+1); | |
167 } | |
168 | |
169 int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds, | |
170 fd_set *exceptfds, struct timeval *timeout) { | |
171 int i, nset, sel; | |
172 int ret = 0; | |
173 int fdlist[IOWRAP_MAXFD+1]; | |
174 | |
175 if (!fuzz.wrapfds) { | |
176 return select(nfds, readfds, writefds, exceptfds, timeout); | |
177 } | |
178 | |
179 assert(nfds <= IOWRAP_MAXFD+1); | |
180 | |
181 if (erand48(rand_state) < CHANCE_INTR) { | |
182 errno = EINTR; | |
183 return -1; | |
184 } | |
185 | |
186 /* read */ | |
187 if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) { | |
188 for (i = 0, nset = 0; i < nfds; i++) { | |
189 if (FD_ISSET(i, readfds)) { | |
190 assert(wrap_fds[i].mode != UNUSED); | |
191 fdlist[nset] = i; | |
192 nset++; | |
193 } | |
194 } | |
195 DROPBEAR_FD_ZERO(readfds); | |
196 | |
197 if (nset > 0) { | |
198 /* set one */ | |
199 sel = fdlist[nrand48(rand_state) % nset]; | |
200 FD_SET(sel, readfds); | |
201 ret++; | |
202 | |
203 if (erand48(rand_state) < CHANCE_READ2) { | |
204 sel = fdlist[nrand48(rand_state) % nset]; | |
205 if (!FD_ISSET(sel, readfds)) { | |
206 FD_SET(sel, readfds); | |
207 ret++; | |
208 } | |
209 } | |
210 } | |
211 } | |
212 | |
213 /* write */ | |
214 if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) { | |
215 for (i = 0, nset = 0; i < nfds; i++) { | |
216 if (FD_ISSET(i, writefds)) { | |
217 assert(wrap_fds[i].mode != UNUSED); | |
218 fdlist[nset] = i; | |
219 nset++; | |
220 } | |
221 } | |
222 DROPBEAR_FD_ZERO(writefds); | |
223 | |
224 /* set one */ | |
225 if (nset > 0) { | |
226 sel = fdlist[nrand48(rand_state) % nset]; | |
227 FD_SET(sel, writefds); | |
228 ret++; | |
229 | |
230 if (erand48(rand_state) < CHANCE_WRITE2) { | |
231 sel = fdlist[nrand48(rand_state) % nset]; | |
232 if (!FD_ISSET(sel, writefds)) { | |
233 FD_SET(sel, writefds); | |
234 ret++; | |
235 } | |
236 } | |
237 } | |
238 } | |
239 return ret; | |
240 } | |
241 |