summaryrefslogtreecommitdiff
path: root/fuzz-wrapfd.c
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2017-05-19 00:48:46 +0800
committerMatt Johnston <matt@ucc.asn.au>2017-05-19 00:48:46 +0800
commit8bb133a13195c94855b457e30add3755533bc836 (patch)
tree84a04af92d105091935d06188e081ae8a1c00cbf /fuzz-wrapfd.c
parent9de4780220d54bbbe41f37f3a41bf7a3a96b9f45 (diff)
downloaddropbear-8bb133a13195c94855b457e30add3755533bc836.tar.gz
add wrapfd. improve fuzzer in makefile
Diffstat (limited to 'fuzz-wrapfd.c')
-rw-r--r--fuzz-wrapfd.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/fuzz-wrapfd.c b/fuzz-wrapfd.c
new file mode 100644
index 0000000..7509afe
--- /dev/null
+++ b/fuzz-wrapfd.c
@@ -0,0 +1,193 @@
+#include "includes.h"
+#include "fuzz-wrapfd.h"
+
+static const int IOWRAP_MAXFD = FD_SETSIZE-1;
+static const int MAX_RANDOM_IN = 50000;
+static const double CHANCE_CLOSE = 1.0 / 300;
+static const double CHANCE_INTR = 1.0 / 200;
+static const double CHANCE_READ1 = 0.6;
+static const double CHANCE_READ2 = 0.3;
+static const double CHANCE_WRITE1 = 0.8;
+static const double CHANCE_WRITE2 = 0.3;
+
+struct fdwrap {
+ enum wrapfd_mode mode;
+ buffer *buf;
+};
+
+static struct fdwrap wrap_fds[IOWRAP_MAXFD+1];
+// for quick selection of in-use descriptors
+static int wrap_used[IOWRAP_MAXFD+1];
+static unsigned int nused;
+static unsigned short rand_state[3];
+
+void wrapfd_setup(uint32_t seed) {
+ nused = 0;
+ memset(wrap_fds, 0x0, sizeof(wrap_fds));
+
+ *((uint32_t*)rand_state) = seed;
+ nrand48(rand_state);
+}
+
+void wrapfd_add(int fd, buffer *buf, enum wrapfd_mode mode) {
+ assert(fd >= 0);
+ assert(fd <= IOWRAP_MAXFD);
+ assert(wrap_fds[fd].mode == UNUSED);
+ assert(buf || mode == RANDOMIN);
+
+ wrap_fds[fd].mode = mode;
+ wrap_fds[fd].buf = buf;
+ wrap_used[nused] = fd;
+
+ nused++;
+}
+
+void wrapfd_remove(int fd) {
+ unsigned int i, j;
+ assert(fd >= 0);
+ assert(fd <= IOWRAP_MAXFD);
+ assert(wrap_fds[fd].mode != UNUSED);
+ wrap_fds[fd].mode = UNUSED;
+
+ // remove from used list
+ for (i = 0, j = 0; i < nused; i++) {
+ if (wrap_used[i] != fd) {
+ wrap_used[j] = wrap_used[i];
+ j++;
+ }
+ }
+ nused--;
+}
+
+
+int wrapfd_read(int fd, void *out, size_t count) {
+ size_t maxread;
+ buffer *buf;
+
+ if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode != UNUSED) {
+ TRACE(("Bad read descriptor %d\n", fd))
+ errno = EBADF;
+ return -1;
+ }
+
+ assert(count != 0);
+
+ if (erand48(rand_state) < CHANCE_CLOSE) {
+ wrapfd_remove(fd);
+ return 0;
+ }
+
+ if (erand48(rand_state) < CHANCE_INTR) {
+ errno = EINTR;
+ return -1;
+ }
+
+ buf = wrap_fds[fd].buf;
+ if (buf) {
+ maxread = MIN(buf->len - buf->pos, count);
+ // returns 0 if buf is EOF, as intended
+ maxread = nrand48(rand_state) % maxread + 1;
+ memcpy(out, buf_getptr(buf, maxread), maxread);
+ buf_incrpos(buf, maxread);
+ return maxread;
+ }
+
+ maxread = MIN(MAX_RANDOM_IN, count);
+ maxread = nrand48(rand_state) % maxread + 1;
+ memset(out, 0xef, maxread);
+ return maxread;
+}
+
+int wrapfd_write(int fd, const void* in, size_t count) {
+ unsigned const volatile char* volin = in;
+ unsigned int i;
+ if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode != UNUSED) {
+ TRACE(("Bad read descriptor %d\n", fd))
+ errno = EBADF;
+ return -1;
+ }
+
+ assert(count != 0);
+
+ // force read to exercise sanitisers
+ for (i = 0; i < count; i++) {
+ (void)volin[i];
+ }
+
+ if (erand48(rand_state) < CHANCE_CLOSE) {
+ wrapfd_remove(fd);
+ return 0;
+ }
+
+ if (erand48(rand_state) < CHANCE_INTR) {
+ errno = EINTR;
+ return -1;
+ }
+
+ return nrand48(rand_state) % (count+1);
+}
+
+int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
+ fd_set *UNUSED(exceptfds), struct timeval *UNUSED(timeout)) {
+ int i, nset;
+ int ret = 0;
+ int fdlist[IOWRAP_MAXFD+1] = {0};
+
+ assert(nfds <= IOWRAP_MAXFD+1);
+
+ if (erand48(rand_state) < CHANCE_INTR) {
+ errno = EINTR;
+ return -1;
+ }
+
+ // read
+ if (erand48(rand_state) < CHANCE_READ1) {
+ for (i = 0, nset = 0; i < nfds; i++) {
+ if (FD_ISSET(i, readfds)) {
+ assert(wrap_fds[i].mode != UNUSED);
+ fdlist[nset] = i;
+ }
+ }
+ FD_ZERO(readfds);
+
+ if (nset > 0) {
+ // set one
+ FD_SET(fdlist[random() % nset], readfds);
+ ret++;
+
+ if (erand48(rand_state) < CHANCE_READ2) {
+ i = fdlist[random() % nset];
+ if (!FD_ISSET(i, readfds)) {
+ FD_SET(i, readfds);
+ ret++;
+ }
+ }
+ }
+ }
+
+ // write
+ if (erand48(rand_state) < CHANCE_WRITE1) {
+ for (i = 0, nset = 0; i < nfds; i++) {
+ if (FD_ISSET(i, writefds)) {
+ assert(wrap_fds[i].mode != UNUSED);
+ fdlist[nset] = i;
+ }
+ }
+ FD_ZERO(writefds);
+
+ // set one
+ if (nset > 0) {
+ FD_SET(fdlist[nrand48(rand_state) % nset], writefds);
+ ret++;
+
+ if (erand48(rand_state) < CHANCE_WRITE2) {
+ i = fdlist[nrand48(rand_state) % nset];
+ if (!FD_ISSET(i, writefds)) {
+ FD_SET(i, writefds);
+ ret++;
+ }
+ }
+ }
+ }
+ return ret;
+}