aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2017-02-20 11:37:43 +0100
committerMarc André Tanner <mat@brain-dump.org>2017-02-20 12:20:39 +0100
commit6911290dbb577fb295e556da6fd7e4f5f7c81a8a (patch)
tree96c2f8d5581a7987c8b1f2b95392900a709c0e83
parentf2548fc882ec951d48193ca488c41061cf887971 (diff)
downloadvis-6911290dbb577fb295e556da6fd7e4f5f7c81a8a.tar.gz
vis-6911290dbb577fb295e556da6fd7e4f5f7c81a8a.tar.xz
test/fuzz: add fuzzing infrastructure
For now we use the american fuzzy lop in the future we might also add libFuzzer support.
-rw-r--r--fuzz/.gitignore2
-rw-r--r--fuzz/Makefile28
-rw-r--r--fuzz/README.md30
-rw-r--r--fuzz/dictionaries/text-fuzzer.dict20
-rw-r--r--fuzz/fuzzer.h18
-rw-r--r--fuzz/inputs/text-fuzzer/text-fuzzer.in13
-rw-r--r--fuzz/text-fuzzer.c149
7 files changed, 260 insertions, 0 deletions
diff --git a/fuzz/.gitignore b/fuzz/.gitignore
new file mode 100644
index 0000000..af19e48
--- /dev/null
+++ b/fuzz/.gitignore
@@ -0,0 +1,2 @@
+/results
+/text-fuzzer
diff --git a/fuzz/Makefile b/fuzz/Makefile
new file mode 100644
index 0000000..66037a2
--- /dev/null
+++ b/fuzz/Makefile
@@ -0,0 +1,28 @@
+-include ../../config.mk
+
+ALL = text-fuzzer
+CC = afl-gcc
+CFLAGS += -I. -I../.. -DBUFFER_SIZE=4 -DBLOCK_SIZE=4
+
+test: $(ALL)
+
+text-fuzzer: text-fuzzer.c fuzzer.h ../../text.c ../../text-util.c ../../text-motions.c ../../text-objects.c ../../text-regex.c
+ @echo Compiling $@ binary
+ ${CC} ${CFLAGS} ${CFLAGS_STD} ${CFLAGS_EXTRA} ${filter %.c, $^} ${LDFLAGS} -o $@
+
+debug: clean
+ $(MAKE) CFLAGS_EXTRA='${CFLAGS_EXTRA} ${CFLAGS_DEBUG}'
+
+afl-fuzz-text: text-fuzzer
+ @mkdir -p "results/$<"
+ @afl-fuzz -i - -x "dictionaries/$<.dict" -o "results/$<" -- "./$<" || \
+ afl-fuzz -i "inputs/$<" -x "dictionaries/$<.dict" -o "results/$<" -- "./$<"
+
+clean:
+ @echo cleaning
+ @rm -f $(ALL)
+
+distclean: clean
+ @rm -rf results/
+
+.PHONY: clean distclean debug afl-fuzz-text
diff --git a/fuzz/README.md b/fuzz/README.md
new file mode 100644
index 0000000..3eabb7a
--- /dev/null
+++ b/fuzz/README.md
@@ -0,0 +1,30 @@
+Fuzzing infrastructure for low level code used by vis
+-----------------------------------------------------
+
+This directory contains some simple command line applications
+which expose core library interfaces through the standard I/O
+streams. They are intended to be used as test drivers for
+fuzzers like [AFL](http://lcamtuf.coredump.cx/afl/).
+
+Run one of the `make afl-fuzz-*` targets to start fuzzing a
+specific instrumented binary using `afl-fuzz(1)`. By default
+it will try to resume a previous fuzzing session, before
+starting a new one if that fails.
+
+The following files are used:
+
+ * `$APP-fuzzer.c` application exposing a simple text interface
+ * `fuzzer.h` common code used among different fuzzing drivers
+ * `./input/$APP/` intial test input, one file per test
+ * `./dictionaries/$APP.dict` a dictionary with valid syntax tokens
+ * `./results/$APP/` the fuzzing results are stored here
+
+See the AFL documentation for further information.
+
+In the future we might also use [libFuzzer](http://llvm.org/docs/LibFuzzer.html)
+for further fuzzing.
+
+Quick start example:
+
+ $ make afl-fuzz-text
+
diff --git a/fuzz/dictionaries/text-fuzzer.dict b/fuzz/dictionaries/text-fuzzer.dict
new file mode 100644
index 0000000..389141b
--- /dev/null
+++ b/fuzz/dictionaries/text-fuzzer.dict
@@ -0,0 +1,20 @@
+# AFL dictionary for text-fuzzer
+#
+# Not sure whether it makes sense to specify a dictionary,
+# the syntax is quite simple?
+#
+cmd_earlier="-"
+cmd_later="+"
+cmd_mark_get="?"
+# cmd_mark_set="= 0"
+cmd_mark_set="="
+cmd_size="#"
+# cmd_delete="d 0 1"
+cmd_delete="d"
+# cmd_insert="i 0 text"
+cmd_insert="i"
+cmd_print="p"
+cmd_quit="q"
+cmd_redo="r"
+cmd_snapshot="s"
+cmd_undo="u"
diff --git a/fuzz/fuzzer.h b/fuzz/fuzzer.h
new file mode 100644
index 0000000..3265532
--- /dev/null
+++ b/fuzz/fuzzer.h
@@ -0,0 +1,18 @@
+#ifndef FUZZER_H
+#define FUZZER_H
+
+enum CmdStatus {
+ CMD_FAIL = false,
+ CMD_OK = true,
+ CMD_ERR, /* syntax error */
+ CMD_QUIT, /* quit, accept no further commands */
+};
+
+static const char *cmd_status_msg[] = {
+ [CMD_FAIL] = "Fail\n",
+ [CMD_OK] = "",
+ [CMD_ERR] = "Syntax error\n",
+ [CMD_QUIT] = "Bye\n",
+};
+
+#endif
diff --git a/fuzz/inputs/text-fuzzer/text-fuzzer.in b/fuzz/inputs/text-fuzzer/text-fuzzer.in
new file mode 100644
index 0000000..11e910c
--- /dev/null
+++ b/fuzz/inputs/text-fuzzer/text-fuzzer.in
@@ -0,0 +1,13 @@
+i 0 text
+d 1 2
+s
+i 1 ex
+u
+r
+-
++
+p
+#
+= 2
+?
+q
diff --git a/fuzz/text-fuzzer.c b/fuzz/text-fuzzer.c
new file mode 100644
index 0000000..449e0dd
--- /dev/null
+++ b/fuzz/text-fuzzer.c
@@ -0,0 +1,149 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "fuzzer.h"
+#include "text.h"
+#include "text-util.h"
+#include "util.h"
+
+#ifndef BUFSIZ
+#define BUFSIZ 1024
+#endif
+
+typedef enum CmdStatus (*Cmd)(Text *txt, const char *cmd);
+
+static Mark mark = EMARK;
+
+static enum CmdStatus cmd_insert(Text *txt, const char *cmd) {
+ char data[BUFSIZ];
+ size_t pos;
+ if (sscanf(cmd, "%zu %s\n", &pos, data) != 2)
+ return CMD_ERR;
+ size_t len = strlen(data);
+ return text_insert(txt, pos, data, len);
+}
+
+static enum CmdStatus cmd_delete(Text *txt, const char *cmd) {
+ size_t pos, len;
+ if (sscanf(cmd, "%zu %zu", &pos, &len) != 2)
+ return CMD_ERR;
+ return text_delete(txt, pos, len);
+}
+
+static enum CmdStatus cmd_size(Text *txt, const char *cmd) {
+ printf("%zu bytes\n", text_size(txt));
+ return CMD_OK;
+}
+
+static enum CmdStatus cmd_snapshot(Text *txt, const char *cmd) {
+ text_snapshot(txt);
+ return CMD_OK;
+}
+
+static enum CmdStatus cmd_undo(Text *txt, const char *cmd) {
+ return text_undo(txt) != EPOS;
+}
+
+static enum CmdStatus cmd_redo(Text *txt, const char *cmd) {
+ return text_redo(txt) != EPOS;
+}
+
+static enum CmdStatus cmd_earlier(Text *txt, const char *cmd) {
+ return text_earlier(txt, 1) != EPOS;
+}
+
+static enum CmdStatus cmd_later(Text *txt, const char *cmd) {
+ return text_later(txt, 1) != EPOS;
+}
+
+static enum CmdStatus cmd_mark_set(Text *txt, const char *cmd) {
+ size_t pos;
+ if (sscanf(cmd, "%zu\n", &pos) != 1)
+ return CMD_ERR;
+ Mark m = text_mark_set(txt, pos);
+ if (m != EMARK)
+ mark = m;
+ return m != EMARK;
+}
+
+static enum CmdStatus cmd_mark_get(Text *txt, const char *cmd) {
+ size_t pos = text_mark_get(txt, mark);
+ if (pos != EPOS)
+ printf("%zu\n", pos);
+ return pos != EPOS;
+}
+
+static enum CmdStatus cmd_print(Text *txt, const char *cmd) {
+ size_t start = 0, size = text_size(txt), rem = size;
+ for (Iterator it = text_iterator_get(txt, start);
+ rem > 0 && text_iterator_valid(&it);
+ text_iterator_next(&it)) {
+ size_t prem = it.end - it.text;
+ if (prem > rem)
+ prem = rem;
+ if (fwrite(it.text, prem, 1, stdout) != 1)
+ return CMD_ERR;
+ rem -= prem;
+ }
+ if (rem != size)
+ puts("");
+ return rem == 0;
+}
+
+static enum CmdStatus cmd_quit(Text *txt, const char *cmd) {
+ return CMD_QUIT;
+}
+
+static Cmd commands[] = {
+ ['-'] = cmd_earlier,
+ ['+'] = cmd_later,
+ ['?'] = cmd_mark_get,
+ ['='] = cmd_mark_set,
+ ['#'] = cmd_size,
+ ['d'] = cmd_delete,
+ ['i'] = cmd_insert,
+ ['p'] = cmd_print,
+ ['q'] = cmd_quit,
+ ['r'] = cmd_redo,
+ ['s'] = cmd_snapshot,
+ ['u'] = cmd_undo,
+};
+
+int main(int argc, char *argv[]) {
+ char line[BUFSIZ], *name = (argc == 1) ? NULL : argv[1];
+ Text *txt = text_load(name);
+ if (!name)
+ name = "-";
+ if (!txt) {
+ fprintf(stderr, "Failed to load text from `%s'\n", name);
+ return 1;
+ }
+
+ printf("Loaded %zu bytes from `%s'\n", text_size(txt), name);
+
+ for (;;) {
+ printf("> ");
+ if (!fgets(line, sizeof(line), stdin))
+ break;
+ if (!isatty(0))
+ printf("%s", line);
+ if (line[0] == '\n')
+ continue;
+ size_t idx = line[0];
+ if (idx < LENGTH(commands) && commands[idx]) {
+ enum CmdStatus ret = commands[idx](txt, line+1);
+ printf("%s", cmd_status_msg[ret]);
+ if (ret == CMD_QUIT)
+ break;
+ } else {
+ puts("Invalid command");
+ }
+ }
+
+ text_free(txt);
+
+ return 0;
+}