From: Brian C Tracy <brian.tracy33@xxxxxxxxx> Add a new fuzz target that exercises the parsing of git configs. The existing git_config_from_mem function is a perfect entry point for fuzzing as it exercises the same code paths as the rest of the config parsing functions and offers an easily fuzzable interface. Config parsing is a useful thing to fuzz because it operates on user controlled data and is a central component of many git operations. Signed-off-by: Brian C Tracy <brian.tracy33@xxxxxxxxx> --- fuzz: add fuzzer for config parsing Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1692%2Fbriantracy%2Fconfig-fuzzer-v2 Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1692/briantracy/config-fuzzer-v2 Pull-Request: https://github.com/gitgitgadget/git/pull/1692 Range-diff vs v1: 1: a43a2e3a07c ! 1: be6aa5efb1c fuzz: add fuzzer for config parsing @@ Commit message Signed-off-by: Brian C Tracy <brian.tracy33@xxxxxxxxx> ## Makefile ## -@@ Makefile: FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o +@@ Makefile: ETAGS_TARGET = TAGS + # runs in the future. + FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o + FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o ++FUZZ_OBJS += oss-fuzz/fuzz-config.o FUZZ_OBJS += oss-fuzz/fuzz-date.o FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o -+FUZZ_OBJS += oss-fuzz/fuzz-config.o - .PHONY: fuzz-objs - fuzz-objs: $(FUZZ_OBJS) - ## ci/run-build-and-minimal-fuzzers.sh ## @@ ci/run-build-and-minimal-fuzzers.sh: group "Build fuzzers" make \ @@ ci/run-build-and-minimal-fuzzers.sh: group "Build fuzzers" make \ fuzz-all -for fuzzer in commit-graph date pack-headers pack-idx ; do -+for fuzzer in commit-graph date pack-headers pack-idx config ; do ++for fuzzer in commit-graph config date pack-headers pack-idx ; do begin_group "fuzz-$fuzzer" ./oss-fuzz/fuzz-$fuzzer -verbosity=0 -runs=1 || exit 1 end_group "fuzz-$fuzzer" ## oss-fuzz/.gitignore ## -@@ oss-fuzz/.gitignore: fuzz-commit-graph +@@ + fuzz-commit-graph ++fuzz-config fuzz-date fuzz-pack-headers fuzz-pack-idx -+fuzz-config ## oss-fuzz/fuzz-config.c (new) ## @@ +#include "git-compat-util.h" +#include "config.h" + -+#include <stdio.h> -+#include <string.h> -+ +int LLVMFuzzerTestOneInput(const uint8_t *, size_t); +static int config_parser_callback(const char *, const char *, + const struct config_context *, void *); @@ oss-fuzz/fuzz-config.c (new) + const struct config_context *ctx UNUSED, + void *data UNUSED) +{ -+ /* Visit every byte of memory we are given to make sure the parser -+ * gave it to us appropriately. Ensure a return of 0 to indicate -+ * success so the parsing continues. */ -+ int c = strlen(key); ++ /* ++ * Visit every byte of memory we are given to make sure the parser ++ * gave it to us appropriately. We need to unconditionally return 0, ++ * but we also want to prevent the strlen from being optimized away. ++ */ ++ size_t c = strlen(key); ++ + if (value) + c += strlen(value); -+ return c < 0; ++ return c == SIZE_MAX; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, const size_t size) +{ + struct config_options config_opts = { 0 }; ++ + config_opts.error_action = CONFIG_ERROR_SILENT; + git_config_from_mem(config_parser_callback, CONFIG_ORIGIN_BLOB, + "fuzztest-config", (const char *)data, size, NULL, Makefile | 1 + ci/run-build-and-minimal-fuzzers.sh | 2 +- oss-fuzz/.gitignore | 1 + oss-fuzz/fuzz-config.c | 33 +++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 oss-fuzz/fuzz-config.c diff --git a/Makefile b/Makefile index 4e255c81f22..af32028b18f 100644 --- a/Makefile +++ b/Makefile @@ -757,6 +757,7 @@ ETAGS_TARGET = TAGS # runs in the future. FUZZ_OBJS += oss-fuzz/dummy-cmd-main.o FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o +FUZZ_OBJS += oss-fuzz/fuzz-config.o FUZZ_OBJS += oss-fuzz/fuzz-date.o FUZZ_OBJS += oss-fuzz/fuzz-pack-headers.o FUZZ_OBJS += oss-fuzz/fuzz-pack-idx.o diff --git a/ci/run-build-and-minimal-fuzzers.sh b/ci/run-build-and-minimal-fuzzers.sh index 8ba486f6598..a51076d18df 100755 --- a/ci/run-build-and-minimal-fuzzers.sh +++ b/ci/run-build-and-minimal-fuzzers.sh @@ -12,7 +12,7 @@ group "Build fuzzers" make \ LIB_FUZZING_ENGINE="-fsanitize=fuzzer,address" \ fuzz-all -for fuzzer in commit-graph date pack-headers pack-idx ; do +for fuzzer in commit-graph config date pack-headers pack-idx ; do begin_group "fuzz-$fuzzer" ./oss-fuzz/fuzz-$fuzzer -verbosity=0 -runs=1 || exit 1 end_group "fuzz-$fuzzer" diff --git a/oss-fuzz/.gitignore b/oss-fuzz/.gitignore index 5b954088254..a877c11f42b 100644 --- a/oss-fuzz/.gitignore +++ b/oss-fuzz/.gitignore @@ -1,4 +1,5 @@ fuzz-commit-graph +fuzz-config fuzz-date fuzz-pack-headers fuzz-pack-idx diff --git a/oss-fuzz/fuzz-config.c b/oss-fuzz/fuzz-config.c new file mode 100644 index 00000000000..94027f5b97e --- /dev/null +++ b/oss-fuzz/fuzz-config.c @@ -0,0 +1,33 @@ +#include "git-compat-util.h" +#include "config.h" + +int LLVMFuzzerTestOneInput(const uint8_t *, size_t); +static int config_parser_callback(const char *, const char *, + const struct config_context *, void *); + +static int config_parser_callback(const char *key, const char *value, + const struct config_context *ctx UNUSED, + void *data UNUSED) +{ + /* + * Visit every byte of memory we are given to make sure the parser + * gave it to us appropriately. We need to unconditionally return 0, + * but we also want to prevent the strlen from being optimized away. + */ + size_t c = strlen(key); + + if (value) + c += strlen(value); + return c == SIZE_MAX; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, const size_t size) +{ + struct config_options config_opts = { 0 }; + + config_opts.error_action = CONFIG_ERROR_SILENT; + git_config_from_mem(config_parser_callback, CONFIG_ORIGIN_BLOB, + "fuzztest-config", (const char *)data, size, NULL, + CONFIG_SCOPE_UNKNOWN, &config_opts); + return 0; +} base-commit: 945115026aa63df4ab849ab14a04da31623abece -- gitgitgadget