зеркало из https://github.com/microsoft/git.git
commit-graph, fuzz: add fuzzer for commit-graph
Break 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. Since parse_commit_graph() is only called by load_commit_graph_one() (and the fuzzer described below), we omit error messages that would be duplicated by the caller. 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@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Родитель
77556354bb
Коммит
aa658574bf
|
@ -1,3 +1,4 @@
|
|||
/fuzz-commit-graph
|
||||
/fuzz_corpora
|
||||
/fuzz-pack-headers
|
||||
/fuzz-pack-idx
|
||||
|
|
1
Makefile
1
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
|
||||
|
||||
|
|
|
@ -84,16 +84,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 +102,55 @@ 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) {
|
||||
munmap(graph_map, graph_size);
|
||||
close(fd);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct commit_graph *parse_commit_graph(void *graph_map, int fd,
|
||||
size_t graph_size)
|
||||
{
|
||||
const unsigned char *data, *chunk_lookup;
|
||||
uint32_t i;
|
||||
struct commit_graph *graph;
|
||||
uint64_t last_chunk_offset;
|
||||
uint32_t last_chunk_id;
|
||||
uint32_t graph_signature;
|
||||
unsigned char graph_version, hash_version;
|
||||
|
||||
if (!graph_map)
|
||||
return NULL;
|
||||
|
||||
if (graph_size < GRAPH_MIN_SIZE)
|
||||
return NULL;
|
||||
|
||||
data = (const unsigned char *)graph_map;
|
||||
|
||||
graph_signature = get_be32(data);
|
||||
if (graph_signature != GRAPH_SIGNATURE) {
|
||||
error(_("graph signature %X does not match signature %X"),
|
||||
graph_signature, GRAPH_SIGNATURE);
|
||||
goto cleanup_fail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
graph_version = *(unsigned char*)(data + 4);
|
||||
if (graph_version != GRAPH_VERSION) {
|
||||
error(_("graph version %X does not match version %X"),
|
||||
graph_version, GRAPH_VERSION);
|
||||
goto cleanup_fail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hash_version = *(unsigned char*)(data + 5);
|
||||
if (hash_version != GRAPH_OID_VERSION) {
|
||||
error(_("hash version %X does not match version %X"),
|
||||
hash_version, GRAPH_OID_VERSION);
|
||||
goto cleanup_fail;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
graph = alloc_commit_graph();
|
||||
|
@ -152,7 +174,8 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
|
|||
if (chunk_offset > graph_size - GIT_MAX_RAWSZ) {
|
||||
error(_("improper chunk offset %08x%08x"), (uint32_t)(chunk_offset >> 32),
|
||||
(uint32_t)chunk_offset);
|
||||
goto cleanup_fail;
|
||||
free(graph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (chunk_id) {
|
||||
|
@ -187,7 +210,8 @@ struct commit_graph *load_commit_graph_one(const char *graph_file)
|
|||
|
||||
if (chunk_repeated) {
|
||||
error(_("chunk id %08x appears multiple times"), chunk_id);
|
||||
goto cleanup_fail;
|
||||
free(graph);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (last_chunk_id == GRAPH_CHUNKID_OIDLOOKUP)
|
||||
|
@ -201,11 +225,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);
|
||||
}
|
||||
|
||||
static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
|
||||
|
|
|
@ -54,6 +54,9 @@ struct commit_graph {
|
|||
|
||||
struct commit_graph *load_commit_graph_one(const char *graph_file);
|
||||
|
||||
struct commit_graph *parse_commit_graph(void *graph_map, int fd,
|
||||
size_t graph_size);
|
||||
|
||||
/*
|
||||
* Return 1 if and only if the repository has a commit-graph
|
||||
* file and generation numbers are computed in that file.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#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);
|
||||
free(g);
|
||||
|
||||
return 0;
|
||||
}
|
Загрузка…
Ссылка в новой задаче