зеркало из https://github.com/microsoft/git.git
Merge branch 'jk/fsck-tree-mode-bits-fix' into maint
"git fsck" reads mode from tree objects but canonicalizes the mode before passing it to the logic to check object sanity, which has hid broken tree objects from the checking logic. This has been corrected, but to help exiting projects with broken tree objects that they cannot fix retroactively, the severity of anomalies this code detects has been demoted to "info" for now. source: <YvQcNpizy9uOZiAz@coredump.intra.peff.net> * jk/fsck-tree-mode-bits-fix: fsck: downgrade tree badFilemode to "info" fsck: actually detect bad file modes in trees tree-walk: add a mechanism for getting non-canonicalized modes
This commit is contained in:
Коммит
e5cb51d3aa
4
fsck.c
4
fsck.c
|
@ -308,7 +308,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
|
|||
return -1;
|
||||
|
||||
name = fsck_get_object_name(options, &tree->object.oid);
|
||||
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
|
||||
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
|
||||
return -1;
|
||||
while (tree_entry_gently(&desc, &entry)) {
|
||||
struct object *obj;
|
||||
|
@ -578,7 +578,7 @@ static int fsck_tree(const struct object_id *tree_oid,
|
|||
const char *o_name;
|
||||
struct name_stack df_dup_candidates = { NULL };
|
||||
|
||||
if (init_tree_desc_gently(&desc, buffer, size)) {
|
||||
if (init_tree_desc_gently(&desc, buffer, size, TREE_DESC_RAW_MODES)) {
|
||||
retval += report(options, tree_oid, OBJ_TREE,
|
||||
FSCK_MSG_BAD_TREE,
|
||||
"cannot be parsed as a tree");
|
||||
|
|
2
fsck.h
2
fsck.h
|
@ -56,7 +56,6 @@ enum fsck_msg_type {
|
|||
FUNC(GITMODULES_PATH, ERROR) \
|
||||
FUNC(GITMODULES_UPDATE, ERROR) \
|
||||
/* warnings */ \
|
||||
FUNC(BAD_FILEMODE, WARN) \
|
||||
FUNC(EMPTY_NAME, WARN) \
|
||||
FUNC(FULL_PATHNAME, WARN) \
|
||||
FUNC(HAS_DOT, WARN) \
|
||||
|
@ -66,6 +65,7 @@ enum fsck_msg_type {
|
|||
FUNC(ZERO_PADDED_FILEMODE, WARN) \
|
||||
FUNC(NUL_IN_COMMIT, WARN) \
|
||||
/* infos (reported as warnings, but ignored by default) */ \
|
||||
FUNC(BAD_FILEMODE, INFO) \
|
||||
FUNC(GITMODULES_PARSE, INFO) \
|
||||
FUNC(GITIGNORE_SYMLINK, INFO) \
|
||||
FUNC(GITATTRIBUTES_SYMLINK, INFO) \
|
||||
|
|
|
@ -2243,7 +2243,7 @@ static int add_promisor_object(const struct object_id *oid,
|
|||
struct tree *tree = (struct tree *)obj;
|
||||
struct tree_desc desc;
|
||||
struct name_entry entry;
|
||||
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
|
||||
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
|
||||
/*
|
||||
* Error messages are given when packs are
|
||||
* verified, so do not print any here.
|
||||
|
|
|
@ -364,6 +364,20 @@ test_expect_success 'tree entry with type mismatch' '
|
|||
test_i18ngrep ! "dangling blob" out
|
||||
'
|
||||
|
||||
test_expect_success 'tree entry with bogus mode' '
|
||||
test_when_finished "remove_object \$blob" &&
|
||||
test_when_finished "remove_object \$tree" &&
|
||||
blob=$(echo blob | git hash-object -w --stdin) &&
|
||||
blob_oct=$(echo $blob | hex2oct) &&
|
||||
tree=$(printf "100000 foo\0${blob_oct}" |
|
||||
git hash-object -t tree --stdin -w --literally) &&
|
||||
git fsck 2>err &&
|
||||
cat >expect <<-EOF &&
|
||||
warning in tree $tree: badFilemode: contains bad file modes
|
||||
EOF
|
||||
test_cmp expect err
|
||||
'
|
||||
|
||||
test_expect_success 'tag pointing to nonexistent' '
|
||||
badoid=$(test_oid deadbeef) &&
|
||||
cat >invalid-tag <<-EOF &&
|
||||
|
|
|
@ -352,4 +352,21 @@ test_expect_success \
|
|||
grep "Cannot demote unterminatedheader" act
|
||||
'
|
||||
|
||||
test_expect_success 'badFilemode is not a strict error' '
|
||||
git init --bare badmode.git &&
|
||||
tree=$(
|
||||
cd badmode.git &&
|
||||
blob=$(echo blob | git hash-object -w --stdin | hex2oct) &&
|
||||
printf "123456 foo\0${blob}" |
|
||||
git hash-object -t tree --stdin -w --literally
|
||||
) &&
|
||||
|
||||
rm -rf dst.git &&
|
||||
git init --bare dst.git &&
|
||||
git -C dst.git config transfer.fsckObjects true &&
|
||||
|
||||
git -C badmode.git push ../dst.git $tree:refs/tags/tree 2>err &&
|
||||
grep "$tree: badFilemode" err
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
14
tree-walk.c
14
tree-walk.c
|
@ -47,17 +47,20 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
|
|||
|
||||
/* Initialize the descriptor entry */
|
||||
desc->entry.path = path;
|
||||
desc->entry.mode = canon_mode(mode);
|
||||
desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode);
|
||||
desc->entry.pathlen = len - 1;
|
||||
oidread(&desc->entry.oid, (const unsigned char *)path + len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, unsigned long size, struct strbuf *err)
|
||||
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer,
|
||||
unsigned long size, struct strbuf *err,
|
||||
enum tree_desc_flags flags)
|
||||
{
|
||||
desc->buffer = buffer;
|
||||
desc->size = size;
|
||||
desc->flags = flags;
|
||||
if (size)
|
||||
return decode_tree_entry(desc, buffer, size, err);
|
||||
return 0;
|
||||
|
@ -66,15 +69,16 @@ static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, u
|
|||
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
|
||||
{
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
if (init_tree_desc_internal(desc, buffer, size, &err))
|
||||
if (init_tree_desc_internal(desc, buffer, size, &err, 0))
|
||||
die("%s", err.buf);
|
||||
strbuf_release(&err);
|
||||
}
|
||||
|
||||
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size)
|
||||
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size,
|
||||
enum tree_desc_flags flags)
|
||||
{
|
||||
struct strbuf err = STRBUF_INIT;
|
||||
int result = init_tree_desc_internal(desc, buffer, size, &err);
|
||||
int result = init_tree_desc_internal(desc, buffer, size, &err, flags);
|
||||
if (result)
|
||||
error("%s", err.buf);
|
||||
strbuf_release(&err);
|
||||
|
|
|
@ -34,6 +34,11 @@ struct tree_desc {
|
|||
|
||||
/* counts the number of bytes left in the `buffer`. */
|
||||
unsigned int size;
|
||||
|
||||
/* option flags passed via init_tree_desc_gently() */
|
||||
enum tree_desc_flags {
|
||||
TREE_DESC_RAW_MODES = (1 << 0),
|
||||
} flags;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -79,7 +84,8 @@ int update_tree_entry_gently(struct tree_desc *);
|
|||
*/
|
||||
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
|
||||
|
||||
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size);
|
||||
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size,
|
||||
enum tree_desc_flags flags);
|
||||
|
||||
/*
|
||||
* Visit the next entry in a tree. Returns 1 when there are more entries
|
||||
|
|
Загрузка…
Ссылка в новой задаче