From 23c204455bf2198806e8c7b0cd86b20a50a379d0 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 9 Apr 2019 19:13:17 -0700 Subject: list-objects.c: handle unexpected non-blob entries Fix one of the cases described in the previous commit where a tree-entry that is promised to a blob is in fact a non-blob. When 'lookup_blob()' returns NULL, it is because Git has cached the requested object as a non-blob. In this case, prevent a SIGSEGV by 'die()'-ing immediately before attempting to dereference the result. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- list-objects.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'list-objects.c') diff --git a/list-objects.c b/list-objects.c index dc77361e11..ea04bbdee6 100644 --- a/list-objects.c +++ b/list-objects.c @@ -133,6 +133,11 @@ static void process_tree_contents(struct traversal_context *ctx, base, entry.path); else { struct blob *b = lookup_blob(ctx->revs->repo, &entry.oid); + if (!b) { + die(_("entry '%s' in tree %s has blob mode, " + "but is not a blob"), + entry.path, oid_to_hex(&tree->object.oid)); + } b->object.flags |= NOT_USER_GIVEN; process_blob(ctx, b, base, entry.path); } -- cgit v1.2.3 From b49e74eac480d167c3af8f1286fe520c3d7ce9e1 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Tue, 9 Apr 2019 19:13:19 -0700 Subject: list-objects.c: handle unexpected non-tree entries Apply similar treatment as the previous commit for non-tree entries, too. Signed-off-by: Taylor Blau Signed-off-by: Junio C Hamano --- list-objects.c | 5 +++++ t/t6102-rev-list-unexpected-objects.sh | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'list-objects.c') diff --git a/list-objects.c b/list-objects.c index ea04bbdee6..bb7e61ef4b 100644 --- a/list-objects.c +++ b/list-objects.c @@ -125,6 +125,11 @@ static void process_tree_contents(struct traversal_context *ctx, if (S_ISDIR(entry.mode)) { struct tree *t = lookup_tree(ctx->revs->repo, &entry.oid); + if (!t) { + die(_("entry '%s' in tree %s has tree mode, " + "but is not a tree"), + entry.path, oid_to_hex(&tree->object.oid)); + } t->object.flags |= NOT_USER_GIVEN; process_tree(ctx, t, base, entry.path); } diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 1377c60378..e3ec195532 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -34,8 +34,9 @@ test_expect_failure 'traverse unexpected non-tree entry (lone)' ' test_must_fail git rev-list --objects $broken_tree ' -test_expect_failure 'traverse unexpected non-tree entry (seen)' ' - test_must_fail git rev-list --objects $blob $broken_tree +test_expect_success 'traverse unexpected non-tree entry (seen)' ' + test_must_fail git rev-list --objects $blob $broken_tree >output 2>&1 && + test_i18ngrep "is not a tree" output ' test_expect_success 'setup unexpected non-commit parent' ' -- cgit v1.2.3 From 97dd512af7ce4afb4f638ef73b4770921c8ca3aa Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 9 Apr 2019 19:13:25 -0700 Subject: rev-list: detect broken root trees When the traversal machinery sees a commit without a root tree, it assumes that the tree was part of a BOUNDARY commit, and quietly ignores the tree. But it could also be caused by a commit whose root tree is broken or missing. Instead, let's die() when we see a NULL root tree. We can differentiate it from the BOUNDARY case by seeing if the commit was actually parsed. This covers that case, plus future-proofs us against any others where we might try to show an unparsed commit. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- list-objects.c | 3 +++ t/t6102-rev-list-unexpected-objects.sh | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'list-objects.c') diff --git a/list-objects.c b/list-objects.c index bb7e61ef4b..b5651ddd5b 100644 --- a/list-objects.c +++ b/list-objects.c @@ -374,6 +374,9 @@ static void do_traverse(struct traversal_context *ctx) struct tree *tree = get_commit_tree(commit); tree->object.flags |= NOT_USER_GIVEN; add_pending_tree(ctx->revs, tree); + } else if (commit->object.parsed) { + die(_("unable to load root tree for commit %s"), + oid_to_hex(&commit->object.oid)); } ctx->show_commit(commit, ctx->show_data); diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 28ee1bcb07..28611c978e 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -67,8 +67,10 @@ test_expect_success 'traverse unexpected non-tree root (lone)' ' test_must_fail git rev-list --objects $broken_commit ' -test_expect_failure 'traverse unexpected non-tree root (seen)' ' - test_must_fail git rev-list --objects $blob $broken_commit +test_expect_success 'traverse unexpected non-tree root (seen)' ' + test_must_fail git rev-list --objects $blob $broken_commit \ + >output 2>&1 && + test_i18ngrep "not a tree" output ' test_expect_success 'setup unexpected non-commit tag' ' -- cgit v1.2.3