From 806278dead57766bf000af62dcb8892ee3a24956 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Thu, 5 Sep 2019 18:04:57 -0400 Subject: commit-graph.c: handle corrupt/missing trees Apply similar treatment as in the previous commit to handle an unchecked call to 'get_commit_tree_oid()'. Previously, a NULL return value from this function would be immediately dereferenced with '->hash', and then cause a segfault. Before dereferencing to access the 'hash' member, check the return value of 'get_commit_tree_oid()' to make sure that it is not NULL. To make this check correct, a related change is also needed in 'commit.c', which is to check the return value of 'get_commit_tree' before taking its address. If 'get_commit_tree' returns NULL, we encounter an undefined behavior when taking the address of the return value of 'get_commit_tree' and then taking '->object.oid'. (On my system, this is memory address 0x8, which is obviously wrong). Fix this by making sure that 'get_commit_tree' returns something non-NULL before digging through a structure that is not there, thus preventing a segfault down the line in the commit graph code. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano diff --git a/commit-graph.c b/commit-graph.c index 6aa6998..cea1b37 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -839,6 +839,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len, while (list < last) { struct commit_list *parent; + struct object_id *tree; int edge_value; uint32_t packedDate[2]; display_progress(ctx->progress, ++ctx->progress_cnt); @@ -846,7 +847,11 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len, if (parse_commit_no_graph(*list)) die(_("unable to parse commit %s"), oid_to_hex(&(*list)->object.oid)); - hashwrite(f, get_commit_tree_oid(*list)->hash, hash_len); + tree = get_commit_tree_oid(*list); + if (!tree) + die(_("unable to get tree for %s"), + oid_to_hex(&(*list)->object.oid)); + hashwrite(f, tree->hash, hash_len); parent = (*list)->parents; diff --git a/commit.c b/commit.c index a98de16..fab22cb 100644 --- a/commit.c +++ b/commit.c @@ -358,7 +358,8 @@ struct tree *repo_get_commit_tree(struct repository *r, struct object_id *get_commit_tree_oid(const struct commit *commit) { - return &get_commit_tree(commit)->object.oid; + struct tree *tree = get_commit_tree(commit); + return tree ? &tree->object.oid : NULL; } void release_commit_memory(struct parsed_object_pool *pool, struct commit *c) diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index abde8d4..5d2d88b 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -607,7 +607,7 @@ test_expect_success 'corrupt commit-graph write (broken parent)' ' ) ' -test_expect_failure 'corrupt commit-graph write (missing tree)' ' +test_expect_success 'corrupt commit-graph write (missing tree)' ' rm -rf repo && git init repo && ( -- cgit v0.10.2-6-g49f6