From cde6f312e4eb8f90a17dd081fcc80433900e2a76 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 27 Dec 2019 13:40:26 +0100 Subject: [PATCH] fuzz: find bugs in the config syntax parser Signed-off-by: Jason A. Donenfeld --- src/fuzz/.gitignore | 1 + src/fuzz/Makefile | 16 +++++++++++ src/fuzz/config.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) create mode 100644 src/fuzz/.gitignore create mode 100644 src/fuzz/Makefile create mode 100644 src/fuzz/config.c diff --git a/src/fuzz/.gitignore b/src/fuzz/.gitignore new file mode 100644 index 0000000..04204c7 --- /dev/null +++ b/src/fuzz/.gitignore @@ -0,0 +1 @@ +config diff --git a/src/fuzz/Makefile b/src/fuzz/Makefile new file mode 100644 index 0000000..87a5dcd --- /dev/null +++ b/src/fuzz/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2018-2019 Jason A. Donenfeld . All Rights Reserved. + +all: config + +CFLAGS ?= -O3 -march=native -g +CFLAGS += -fsanitize=fuzzer -std=gnu11 -idirafter ../uapi + +config: config.c ../config.c ../encoding.c + clang $(CFLAGS) -o $@ $< + +clean: + rm -f config + +.PHONY: all clean diff --git a/src/fuzz/config.c b/src/fuzz/config.c new file mode 100644 index 0000000..4877ba7 --- /dev/null +++ b/src/fuzz/config.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2019 Jason A. Donenfeld . All Rights Reserved. + */ + +#include +#undef stderr +#define stderr stdin +#include "../config.c" +#include "../encoding.c" +#undef stderr + +#include +#include +#include +#include +#include "../config.h" + +const char *__asan_default_options() +{ + return "verbosity=1"; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t len) +{ + bool file; + char *input; + + if (len < 2) + return 0; + file = !!(data[0] >> 7); + input = malloc(len); + if (!input) + return 0; + memcpy(input, data + 1, len - 1); + input[len - 1] = '\0'; + + if (file) { + struct config_ctx ctx; + char *saveptr; + + config_read_init(&ctx, false); + for (char *line = strtok_r(input, "\n", &saveptr); line; line = strtok_r(NULL, "\n", &saveptr)) { + if (!config_read_line(&ctx, line)) + config_read_init(&ctx, false); + } + free_wgdevice(config_read_finish(&ctx)); + } else { + size_t spaces = 0; + char **argv, *saveptr; + + for (char *c = input; *c; ++c) { + if (*c == ' ') + ++spaces; + } + argv = calloc(spaces + 1, sizeof(char *)); + if (!argv) + goto out; + spaces = 0; + for (char *token = strtok_r(input, " ", &saveptr); token; token = strtok_r(NULL, " ", &saveptr)) + argv[spaces++] = token; + free_wgdevice(config_read_cmd(argv, spaces)); + free(argv); + } + +out: + free(input); + return 0; +}