зеркало из https://github.com/microsoft/git.git
Merge branch 'tb/unexpected'
Code tightening against a "wrong" object appearing where an object of a different type is expected, instead of blindly assuming that the connection between objects are correctly made. * tb/unexpected: rev-list: detect broken root trees rev-list: let traversal die when --missing is not in use get_commit_tree(): return NULL for broken tree list-objects.c: handle unexpected non-tree entries list-objects.c: handle unexpected non-blob entries t: introduce tests for unexpected object types t: move 'hex2oct' into test-lib-functions.sh
This commit is contained in:
Коммит
ea2dab1abb
|
@ -379,7 +379,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
repo_init_revisions(the_repository, &revs, prefix);
|
||||
revs.abbrev = DEFAULT_ABBREV;
|
||||
revs.commit_format = CMIT_FMT_UNSPECIFIED;
|
||||
revs.do_not_die_on_missing_tree = 1;
|
||||
|
||||
/*
|
||||
* Scan the argument list before invoking setup_revisions(), so that we
|
||||
|
@ -409,6 +408,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
|
|||
}
|
||||
}
|
||||
|
||||
if (arg_missing_action)
|
||||
revs.do_not_die_on_missing_tree = 1;
|
||||
|
||||
argc = setup_revisions(argc, argv, &revs, &s_r_opt);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
|
6
commit.c
6
commit.c
|
@ -351,10 +351,10 @@ struct tree *repo_get_commit_tree(struct repository *r,
|
|||
if (commit->maybe_tree || !commit->object.parsed)
|
||||
return commit->maybe_tree;
|
||||
|
||||
if (commit->graph_pos == COMMIT_NOT_FROM_GRAPH)
|
||||
BUG("commit has NULL tree, but was not loaded from commit-graph");
|
||||
if (commit->graph_pos != COMMIT_NOT_FROM_GRAPH)
|
||||
return get_commit_tree_in_graph(r, commit);
|
||||
|
||||
return get_commit_tree_in_graph(r, commit);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct object_id *get_commit_tree_oid(const struct commit *commit)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -133,6 +138,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);
|
||||
}
|
||||
|
@ -364,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);
|
||||
|
||||
|
|
|
@ -199,10 +199,6 @@ test_expect_success 'too-short tree' '
|
|||
test_i18ngrep "too-short tree object" err
|
||||
'
|
||||
|
||||
hex2oct() {
|
||||
perl -ne 'printf "\\%03o", hex for /../g'
|
||||
}
|
||||
|
||||
test_expect_success 'malformed mode in tree' '
|
||||
hex_sha1=$(echo foo | git hash-object --stdin -w) &&
|
||||
bin_sha1=$(echo $hex_sha1 | hex2oct) &&
|
||||
|
|
|
@ -256,10 +256,6 @@ test_expect_success 'unparseable tree object' '
|
|||
test_i18ngrep ! "fatal: empty filename in tree entry" out
|
||||
'
|
||||
|
||||
hex2oct() {
|
||||
perl -ne 'printf "\\%03o", hex for /../g'
|
||||
}
|
||||
|
||||
test_expect_success 'tree entry with type mismatch' '
|
||||
test_when_finished "remove_object \$blob" &&
|
||||
test_when_finished "remove_object \$tree" &&
|
||||
|
|
|
@ -611,10 +611,6 @@ test_expect_success 'GIT_TRACE_PACKFILE produces a usable pack' '
|
|||
git -C replay.git index-pack -v --stdin <tmp.pack
|
||||
'
|
||||
|
||||
hex2oct () {
|
||||
perl -ne 'printf "\\%03o", hex for /../g'
|
||||
}
|
||||
|
||||
test_expect_success 'clone on case-insensitive fs' '
|
||||
git init icasefs &&
|
||||
(
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
#!/bin/sh
|
||||
|
||||
test_description='git rev-list should handle unexpected object types'
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
test_expect_success 'setup well-formed objects' '
|
||||
blob="$(printf "foo" | git hash-object -w --stdin)" &&
|
||||
tree="$(printf "100644 blob $blob\tfoo" | git mktree)" &&
|
||||
commit="$(git commit-tree $tree -m "first commit")" &&
|
||||
git cat-file commit $commit >good-commit
|
||||
'
|
||||
|
||||
test_expect_success 'setup unexpected non-blob entry' '
|
||||
printf "100644 foo\0$(echo $tree | hex2oct)" >broken-tree &&
|
||||
broken_tree="$(git hash-object -w --literally -t tree broken-tree)"
|
||||
'
|
||||
|
||||
test_expect_failure 'traverse unexpected non-blob entry (lone)' '
|
||||
test_must_fail git rev-list --objects $broken_tree
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-blob entry (seen)' '
|
||||
test_must_fail git rev-list --objects $tree $broken_tree >output 2>&1 &&
|
||||
test_i18ngrep "is not a blob" output
|
||||
'
|
||||
|
||||
test_expect_success 'setup unexpected non-tree entry' '
|
||||
printf "40000 foo\0$(echo $blob | hex2oct)" >broken-tree &&
|
||||
broken_tree="$(git hash-object -w --literally -t tree broken-tree)"
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-tree entry (lone)' '
|
||||
test_must_fail git rev-list --objects $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' '
|
||||
sed "/^author/ { h; s/.*/parent $blob/; G; }" <good-commit \
|
||||
>broken-commit &&
|
||||
broken_commit="$(git hash-object -w --literally -t commit \
|
||||
broken-commit)"
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-commit parent (lone)' '
|
||||
test_must_fail git rev-list --objects $broken_commit >output 2>&1 &&
|
||||
test_i18ngrep "not a commit" output
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-commit parent (seen)' '
|
||||
test_must_fail git rev-list --objects $commit $broken_commit \
|
||||
>output 2>&1 &&
|
||||
test_i18ngrep "not a commit" output
|
||||
'
|
||||
|
||||
test_expect_success 'setup unexpected non-tree root' '
|
||||
sed -e "s/$tree/$blob/" <good-commit >broken-commit &&
|
||||
broken_commit="$(git hash-object -w --literally -t commit \
|
||||
broken-commit)"
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-tree root (lone)' '
|
||||
test_must_fail git rev-list --objects $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' '
|
||||
git tag -a -m "tagged commit" tag $commit &&
|
||||
git cat-file tag tag >good-tag &&
|
||||
test_when_finished "git tag -d tag" &&
|
||||
sed -e "s/$commit/$blob/" <good-tag >broken-tag &&
|
||||
tag=$(git hash-object -w --literally -t tag broken-tag)
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-commit tag (lone)' '
|
||||
test_must_fail git rev-list --objects $tag
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-commit tag (seen)' '
|
||||
test_must_fail git rev-list --objects $blob $tag >output 2>&1 &&
|
||||
test_i18ngrep "not a commit" output
|
||||
'
|
||||
|
||||
test_expect_success 'setup unexpected non-tree tag' '
|
||||
git tag -a -m "tagged tree" tag $tree &&
|
||||
git cat-file tag tag >good-tag &&
|
||||
test_when_finished "git tag -d tag" &&
|
||||
sed -e "s/$tree/$blob/" <good-tag >broken-tag &&
|
||||
tag=$(git hash-object -w --literally -t tag broken-tag)
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-tree tag (lone)' '
|
||||
test_must_fail git rev-list --objects $tag
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-tree tag (seen)' '
|
||||
test_must_fail git rev-list --objects $blob $tag >output 2>&1 &&
|
||||
test_i18ngrep "not a tree" output
|
||||
'
|
||||
|
||||
test_expect_success 'setup unexpected non-blob tag' '
|
||||
git tag -a -m "tagged blob" tag $blob &&
|
||||
git cat-file tag tag >good-tag &&
|
||||
test_when_finished "git tag -d tag" &&
|
||||
sed -e "s/$blob/$commit/" <good-tag >broken-tag &&
|
||||
tag=$(git hash-object -w --literally -t tag broken-tag)
|
||||
'
|
||||
|
||||
test_expect_failure 'traverse unexpected non-blob tag (lone)' '
|
||||
test_must_fail git rev-list --objects $tag
|
||||
'
|
||||
|
||||
test_expect_success 'traverse unexpected non-blob tag (seen)' '
|
||||
test_must_fail git rev-list --objects $commit $tag >output 2>&1 &&
|
||||
test_i18ngrep "not a blob" output
|
||||
'
|
||||
|
||||
test_done
|
|
@ -1239,6 +1239,12 @@ depacketize () {
|
|||
'
|
||||
}
|
||||
|
||||
# Converts base-16 data into base-8. The output is given as a sequence of
|
||||
# escaped octals, suitable for consumption by 'printf'.
|
||||
hex2oct () {
|
||||
perl -ne 'printf "\\%03o", hex for /../g'
|
||||
}
|
||||
|
||||
# Set the hash algorithm in use to $1. Only useful when testing the testsuite.
|
||||
test_set_hash () {
|
||||
test_hash_algo="$1"
|
||||
|
|
Загрузка…
Ссылка в новой задаче