From patchwork Mon Oct 5 12:16:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816533 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7876213B2 for ; Mon, 5 Oct 2020 12:16:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5A557208E4 for ; Mon, 5 Oct 2020 12:16:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726576AbgJEMQ3 (ORCPT ); Mon, 5 Oct 2020 08:16:29 -0400 Received: from cloud.peff.net ([104.130.231.41]:49570 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726391AbgJEMQ3 (ORCPT ); Mon, 5 Oct 2020 08:16:29 -0400 Received: (qmail 32227 invoked by uid 109); 5 Oct 2020 12:16:28 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:28 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19014 invoked by uid 111); 5 Oct 2020 12:16:27 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:27 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:27 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 1/8] fsck_tree(): fix shadowed variable Message-ID: <20201005121627.GA2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Commit b2f2039c2b (fsck: accept an oid instead of a "struct tree" for fsck_tree(), 2019-10-18) introduced a new "oid" parameter to fsck_tree(), and we pass it to the report() function when we find problems. However, that is shadowed within the tree-walking loop by the existing "oid" variable which we use to store the oid of each tree entry. As a result, we may report the wrong oid for some problems we detect within the loop (the entry oid, instead of the tree oid). Our tests didn't catch this because they checked only that we found the expected fsck problem, not that it was attached to the correct object. Let's rename both variables in the function to avoid confusion. This makes the diff a little noisy (e.g., all of the report() calls outside the loop were already correct but need to be touched), but makes sure we catch all cases and will avoid similar confusion in the future. Note that our test change removes the comment about translation. It was arguably confusing since 674ba34038 (fsck: mark strings for translation, 2018-11-10); we wouldn't translate gitmodulesSymlink, but it did get removed by GETTEXT_POISON because that feature eats embedded %s characters. But certainly after this patch, when we look for the "tree %s: %s" format, we could get foiled by translation. Signed-off-by: Jeff King --- fsck.c | 40 +++++++++++++++++++------------------- t/t7415-submodule-names.sh | 8 ++++---- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/fsck.c b/fsck.c index f82e2fe9e3..46a108839f 100644 --- a/fsck.c +++ b/fsck.c @@ -633,7 +633,7 @@ static int verify_ordered(unsigned mode1, const char *name1, return c1 < c2 ? 0 : TREE_UNORDERED; } -static int fsck_tree(const struct object_id *oid, +static int fsck_tree(const struct object_id *tree_oid, const char *buffer, unsigned long size, struct fsck_options *options) { @@ -654,7 +654,7 @@ static int fsck_tree(const struct object_id *oid, struct name_stack df_dup_candidates = { NULL }; if (init_tree_desc_gently(&desc, buffer, size)) { - retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); return retval; } @@ -664,11 +664,11 @@ static int fsck_tree(const struct object_id *oid, while (desc.size) { unsigned short mode; const char *name, *backslash; - const struct object_id *oid; + const struct object_id *entry_oid; - oid = tree_entry_extract(&desc, &name, &mode); + entry_oid = tree_entry_extract(&desc, &name, &mode); - has_null_sha1 |= is_null_oid(oid); + has_null_sha1 |= is_null_oid(entry_oid); has_full_path |= !!strchr(name, '/'); has_empty_name |= !*name; has_dot |= !strcmp(name, "."); @@ -678,10 +678,10 @@ static int fsck_tree(const struct object_id *oid, if (is_hfs_dotgitmodules(name) || is_ntfs_dotgitmodules(name)) { if (!S_ISLNK(mode)) - oidset_insert(&gitmodules_found, oid); + oidset_insert(&gitmodules_found, entry_oid); else retval += report(options, - oid, OBJ_TREE, + tree_oid, OBJ_TREE, FSCK_MSG_GITMODULES_SYMLINK, ".gitmodules is a symbolic link"); } @@ -692,9 +692,9 @@ static int fsck_tree(const struct object_id *oid, has_dotgit |= is_ntfs_dotgit(backslash); if (is_ntfs_dotgitmodules(backslash)) { if (!S_ISLNK(mode)) - oidset_insert(&gitmodules_found, oid); + oidset_insert(&gitmodules_found, entry_oid); else - retval += report(options, oid, OBJ_TREE, + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_GITMODULES_SYMLINK, ".gitmodules is a symbolic link"); } @@ -703,7 +703,7 @@ static int fsck_tree(const struct object_id *oid, } if (update_tree_entry_gently(&desc)) { - retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); break; } @@ -751,25 +751,25 @@ static int fsck_tree(const struct object_id *oid, name_stack_clear(&df_dup_candidates); if (has_null_sha1) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1"); if (has_full_path) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_FULL_PATHNAME, "contains full pathnames"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_FULL_PATHNAME, "contains full pathnames"); if (has_empty_name) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_EMPTY_NAME, "contains empty pathname"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_EMPTY_NAME, "contains empty pathname"); if (has_dot) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOT, "contains '.'"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOT, "contains '.'"); if (has_dotdot) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOTDOT, "contains '..'"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOTDOT, "contains '..'"); if (has_dotgit) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_HAS_DOTGIT, "contains '.git'"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOTGIT, "contains '.git'"); if (has_zero_pad) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_ZERO_PADDED_FILEMODE, "contains zero-padded file modes"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_ZERO_PADDED_FILEMODE, "contains zero-padded file modes"); if (has_bad_modes) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_BAD_FILEMODE, "contains bad file modes"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_FILEMODE, "contains bad file modes"); if (has_dup_entries) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_DUPLICATE_ENTRIES, "contains duplicate file entries"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_DUPLICATE_ENTRIES, "contains duplicate file entries"); if (not_properly_sorted) - retval += report(options, oid, OBJ_TREE, FSCK_MSG_TREE_NOT_SORTED, "not properly sorted"); + retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_TREE_NOT_SORTED, "not properly sorted"); return retval; } diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh index f70368bc2e..d1781ef10c 100755 --- a/t/t7415-submodule-names.sh +++ b/t/t7415-submodule-names.sh @@ -148,13 +148,13 @@ test_expect_success 'fsck detects symlinked .gitmodules file' ' { printf "100644 blob $content\t$tricky\n" && printf "120000 blob $target\t.gitmodules\n" - } | git mktree && + } >bad-tree && + tree=$(git mktree output && - test_i18ngrep gitmodulesSymlink output + test_i18ngrep "tree $tree: gitmodulesSymlink" output ) ' From patchwork Mon Oct 5 12:16:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816537 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B9A2112E for ; Mon, 5 Oct 2020 12:16:37 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2A2CE20774 for ; Mon, 5 Oct 2020 12:16:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726597AbgJEMQe (ORCPT ); Mon, 5 Oct 2020 08:16:34 -0400 Received: from cloud.peff.net ([104.130.231.41]:49574 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726391AbgJEMQb (ORCPT ); Mon, 5 Oct 2020 08:16:31 -0400 Received: (qmail 32233 invoked by uid 109); 5 Oct 2020 12:16:31 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:31 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19024 invoked by uid 111); 5 Oct 2020 12:16:30 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:30 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:30 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 2/8] fsck_tree(): wrap some long lines Message-ID: <20201005121630.GB2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Many calls to report() in fsck_tree() are kept on a single line and are quite long. Most were pretty big to begin with, but have gotten even longer over the years as we've added more parameters. Let's accept the churn of wrapping them in order to conform to our usual line limits. Signed-off-by: Jeff King --- fsck.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/fsck.c b/fsck.c index 46a108839f..024810139b 100644 --- a/fsck.c +++ b/fsck.c @@ -654,7 +654,9 @@ static int fsck_tree(const struct object_id *tree_oid, struct name_stack df_dup_candidates = { NULL }; if (init_tree_desc_gently(&desc, buffer, size)) { - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_BAD_TREE, + "cannot be parsed as a tree"); return retval; } @@ -703,7 +705,9 @@ static int fsck_tree(const struct object_id *tree_oid, } if (update_tree_entry_gently(&desc)) { - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_TREE, "cannot be parsed as a tree"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_BAD_TREE, + "cannot be parsed as a tree"); break; } @@ -751,25 +755,45 @@ static int fsck_tree(const struct object_id *tree_oid, name_stack_clear(&df_dup_candidates); if (has_null_sha1) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_NULL_SHA1, "contains entries pointing to null sha1"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_NULL_SHA1, + "contains entries pointing to null sha1"); if (has_full_path) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_FULL_PATHNAME, "contains full pathnames"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_FULL_PATHNAME, + "contains full pathnames"); if (has_empty_name) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_EMPTY_NAME, "contains empty pathname"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_EMPTY_NAME, + "contains empty pathname"); if (has_dot) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOT, "contains '.'"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_HAS_DOT, + "contains '.'"); if (has_dotdot) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOTDOT, "contains '..'"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_HAS_DOTDOT, + "contains '..'"); if (has_dotgit) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_HAS_DOTGIT, "contains '.git'"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_HAS_DOTGIT, + "contains '.git'"); if (has_zero_pad) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_ZERO_PADDED_FILEMODE, "contains zero-padded file modes"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_ZERO_PADDED_FILEMODE, + "contains zero-padded file modes"); if (has_bad_modes) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_BAD_FILEMODE, "contains bad file modes"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_BAD_FILEMODE, + "contains bad file modes"); if (has_dup_entries) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_DUPLICATE_ENTRIES, "contains duplicate file entries"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_DUPLICATE_ENTRIES, + "contains duplicate file entries"); if (not_properly_sorted) - retval += report(options, tree_oid, OBJ_TREE, FSCK_MSG_TREE_NOT_SORTED, "not properly sorted"); + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_TREE_NOT_SORTED, + "not properly sorted"); return retval; } From patchwork Mon Oct 5 12:16:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816539 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 76713618 for ; Mon, 5 Oct 2020 12:16:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5CBB22078D for ; Mon, 5 Oct 2020 12:16:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726645AbgJEMQk (ORCPT ); Mon, 5 Oct 2020 08:16:40 -0400 Received: from cloud.peff.net ([104.130.231.41]:49582 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725994AbgJEMQg (ORCPT ); Mon, 5 Oct 2020 08:16:36 -0400 Received: (qmail 32242 invoked by uid 109); 5 Oct 2020 12:16:35 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:35 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19030 invoked by uid 111); 5 Oct 2020 12:16:34 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:34 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:34 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 3/8] t7415: rename to expand scope Message-ID: <20201005121634.GC2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org This script has already expanded beyond its original intent of ".. in submodule names" to include other malicious submodule bits. Let's update the name and description to reflect that, as well as the fact that we'll soon be adding similar tests for other meta-files (.gitattributes, etc). We'll also renumber it to move it out of the group of submodule-specific tests. Signed-off-by: Jeff King --- ...ubmodule-names.sh => t7450-bad-dotgitx-files.sh} | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) rename t/{t7415-submodule-names.sh => t7450-bad-dotgitx-files.sh} (95%) diff --git a/t/t7415-submodule-names.sh b/t/t7450-bad-dotgitx-files.sh similarity index 95% rename from t/t7415-submodule-names.sh rename to t/t7450-bad-dotgitx-files.sh index d1781ef10c..fb28539948 100755 --- a/t/t7415-submodule-names.sh +++ b/t/t7450-bad-dotgitx-files.sh @@ -1,9 +1,16 @@ #!/bin/sh -test_description='check handling of .. in submodule names +test_description='check forbidden or malicious patterns in .git* files -Exercise the name-checking function on a variety of names, and then give a -real-world setup that confirms we catch this in practice. +Such as: + + - presence of .. in submodule names; + Exercise the name-checking function on a variety of names, and then give a + real-world setup that confirms we catch this in practice. + + - nested submodule names + + - symlinked .gitmodules, etc ' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh From patchwork Mon Oct 5 12:16:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816543 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EEAFE1752 for ; Mon, 5 Oct 2020 12:16:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DCBE420848 for ; Mon, 5 Oct 2020 12:16:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726636AbgJEMQk (ORCPT ); Mon, 5 Oct 2020 08:16:40 -0400 Received: from cloud.peff.net ([104.130.231.41]:49584 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726623AbgJEMQi (ORCPT ); Mon, 5 Oct 2020 08:16:38 -0400 Received: (qmail 32247 invoked by uid 109); 5 Oct 2020 12:16:38 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:38 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19045 invoked by uid 111); 5 Oct 2020 12:16:37 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:37 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:37 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 4/8] t7450: test verify_path() handling of gitmodules Message-ID: <20201005121637.GD2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org Commit 10ecfa7649 (verify_path: disallow symlinks in .gitmodules, 2018-05-04) made it impossible to load a symlink .gitmodules file into the index. However, there are no tests of this behavior. Let's make sure this case is covered. We can easily reuse the test setup created by the matching b7b1fca175 (fsck: complain when .gitmodules is a symlink, 2018-05-04). Signed-off-by: Jeff King --- t/t7450-bad-dotgitx-files.sh | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/t/t7450-bad-dotgitx-files.sh b/t/t7450-bad-dotgitx-files.sh index fb28539948..8bfd32b10a 100755 --- a/t/t7450-bad-dotgitx-files.sh +++ b/t/t7450-bad-dotgitx-files.sh @@ -139,7 +139,7 @@ test_expect_success 'index-pack --strict works for non-repo pack' ' grep gitmodulesName output ' -test_expect_success 'fsck detects symlinked .gitmodules file' ' +test_expect_success 'set up repo with symlinked .gitmodules file' ' git init symlink && ( cd symlink && @@ -155,8 +155,14 @@ test_expect_success 'fsck detects symlinked .gitmodules file' ' { printf "100644 blob $content\t$tricky\n" && printf "120000 blob $target\t.gitmodules\n" - } >bad-tree && - tree=$(git mktree bad-tree + ) && + tree=$(git -C symlink mktree err && + test_i18ngrep "invalid path.*gitmodules" err && + git -C symlink ls-files >out && + test_must_be_empty out +' + test_expect_success 'fsck detects non-blob .gitmodules' ' git init non-blob && ( From patchwork Mon Oct 5 12:16:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816545 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id EF997618 for ; Mon, 5 Oct 2020 12:16:43 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DC1DD20848 for ; Mon, 5 Oct 2020 12:16:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726657AbgJEMQm (ORCPT ); Mon, 5 Oct 2020 08:16:42 -0400 Received: from cloud.peff.net ([104.130.231.41]:49588 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725994AbgJEMQl (ORCPT ); Mon, 5 Oct 2020 08:16:41 -0400 Received: (qmail 32253 invoked by uid 109); 5 Oct 2020 12:16:40 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:40 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19049 invoked by uid 111); 5 Oct 2020 12:16:40 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:40 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:39 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 5/8] t7450: test .gitmodules symlink matching against obscured names Message-ID: <20201005121639.GE2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In t7450 we check that both verify_path() and fsck catch malformed .gitmodules entries in trees. However, we don't check that we catch filesystem-equivalent forms of these (e.g., ".GITMOD~1" on Windows). Our name-matching functions are exercised well in t0060, but there's nothing to test that we correctly call the matching functions from the actual fsck and verify_path() code. So instead of testing just .gitmodules, let's repeat our tests for a few basic cases. We don't need to be exhaustive here (t0060 handles that), but just make sure we hit one name of each type. Besides pushing the tests into a function that takes the path as a parameter, we'll need to do a few things: - adjust the directory name to accommodate the tests running multiple times - set core.protecthfs for index checks. Fsck always protects all types by default, but we want to be able to exercise the HFS routines on every system. Note that core.protectntfs is already the default these days, but it doesn't hurt to explicitly label our need for it. - we'll also take the filename ("gitmodules") as a parameter. All calls use the same name for now, but a future patch will extend this to handle other .gitfoo files. Note that our fake-content symlink destination is somewhat .gitmodules specific. But it isn't necessary for other files (which don't do a content check). And it happens to be a valid attribute and ignore file anyway. Signed-off-by: Jeff King --- t/t7450-bad-dotgitx-files.sh | 91 +++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/t/t7450-bad-dotgitx-files.sh b/t/t7450-bad-dotgitx-files.sh index 8bfd32b10a..0cd0f71c39 100755 --- a/t/t7450-bad-dotgitx-files.sh +++ b/t/t7450-bad-dotgitx-files.sh @@ -139,44 +139,59 @@ test_expect_success 'index-pack --strict works for non-repo pack' ' grep gitmodulesName output ' -test_expect_success 'set up repo with symlinked .gitmodules file' ' - git init symlink && - ( - cd symlink && - - # Make the tree directly to avoid index restrictions. - # - # Because symlinks store the target as a blob, choose - # a pathname that could be parsed as a .gitmodules file - # to trick naive non-symlink-aware checking. - tricky="[foo]bar=true" && - content=$(git hash-object -w ../.gitmodules) && - target=$(printf "$tricky" | git hash-object -w --stdin) && - { - printf "100644 blob $content\t$tricky\n" && - printf "120000 blob $target\t.gitmodules\n" - } >bad-tree - ) && - tree=$(git -C symlink mktree output && - test_i18ngrep "tree $tree: gitmodulesSymlink" output - ) -' - -test_expect_success 'refuse to load symlinked .gitmodules into index' ' - test_must_fail git -C symlink read-tree $tree 2>err && - test_i18ngrep "invalid path.*gitmodules" err && - git -C symlink ls-files >out && - test_must_be_empty out -' +check_forbidden_symlink () { + name=$1 + type=$2 + path=$3 + dir=symlink-$name-$type + + test_expect_success "set up repo with symlinked $name ($type)" ' + git init $dir && + ( + cd $dir && + + # Make the tree directly to avoid index restrictions. + # + # Because symlinks store the target as a blob, choose + # a pathname that could be parsed as a .gitmodules file + # to trick naive non-symlink-aware checking. + tricky="[foo]bar=true" && + content=$(git hash-object -w ../.gitmodules) && + target=$(printf "$tricky" | git hash-object -w --stdin) && + { + printf "100644 blob $content\t$tricky\n" && + printf "120000 blob $target\t$path\n" + } >bad-tree + ) && + tree=$(git -C $dir mktree <$dir/bad-tree) + ' + + test_expect_success "fsck detects symlinked $name ($type)" ' + ( + cd $dir && + + # Check not only that we fail, but that it is due to the + # symlink detector + test_must_fail git fsck 2>output && + test_i18ngrep "tree $tree: ${name}Symlink" output + ) + ' + + test_expect_success "refuse to load symlinked $name into index ($type)" ' + test_must_fail \ + git -C $dir \ + -c core.protectntfs \ + -c core.protecthfs \ + read-tree $tree 2>err && + test_i18ngrep "invalid path.*$name" err && + git -C $dir ls-files -s >out && + test_must_be_empty out + ' +} + +check_forbidden_symlink gitmodules vanilla .gitmodules +check_forbidden_symlink gitmodules ntfs ".gitmodules ." +check_forbidden_symlink gitmodules hfs ".${u200c}gitmodules" test_expect_success 'fsck detects non-blob .gitmodules' ' git init non-blob && From patchwork Mon Oct 5 12:16:43 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816553 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 266EC112E for ; Mon, 5 Oct 2020 12:16:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 14E4E208B6 for ; Mon, 5 Oct 2020 12:16:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726720AbgJEMQs (ORCPT ); Mon, 5 Oct 2020 08:16:48 -0400 Received: from cloud.peff.net ([104.130.231.41]:49592 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726665AbgJEMQo (ORCPT ); Mon, 5 Oct 2020 08:16:44 -0400 Received: (qmail 32259 invoked by uid 109); 5 Oct 2020 12:16:44 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:44 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19053 invoked by uid 111); 5 Oct 2020 12:16:43 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:43 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:43 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 6/8] t0060: test obscured .gitattributes and .gitignore matching Message-ID: <20201005121643.GF2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org We have tests that cover various filesystem-specific spellings of ".gitmodules", because we need to reliably identify that path for some security checks. These are from dc2d9ba318 (is_{hfs,ntfs}_dotgitmodules: add tests, 2018-05-12), with the actual code coming from e7cb0b4455 (is_ntfs_dotgit: match other .git files, 2018-05-11) and 0fc333ba20 (is_hfs_dotgit: match other .git files, 2018-05-02). Those latter two commits also added similar matching functions for .gitattributes and .gitignore. These ended up not being used in the final series, and are currently dead code. But in preparation for them being used, let's make sure they actually work by throwing a few basic checks at them. I didn't bother with the whole battery of tests that we cover for .gitmodules. These functions are all based on the same generic matcher, so it's sufficient to test most of the corner cases just once. Note that the ntfs magic prefix names in the tests come from the algorithm described in e7cb0b4455 (and are different for each file). Signed-off-by: Jeff King --- t/helper/test-path-utils.c | 41 ++++++++++++++++++++++++++------------ t/t0060-path-utils.sh | 20 +++++++++++++++++++ 2 files changed, 48 insertions(+), 13 deletions(-) diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index 313a153209..732372b97f 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -172,9 +172,22 @@ static struct test_data dirname_data[] = { { NULL, NULL } }; -static int is_dotgitmodules(const char *path) +static int check_dotgitx(const char *x, const char **argv, + int (*is_hfs)(const char *), + int (*is_ntfs)(const char *)) { - return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path); + int res = 0, expect = 1; + for (; *argv; argv++) { + if (!strcmp("--not", *argv)) + expect = !expect; + else if (expect != (is_hfs(*argv) || is_ntfs(*argv))) + res = error("'%s' is %s.git%s", *argv, + expect ? "not " : "", x); + else + fprintf(stderr, "ok: '%s' is %s.git%s\n", + *argv, expect ? "" : "not ", x); + } + return !!res; } static int cmp_by_st_size(const void *a, const void *b) @@ -382,17 +395,19 @@ int cmd__path_utils(int argc, const char **argv) return test_function(dirname_data, posix_dirname, argv[1]); if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) { - int res = 0, expect = 1, i; - for (i = 2; i < argc; i++) - if (!strcmp("--not", argv[i])) - expect = !expect; - else if (expect != is_dotgitmodules(argv[i])) - res = error("'%s' is %s.gitmodules", argv[i], - expect ? "not " : ""); - else - fprintf(stderr, "ok: '%s' is %s.gitmodules\n", - argv[i], expect ? "" : "not "); - return !!res; + return check_dotgitx("modules", argv + 2, + is_hfs_dotgitmodules, + is_ntfs_dotgitmodules); + } + if (argc > 2 && !strcmp(argv[1], "is_dotgitignore")) { + return check_dotgitx("ignore", argv + 2, + is_hfs_dotgitignore, + is_ntfs_dotgitignore); + } + if (argc > 2 && !strcmp(argv[1], "is_dotgitattributes")) { + return check_dotgitx("attributes", argv + 2, + is_hfs_dotgitattributes, + is_ntfs_dotgitattributes); } if (argc > 2 && !strcmp(argv[1], "file-size")) { diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 56db5c8aba..b2e3cf3f4c 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -468,6 +468,26 @@ test_expect_success 'match .gitmodules' ' .gitmodules,:\$DATA ' +test_expect_success 'match .gitattributes' ' + test-tool path-utils is_dotgitattributes \ + .gitattributes \ + .git${u200c}attributes \ + .Gitattributes \ + .gitattributeS \ + GITATT~1 \ + GI7D29~1 +' + +test_expect_success 'match .gitignore' ' + test-tool path-utils is_dotgitignore \ + .gitignore \ + .git${u200c}ignore \ + .Gitignore \ + .gitignorE \ + GITIGN~1 \ + GI250A~1 +' + test_expect_success MINGW 'is_valid_path() on Windows' ' test-tool path-utils is_valid_path \ win32 \ From patchwork Mon Oct 5 12:16:45 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816549 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 95265618 for ; Mon, 5 Oct 2020 12:16:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 84A0520774 for ; Mon, 5 Oct 2020 12:16:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726680AbgJEMQr (ORCPT ); Mon, 5 Oct 2020 08:16:47 -0400 Received: from cloud.peff.net ([104.130.231.41]:49598 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726000AbgJEMQr (ORCPT ); Mon, 5 Oct 2020 08:16:47 -0400 Received: (qmail 32267 invoked by uid 109); 5 Oct 2020 12:16:46 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:46 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19057 invoked by uid 111); 5 Oct 2020 12:16:45 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:45 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:45 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 7/8] verify_path(): disallow symlinks in .gitattributes and .gitignore Message-ID: <20201005121645.GG2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org In commit 10ecfa7649 (verify_path: disallow symlinks in .gitmodules, 2018-05-04) we made it impossible to load a .gitmodules file that's a symlink into the index. The security reasons for doing so are described there. We also discussed forbidding symlinks of other .git files as part of that fix, but the tradeoff was less compelling: 1. Unlike .gitmodules, the other files don't have content-level fsck checks. So an attacker using symlinks to evade those checks isn't a problem. 2. Unlike .gitmodules, Git will never write .gitignore or .gitattributes itself, making it much less likely to use them to write outside the repo. They could be used for out-of-repo reads, however. 3. The .gitmodules change was part of a critical bug-fix that was not publicly disclosed until it was released. Changing the other files was not needed for the minimal fix. However, it's still a reasonable idea to forbid symlinks for these files: - As noted, they can still be used to read out-of-repo files (which is fairly restricted, but in some circumstances you can probe file content by speculatively creating files and seeing if they get ignored) - They don't currently behave well in all cases. We sometimes read these files from the index, where we _don't_ follow symlinks (we'd just treat the symlink target as the .gitignore or .gitattributes content, which is actively wrong). This patch forbids symlinked versions of these files from entering the index. We already have helpers for obscured forms of the names from e7cb0b4455 (is_ntfs_dotgit: match other .git files, 2018-05-11) and 0fc333ba20 (is_hfs_dotgit: match other .git files, 2018-05-02), which were done as part of the series touching .gitmodules. No tests yet, as we'll add them in a subsequent patch once we have fsck support, too. Signed-off-by: Jeff King --- read-cache.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/read-cache.c b/read-cache.c index ecf6f68994..63aec6c35d 100644 --- a/read-cache.c +++ b/read-cache.c @@ -947,7 +947,9 @@ static int verify_dotfile(const char *rest, unsigned mode) return 0; if (S_ISLNK(mode)) { rest += 3; - if (skip_iprefix(rest, "modules", &rest) && + if ((skip_iprefix(rest, "modules", &rest) || + skip_iprefix(rest, "ignore", &rest) || + skip_iprefix(rest, "attributes", &rest)) && (*rest == '\0' || is_dir_sep(*rest))) return 0; } @@ -980,7 +982,9 @@ int verify_path(const char *path, unsigned mode) if (is_hfs_dotgit(path)) return 0; if (S_ISLNK(mode)) { - if (is_hfs_dotgitmodules(path)) + if (is_hfs_dotgitmodules(path) || + is_hfs_dotgitignore(path) || + is_hfs_dotgitattributes(path)) return 0; } } @@ -992,7 +996,9 @@ int verify_path(const char *path, unsigned mode) if (is_ntfs_dotgit(path)) return 0; if (S_ISLNK(mode)) { - if (is_ntfs_dotgitmodules(path)) + if (is_ntfs_dotgitmodules(path) || + is_ntfs_dotgitignore(path) || + is_ntfs_dotgitattributes(path)) return 0; } } From patchwork Mon Oct 5 12:16:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff King X-Patchwork-Id: 11816557 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E0FDE618 for ; Mon, 5 Oct 2020 12:17:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CA4E02085B for ; Mon, 5 Oct 2020 12:17:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726329AbgJEMQ6 (ORCPT ); Mon, 5 Oct 2020 08:16:58 -0400 Received: from cloud.peff.net ([104.130.231.41]:49616 "EHLO cloud.peff.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726648AbgJEMQu (ORCPT ); Mon, 5 Oct 2020 08:16:50 -0400 Received: (qmail 32279 invoked by uid 109); 5 Oct 2020 12:16:49 -0000 Received: from Unknown (HELO peff.net) (10.0.1.2) by cloud.peff.net (qpsmtpd/0.94) with ESMTP; Mon, 05 Oct 2020 12:16:49 +0000 Authentication-Results: cloud.peff.net; auth=none Received: (qmail 19089 invoked by uid 111); 5 Oct 2020 12:16:48 -0000 Received: from coredump.intra.peff.net (HELO sigill.intra.peff.net) (10.0.0.2) by peff.net (qpsmtpd/0.94) with (TLS_AES_256_GCM_SHA384 encrypted) ESMTPS; Mon, 05 Oct 2020 08:16:48 -0400 Authentication-Results: peff.net; auth=none Date: Mon, 5 Oct 2020 08:16:48 -0400 From: Jeff King To: git@vger.kernel.org Cc: Jonathan Nieder Subject: [PATCH v2 8/8] fsck: complain when .gitattributes or .gitignore is a symlink Message-ID: <20201005121648.GH2907394@coredump.intra.peff.net> References: <20201005121609.GA2907272@coredump.intra.peff.net> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20201005121609.GA2907272@coredump.intra.peff.net> Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The previous commit made it impossible to have a symlinked .gitattributes or .gitignore file via verify_path(). Let's add the same check to fsck, which matches how we handle .gitmodules symlinks, via b7b1fca175 (fsck: complain when .gitmodules is a symlink, 2018-05-04). Note that we won't add these to the existing gitmodules block. The logic for gitmodules is a bit more complicated, as we also check the content of non-symlink instances we find. But for these new files, there is no content check; we're just looking at the name and mode of the tree entry (and we can avoid even the complicated name checks in the common case that the mode doesn't indicate a symlink). We can reuse the test helper function we defined for .gitmodules, though (and this covers the verify_path() change from the previous commit, as well). Signed-off-by: Jeff King --- fsck.c | 15 +++++++++++++++ t/t7450-bad-dotgitx-files.sh | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/fsck.c b/fsck.c index 024810139b..fcd3f268b1 100644 --- a/fsck.c +++ b/fsck.c @@ -67,6 +67,8 @@ static struct oidset gitmodules_done = OIDSET_INIT; FUNC(GITMODULES_URL, ERROR) \ FUNC(GITMODULES_PATH, ERROR) \ FUNC(GITMODULES_UPDATE, ERROR) \ + FUNC(GITIGNORE_SYMLINK, ERROR) \ + FUNC(GITATTRIBUTES_SYMLINK, ERROR) \ /* warnings */ \ FUNC(BAD_FILEMODE, WARN) \ FUNC(EMPTY_NAME, WARN) \ @@ -688,6 +690,19 @@ static int fsck_tree(const struct object_id *tree_oid, ".gitmodules is a symbolic link"); } + if (S_ISLNK(mode)) { + if (is_hfs_dotgitignore(name) || + is_ntfs_dotgitignore(name)) + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_GITIGNORE_SYMLINK, + ".gitignore is a symlink"); + if (is_hfs_dotgitattributes(name) || + is_ntfs_dotgitattributes(name)) + retval += report(options, tree_oid, OBJ_TREE, + FSCK_MSG_GITATTRIBUTES_SYMLINK, + ".gitattributes is a symlink"); + } + if ((backslash = strchr(name, '\\'))) { while (backslash) { backslash++; diff --git a/t/t7450-bad-dotgitx-files.sh b/t/t7450-bad-dotgitx-files.sh index 0cd0f71c39..326b34e167 100755 --- a/t/t7450-bad-dotgitx-files.sh +++ b/t/t7450-bad-dotgitx-files.sh @@ -193,6 +193,14 @@ check_forbidden_symlink gitmodules vanilla .gitmodules check_forbidden_symlink gitmodules ntfs ".gitmodules ." check_forbidden_symlink gitmodules hfs ".${u200c}gitmodules" +check_forbidden_symlink gitattributes vanilla .gitattributes +check_forbidden_symlink gitattributes ntfs ".gitattributes ." +check_forbidden_symlink gitattributes hfs ".${u200c}gitattributes" + +check_forbidden_symlink gitignore vanilla .gitignore +check_forbidden_symlink gitignore ntfs ".gitignore ." +check_forbidden_symlink gitignore hfs ".${u200c}gitignore" + test_expect_success 'fsck detects non-blob .gitmodules' ' git init non-blob && (