From 213cad5417dd391e0d049f1adfda0aa4a10e9c22 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Thu, 3 Mar 2016 23:02:19 -0800 Subject: [PATCH] Initial commit. --- Makefile | 18 ++++++++++++++++++ buf.c | 37 ++++++++++++++++++++++++++++++++++++ buf.h | 23 +++++++++++++++++++++++ rand.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ rand.h | 7 +++++++ stutterfuzz.c | 35 ++++++++++++++++++++++++++++++++++ 6 files changed, 172 insertions(+) create mode 100644 Makefile create mode 100644 buf.c create mode 100644 buf.h create mode 100644 rand.c create mode 100644 rand.h create mode 100644 stutterfuzz.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5115726 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +COMP ?= clang +DISABLED_WARNINGS ?= +CFLAGS ?= -Weverything -Werror -O3 -g --std=gnu11 --pedantic-errors -fPIE -fstack-protector-strong -D_GNU_SOURCE $(DISABLED_WARNINGS) +LDFLAGS ?= $(CFLAGS) -Wl,-z,relro -Wl,-z,now -pie +LIBS ?= + +OBJ = buf.o rand.o + +all: stutterfuzz + +clean: + rm -rf *.o stutterfuzz + +%.o: %.c *.h + $(COMP) -c $(CFLAGS) $< -o $@ + +stutterfuzz: stutterfuzz.o $(OBJ) + $(COMP) $(LDFLAGS) -o stutterfuzz stutterfuzz.o $(OBJ) diff --git a/buf.c b/buf.c new file mode 100644 index 0000000..a31299a --- /dev/null +++ b/buf.c @@ -0,0 +1,37 @@ +#include +#include +#include + +#include "buf.h" + +void buf_init(struct buf *buf) { + buf->start = 0; + buf->length = 0; +} + +ssize_t buf_fill(struct buf *buf, int fd) { + if (buf->start + buf->length == BUF_LEN_MAX) { + assert(buf->start > 0); + memmove(buf->buf, buf_at(buf, 0), buf->length); + buf->start = 0; + } + + size_t space = BUF_LEN_MAX - buf->length - buf->start; + ssize_t in = read(fd, buf_at(buf, buf->length), space); + if (in <= 0) { + return in; + } + buf->length += (size_t) in; + return in; +} + +void buf_consume(struct buf *buf, size_t length) { + assert(buf->length >= length); + + buf->length -= length; + if (buf->length) { + buf->start += length; + } else { + buf->start = 0; + } +} diff --git a/buf.h b/buf.h new file mode 100644 index 0000000..b34b85d --- /dev/null +++ b/buf.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include + +#define BUF_LEN_MAX 256 +struct buf { + uint8_t buf[BUF_LEN_MAX]; + size_t start; + size_t length; +}; +#define BUF_INIT { \ + .start = 0, \ + .length = 0, \ +} + +#define buf_chr(buff, at) ((buff)->buf[(buff)->start + (at)]) +#define buf_at(buff, at) (&buf_chr(buff, at)) + +void buf_init(struct buf *); +ssize_t buf_fill(struct buf *, int); +void buf_consume(struct buf *, size_t); diff --git a/rand.c b/rand.c new file mode 100644 index 0000000..82d6563 --- /dev/null +++ b/rand.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "buf.h" + +#include "rand.h" + +static struct buf rand_buf = BUF_INIT; +static int rand_fd; + +void rand_init() { + rand_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + assert(rand_fd >= 0); + assert(read(rand_fd, buf_at(&rand_buf, 0), BUF_LEN_MAX) == BUF_LEN_MAX); + rand_buf.length = BUF_LEN_MAX; +} + +void rand_cleanup() { + assert(!close(rand_fd)); +} + +void rand_fill(void *value, size_t size) { + if (size <= rand_buf.length) { + memcpy(value, buf_at(&rand_buf, 0), size); + buf_consume(&rand_buf, size); + return; + } + + struct iovec iov[2] = { + { + .iov_base = rand_buf.buf, + .iov_len = rand_buf.start, + }, + { + .iov_base = value, + .iov_len = size, + }, + }; + + size_t bytes = rand_buf.start + size; + assert(bytes < SSIZE_MAX); + assert(readv(rand_fd, iov, 2) == (ssize_t) bytes); + rand_buf.start = 0; + rand_buf.length = BUF_LEN_MAX; +} diff --git a/rand.h b/rand.h new file mode 100644 index 0000000..37a361d --- /dev/null +++ b/rand.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void rand_init(void); +void rand_cleanup(void); +void rand_fill(void *, size_t); diff --git a/stutterfuzz.c b/stutterfuzz.c new file mode 100644 index 0000000..fc5c24a --- /dev/null +++ b/stutterfuzz.c @@ -0,0 +1,35 @@ +#include +#include + +#include "rand.h" + +static uint64_t sqrt64(uint64_t n) { + uint64_t g = UINT64_C(1) << 31; + + for (uint64_t c = g; c; g |= c) { + if (g * g > n) { + g ^= c; + } + c >>= 1; + } + return g; +} + +static uint64_t get_split(uint64_t len) { + uint64_t rnd; + rand_fill(&rnd, sizeof(rnd)); + rnd %= (len * len); + return sqrt64(rnd) + 1; +} + +int main(int __attribute__ ((unused)) argc, char __attribute__ ((unused)) *argv[]) { + rand_init(); + + for (uint64_t len = 1397; len;) { + uint64_t consume = get_split(len); + fprintf(stderr, "consume %ju bytes\n", (uintmax_t) consume); + len -= consume; + } + + rand_cleanup(); +}