fuzz: add fuzzer for config parsing
PATCH 1/1 fuzz: add fuzzer for config parsing
From: Brian C Tracy <[email protected]>
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.
---
fuzz: add fuzzer for config parsing
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1692%2Fbriantracy%2Fconfig-fuzzer-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1692/briantracy/config-fuzzer-v1
Pull-Request: https://github.com/gitgitgadget/git/pull/1692
Makefile | 1 + ci/run-build-and-minimal-fuzzers.sh | 2 +- oss-fuzz/.gitignore | 1 + oss-fuzz/fuzz-config.c | 32 +++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 oss-fuzz/fuzz-config.c
Makefile +1 -0
@@ -760,6 +760,7 @@ FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.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 +1 -1
@@ -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 date pack-headers pack-idx config ; do begin_group "fuzz-$fuzzer" ./oss-fuzz/fuzz-$fuzzer -verbosity=0 -runs=1 || exit 1 end_group "fuzz-$fuzzer"
oss-fuzz/.gitignore +1 -0
@@ -2,3 +2,4 @@ fuzz-commit-graph fuzz-date fuzz-pack-headers fuzz-pack-idx +fuzz-config
oss-fuzz/fuzz-config.c new file +32 -0
@@ -0,0 +1,32 @@ +#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 *); + +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. Ensure a return of 0 to indicate +* success so the parsing continues. */ +int c =strlen (key); +if (value) + c +=strlen (value); +return c <0 ; +} + +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
Signature · 1 line
gitgitgadget
Makefile FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o · line 763
Quoted 9 lines · Brian Tracy via GitGitGadget
Makefile +1
-0@@ -760,6 +760,7 @@ FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.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
Keep the similar things alphabetically ordered, i.e. "config" comes after "commit-graph" before "date".
Makefile FUZZ_OBJS += oss-fuzz/fuzz-commit-graph.o · line 764
Quoted 2 lines
Makefile +1
-1-for fuzzer in commit-graph date pack-headers pack-idx ; do +for fuzzer in commit-graph date pack-headers pack-idx config ; do
Ditto.
oss-fuzz/.gitignore fuzz-commit-graph · line 5
Quoted 9 lines
oss-fuzz/.gitignore +1
-0@@ -2,3 +2,4 @@ fuzz-commit-graph fuzz-date fuzz-pack-headers fuzz-pack-idx +fuzz-config
Ditto.
oss-fuzz/fuzz-config.c line 5
Quoted 11 lines
oss-fuzz/fuzz-config.c new file +5
-0@@ -0,0 +1,32 @@ +#include "git-compat-util.h" +#include "config.h" + +#include <stdio.h> +#include <string.h>
You shouldn't have to include system header files yourself.
"git-compat-util.h" is there exactly for insulating yor code from details such as which system headers in what order need to be included and which CPP feature macros need to be defined before their inclusion, and including it as the first header file should be sufficient.
oss-fuzz/fuzz-config.c line 17
Quoted 12 lines
oss-fuzz/fuzz-config.c new file +12
-0+ +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. Ensure a return of 0 to indicate +* success so the parsing continues. */
/*
* Our multi-line comments are formatted with
* the slash-asterisk at the beginning and
* the asterisk-slash at the end on their
* own lines.
*/
oss-fuzz/fuzz-config.c line 18
Quoted 1 line
oss-fuzz/fuzz-config.c new file +1
-0+int c =strlen (key);
Isn't the type of return value from strlen() size_t? It should be available by inclusing "git-compat-util.h" to you for free.
oss-fuzz/fuzz-config.c line 21
Quoted 3 lines
oss-fuzz/fuzz-config.c new file +3
-0+if (value) + c +=strlen (value); +return c <0 ;
Is there a reason why this is not "return 0"? Is it to fool a clever compiler optimization that knows that omitting calls to git_config_from_mem() is safe if its callback function does not have externally observable side effects and always succeeds?
oss-fuzz/fuzz-config.c line 26
Quoted 5 lines
oss-fuzz/fuzz-config.c new file +5
-0+} + +int LLVMFuzzerTestOneInput (const uint8_t *data,const size_t size) +{ +struct config_options config_opts = {0 };
We still honor -Wdecl-after-statement and leave a blank line between the decl and the first statement here.
Quoted 8 lines
oss-fuzz/fuzz-config.c new file +6
-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
Thanks.
PATCH v2 1/1 fuzz: add fuzzer for config parsing
In reply to Brian Tracy via GitGitGadgetFrom: Brian C Tracy <[email protected]>
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.
---
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 <[email protected]>
## 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
Makefile +1 -0
@@ -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
ci/run-build-and-minimal-fuzzers.sh +1 -1
@@ -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"
oss-fuzz/.gitignore +1 -0
@@ -1,4 +1,5 @@ fuzz-commit-graph +fuzz-config fuzz-date fuzz-pack-headers fuzz-pack-idx
oss-fuzz/fuzz-config.c new file +33 -0
@@ -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
Signature · 1 line
gitgitgadget