fsck: complain when .gitmodules is a symlink

We've recently forbidden .gitmodules to be a symlink in verify_path(). And it's an easy way to circumvent our fsck checks for .gitmodules content. So let's complain when we see it. Signed-off-by: Jeff King <peff@peff.net>

Jeff King committed May 4, 2018 at 20:03 UTC b7b1fca175f1ed7933f361028c631b9ac86d868d
2 files changed +38 -2
fsck.c
+9 -2
@@ -63,6 +63,7 @@ static struct oidset gitmodules_done = OIDSET_INIT;
63 FUNC(GITMODULES_BLOB, ERROR) \
64 FUNC(GITMODULES_PARSE, ERROR) \
65 FUNC(GITMODULES_NAME, ERROR) \
66 + FUNC(GITMODULES_SYMLINK, ERROR) \
67 /* warnings */ \
68 FUNC(BAD_FILEMODE, WARN) \
69 FUNC(EMPTY_NAME, WARN) \
@@ -576,8 +577,14 @@ static int fsck_tree(struct tree *item, struct fsck_options *options)
577 has_dotgit |= is_hfs_dotgit(name) || is_ntfs_dotgit(name);
578 has_zero_pad |= *(char *)desc.buffer == '0';
579
579 - if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name))
580 - oidset_insert(&gitmodules_found, oid);
580 + if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) {
581 + if (!S_ISLNK(mode))
582 + oidset_insert(&gitmodules_found, oid);
583 + else
584 + retval += report(options, &item->object,
585 + FSCK_MSG_GITMODULES_SYMLINK,
586 + ".gitmodules is a symbolic link");
587 + }
588
589 if (update_tree_entry_gently(&desc)) {
590 retval += report(options, &item->object, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree");
t/t7415-submodule-names.sh
+29
@@ -122,4 +122,33 @@ test_expect_success 'transfer.fsckObjects handles odd pack (index)' '
122 test_must_fail git -C dst.git index-pack --strict --stdin <odd.pack
123 '
124
125 +test_expect_success 'fsck detects symlinked .gitmodules file' '
126 + git init symlink &&
127 + (
128 + cd symlink &&
129 +
130 + # Make the tree directly to avoid index restrictions.
131 + #
132 + # Because symlinks store the target as a blob, choose
133 + # a pathname that could be parsed as a .gitmodules file
134 + # to trick naive non-symlink-aware checking.
135 + tricky="[foo]bar=true" &&
136 + content=$(git hash-object -w ../.gitmodules) &&
137 + target=$(printf "$tricky" | git hash-object -w --stdin) &&
138 + tree=$(
139 + {
140 + printf "100644 blob $content\t$tricky\n" &&
141 + printf "120000 blob $target\t.gitmodules\n"
142 + } | git mktree
143 + ) &&
144 + commit=$(git commit-tree $tree) &&
145 +
146 + # Check not only that we fail, but that it is due to the
147 + # symlink detector; this grep string comes from the config
148 + # variable name and will not be translated.
149 + test_must_fail git fsck 2>output &&
150 + grep gitmodulesSymlink output
151 + )
152 +'
153 +
154 test_done