Skip to content

Commit e5cb51d

Browse files
committed
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: <[email protected]> * 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
2 parents 222f953 + 4dd3b04 commit e5cb51d

File tree

7 files changed

+51
-10
lines changed

7 files changed

+51
-10
lines changed

fsck.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ static int fsck_walk_tree(struct tree *tree, void *data, struct fsck_options *op
308308
return -1;
309309

310310
name = fsck_get_object_name(options, &tree->object.oid);
311-
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
311+
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
312312
return -1;
313313
while (tree_entry_gently(&desc, &entry)) {
314314
struct object *obj;
@@ -578,7 +578,7 @@ static int fsck_tree(const struct object_id *tree_oid,
578578
const char *o_name;
579579
struct name_stack df_dup_candidates = { NULL };
580580

581-
if (init_tree_desc_gently(&desc, buffer, size)) {
581+
if (init_tree_desc_gently(&desc, buffer, size, TREE_DESC_RAW_MODES)) {
582582
retval += report(options, tree_oid, OBJ_TREE,
583583
FSCK_MSG_BAD_TREE,
584584
"cannot be parsed as a tree");

fsck.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ enum fsck_msg_type {
5656
FUNC(GITMODULES_PATH, ERROR) \
5757
FUNC(GITMODULES_UPDATE, ERROR) \
5858
/* warnings */ \
59-
FUNC(BAD_FILEMODE, WARN) \
6059
FUNC(EMPTY_NAME, WARN) \
6160
FUNC(FULL_PATHNAME, WARN) \
6261
FUNC(HAS_DOT, WARN) \
@@ -66,6 +65,7 @@ enum fsck_msg_type {
6665
FUNC(ZERO_PADDED_FILEMODE, WARN) \
6766
FUNC(NUL_IN_COMMIT, WARN) \
6867
/* infos (reported as warnings, but ignored by default) */ \
68+
FUNC(BAD_FILEMODE, INFO) \
6969
FUNC(GITMODULES_PARSE, INFO) \
7070
FUNC(GITIGNORE_SYMLINK, INFO) \
7171
FUNC(GITATTRIBUTES_SYMLINK, INFO) \

packfile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2243,7 +2243,7 @@ static int add_promisor_object(const struct object_id *oid,
22432243
struct tree *tree = (struct tree *)obj;
22442244
struct tree_desc desc;
22452245
struct name_entry entry;
2246-
if (init_tree_desc_gently(&desc, tree->buffer, tree->size))
2246+
if (init_tree_desc_gently(&desc, tree->buffer, tree->size, 0))
22472247
/*
22482248
* Error messages are given when packs are
22492249
* verified, so do not print any here.

t/t1450-fsck.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,20 @@ test_expect_success 'tree entry with type mismatch' '
364364
test_i18ngrep ! "dangling blob" out
365365
'
366366

367+
test_expect_success 'tree entry with bogus mode' '
368+
test_when_finished "remove_object \$blob" &&
369+
test_when_finished "remove_object \$tree" &&
370+
blob=$(echo blob | git hash-object -w --stdin) &&
371+
blob_oct=$(echo $blob | hex2oct) &&
372+
tree=$(printf "100000 foo\0${blob_oct}" |
373+
git hash-object -t tree --stdin -w --literally) &&
374+
git fsck 2>err &&
375+
cat >expect <<-EOF &&
376+
warning in tree $tree: badFilemode: contains bad file modes
377+
EOF
378+
test_cmp expect err
379+
'
380+
367381
test_expect_success 'tag pointing to nonexistent' '
368382
badoid=$(test_oid deadbeef) &&
369383
cat >invalid-tag <<-EOF &&

t/t5504-fetch-receive-strict.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,21 @@ test_expect_success \
352352
grep "Cannot demote unterminatedheader" act
353353
'
354354

355+
test_expect_success 'badFilemode is not a strict error' '
356+
git init --bare badmode.git &&
357+
tree=$(
358+
cd badmode.git &&
359+
blob=$(echo blob | git hash-object -w --stdin | hex2oct) &&
360+
printf "123456 foo\0${blob}" |
361+
git hash-object -t tree --stdin -w --literally
362+
) &&
363+
364+
rm -rf dst.git &&
365+
git init --bare dst.git &&
366+
git -C dst.git config transfer.fsckObjects true &&
367+
368+
git -C badmode.git push ../dst.git $tree:refs/tags/tree 2>err &&
369+
grep "$tree: badFilemode" err
370+
'
371+
355372
test_done

tree-walk.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,20 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l
4747

4848
/* Initialize the descriptor entry */
4949
desc->entry.path = path;
50-
desc->entry.mode = canon_mode(mode);
50+
desc->entry.mode = (desc->flags & TREE_DESC_RAW_MODES) ? mode : canon_mode(mode);
5151
desc->entry.pathlen = len - 1;
5252
oidread(&desc->entry.oid, (const unsigned char *)path + len);
5353

5454
return 0;
5555
}
5656

57-
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, unsigned long size, struct strbuf *err)
57+
static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer,
58+
unsigned long size, struct strbuf *err,
59+
enum tree_desc_flags flags)
5860
{
5961
desc->buffer = buffer;
6062
desc->size = size;
63+
desc->flags = flags;
6164
if (size)
6265
return decode_tree_entry(desc, buffer, size, err);
6366
return 0;
@@ -66,15 +69,16 @@ static int init_tree_desc_internal(struct tree_desc *desc, const void *buffer, u
6669
void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size)
6770
{
6871
struct strbuf err = STRBUF_INIT;
69-
if (init_tree_desc_internal(desc, buffer, size, &err))
72+
if (init_tree_desc_internal(desc, buffer, size, &err, 0))
7073
die("%s", err.buf);
7174
strbuf_release(&err);
7275
}
7376

74-
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size)
77+
int init_tree_desc_gently(struct tree_desc *desc, const void *buffer, unsigned long size,
78+
enum tree_desc_flags flags)
7579
{
7680
struct strbuf err = STRBUF_INIT;
77-
int result = init_tree_desc_internal(desc, buffer, size, &err);
81+
int result = init_tree_desc_internal(desc, buffer, size, &err, flags);
7882
if (result)
7983
error("%s", err.buf);
8084
strbuf_release(&err);

tree-walk.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ struct tree_desc {
3434

3535
/* counts the number of bytes left in the `buffer`. */
3636
unsigned int size;
37+
38+
/* option flags passed via init_tree_desc_gently() */
39+
enum tree_desc_flags {
40+
TREE_DESC_RAW_MODES = (1 << 0),
41+
} flags;
3742
};
3843

3944
/**
@@ -79,7 +84,8 @@ int update_tree_entry_gently(struct tree_desc *);
7984
*/
8085
void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size);
8186

82-
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size);
87+
int init_tree_desc_gently(struct tree_desc *desc, const void *buf, unsigned long size,
88+
enum tree_desc_flags flags);
8389

8490
/*
8591
* Visit the next entry in a tree. Returns 1 when there are more entries

0 commit comments

Comments
 (0)