]> git.ipfire.org Git - thirdparty/git.git/commitdiff
commit-graph.c: handle corrupt/missing trees
authorTaylor Blau <me@ttaylorr.com>
Thu, 5 Sep 2019 22:04:57 +0000 (18:04 -0400)
committerJunio C Hamano <gitster@pobox.com>
Mon, 9 Sep 2019 17:55:59 +0000 (10:55 -0700)
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 <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit-graph.c
commit.c
t/t5318-commit-graph.sh

index 6aa6998ecd3aa6aa02aa51811c5e9314f75c8879..cea1b37493fa212b5dbab81ed7a581570eb98ba8 100644 (file)
@@ -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;
 
index a98de16e3d570e09696a844b018bd4d580d9a30e..fab22cb74025b845ed99f701968b0a4bec8e79d0 100644 (file)
--- 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)
index abde8d4e900a360a7390d797235a4958c95a6c2e..5d2d88b100408a43676afe0b077ed64315521eb3 100755 (executable)
@@ -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 &&
        (