On Wed, Dec 05 2018, Josh Steadmon wrote: > Breaks load_commit_graph_one() into a new function, > parse_commit_graph(). The latter function operates on arbitrary buffers, > which makes it suitable as a fuzzing target. > > Adds fuzz-commit-graph.c, which provides a fuzzing entry point > compatible with libFuzzer (and possibly other fuzzing engines). > > Signed-off-by: Josh Steadmon <steadmon@xxxxxxxxxx> > --- > .gitignore | 1 + > Makefile | 1 + > commit-graph.c | 63 +++++++++++++++++++++++++++++++++------------ > fuzz-commit-graph.c | 18 +++++++++++++ > 4 files changed, 66 insertions(+), 17 deletions(-) > create mode 100644 fuzz-commit-graph.c > > diff --git a/.gitignore b/.gitignore > index 0d77ea5894..8bcf153ed9 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -1,3 +1,4 @@ > +/fuzz-commit-graph > /fuzz_corpora > /fuzz-pack-headers > /fuzz-pack-idx > diff --git a/Makefile b/Makefile > index 1a44c811aa..6b72f37c29 100644 > --- a/Makefile > +++ b/Makefile > @@ -684,6 +684,7 @@ SCRIPTS = $(SCRIPT_SH_INS) \ > > ETAGS_TARGET = TAGS > > +FUZZ_OBJS += fuzz-commit-graph.o > FUZZ_OBJS += fuzz-pack-headers.o > FUZZ_OBJS += fuzz-pack-idx.o > > diff --git a/commit-graph.c b/commit-graph.c > index 40c855f185..0755359b1a 100644 > --- a/commit-graph.c > +++ b/commit-graph.c > @@ -46,6 +46,10 @@ > #define GRAPH_MIN_SIZE (GRAPH_HEADER_SIZE + 4 * GRAPH_CHUNKLOOKUP_WIDTH \ > + GRAPH_FANOUT_SIZE + GRAPH_OID_LEN) > > +struct commit_graph *parse_commit_graph(void *graph_map, int fd, > + size_t graph_size); > + > + > char *get_commit_graph_filename(const char *obj_dir) > { > return xstrfmt("%s/info/commit-graph", obj_dir); > @@ -84,16 +88,10 @@ static int commit_graph_compatible(struct repository *r) > struct commit_graph *load_commit_graph_one(const char *graph_file) > { > void *graph_map; > - const unsigned char *data, *chunk_lookup; > size_t graph_size; > struct stat st; > - uint32_t i; > - struct commit_graph *graph; > + struct commit_graph *ret; > int fd = git_open(graph_file); > - uint64_t last_chunk_offset; > - uint32_t last_chunk_id; > - uint32_t graph_signature; > - unsigned char graph_version, hash_version; > > if (fd < 0) > return NULL; > @@ -108,27 +106,61 @@ struct commit_graph *load_commit_graph_one(const char *graph_file) > die(_("graph file %s is too small"), graph_file); > } > graph_map = xmmap(NULL, graph_size, PROT_READ, MAP_PRIVATE, fd, 0); > + ret = parse_commit_graph(graph_map, fd, graph_size); > + > + if (ret == NULL) { Code in git usually uses just !ret. > + munmap(graph_map, graph_size); > + close(fd); > + exit(1); Ouch, exit(1) from load_commit_graph_one()? Can't we return NULL here instead? Nasty to exit from a library routine, but then I see later... > @@ -201,11 +235,6 @@ struct commit_graph *load_commit_graph_one(const char *graph_file) > } > > return graph; > - > -cleanup_fail: > - munmap(graph_map, graph_size); > - close(fd); > - exit(1); > } ... ah, I see this is where you got the exit(1) from. So it was there already. > static void prepare_commit_graph_one(struct repository *r, const char *obj_dir) > diff --git a/fuzz-commit-graph.c b/fuzz-commit-graph.c > new file mode 100644 > index 0000000000..420851d0d2 > --- /dev/null > +++ b/fuzz-commit-graph.c > @@ -0,0 +1,18 @@ > +#include "object-store.h" > +#include "commit-graph.h" > + > +struct commit_graph *parse_commit_graph(void *graph_map, int fd, > + size_t graph_size); > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); > + > +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) > +{ > + struct commit_graph *g; > + > + g = parse_commit_graph((void *) data, -1, size); > + if (g) > + free(g); > + > + return 0; > +} I hadn't looked at this before, but see your 5e47215080 ("fuzz: add basic fuzz testing target.", 2018-10-12) for some prior art. There's instructions there for a very long "make" invocation. Would be nice if this were friendlier and we could just do "make test-fuzz" or something...