t0060: test ntfs/hfs-obscured dotfiles

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 in some fsck checks, let's make sure they actually work by throwing a few basic tests at them. Likewise, let's cover .mailmap (which does need matching code added). 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 <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 3, 2021 at 16:43 UTC 801ed010bf13465bf67608beabbaa1ec2550204f
6 files changed +75 -13
cache.h
+1
@@ -1271,6 +1271,7 @@ int is_ntfs_dotgit(const char *name);
1271 int is_ntfs_dotgitmodules(const char *name);
1272 int is_ntfs_dotgitignore(const char *name);
1273 int is_ntfs_dotgitattributes(const char *name);
1274 +int is_ntfs_dotmailmap(const char *name);
1275
1276 /*
1277 * Returns true iff "str" could be confused as a command-line option when
path.c
+5
@@ -1493,6 +1493,11 @@ int is_ntfs_dotgitattributes(const char *name)
1493 return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
1494 }
1495
1496 +int is_ntfs_dotmailmap(const char *name)
1497 +{
1498 + return is_ntfs_dot_str(name, "mailmap", "maba30");
1499 +}
1500 +
1501 int looks_like_command_line_option(const char *str)
1502 {
1503 return str && str[0] == '-';
t/helper/test-path-utils.c
+33 -13
@@ -172,9 +172,22 @@ static struct test_data dirname_data[] = {
172 { NULL, NULL }
173 };
174
175 -static int is_dotgitmodules(const char *path)
175 +static int check_dotfile(const char *x, const char **argv,
176 + int (*is_hfs)(const char *),
177 + int (*is_ntfs)(const char *))
178 {
177 - return is_hfs_dotgitmodules(path) || is_ntfs_dotgitmodules(path);
179 + int res = 0, expect = 1;
180 + for (; *argv; argv++) {
181 + if (!strcmp("--not", *argv))
182 + expect = !expect;
183 + else if (expect != (is_hfs(*argv) || is_ntfs(*argv)))
184 + res = error("'%s' is %s.git%s", *argv,
185 + expect ? "not " : "", x);
186 + else
187 + fprintf(stderr, "ok: '%s' is %s.git%s\n",
188 + *argv, expect ? "" : "not ", x);
189 + }
190 + return !!res;
191 }
192
193 static int cmp_by_st_size(const void *a, const void *b)
@@ -382,17 +395,24 @@ int cmd__path_utils(int argc, const char **argv)
395 return test_function(dirname_data, posix_dirname, argv[1]);
396
397 if (argc > 2 && !strcmp(argv[1], "is_dotgitmodules")) {
385 - int res = 0, expect = 1, i;
386 - for (i = 2; i < argc; i++)
387 - if (!strcmp("--not", argv[i]))
388 - expect = !expect;
389 - else if (expect != is_dotgitmodules(argv[i]))
390 - res = error("'%s' is %s.gitmodules", argv[i],
391 - expect ? "not " : "");
392 - else
393 - fprintf(stderr, "ok: '%s' is %s.gitmodules\n",
394 - argv[i], expect ? "" : "not ");
395 - return !!res;
398 + return check_dotfile("modules", argv + 2,
399 + is_hfs_dotgitmodules,
400 + is_ntfs_dotgitmodules);
401 + }
402 + if (argc > 2 && !strcmp(argv[1], "is_dotgitignore")) {
403 + return check_dotfile("ignore", argv + 2,
404 + is_hfs_dotgitignore,
405 + is_ntfs_dotgitignore);
406 + }
407 + if (argc > 2 && !strcmp(argv[1], "is_dotgitattributes")) {
408 + return check_dotfile("attributes", argv + 2,
409 + is_hfs_dotgitattributes,
410 + is_ntfs_dotgitattributes);
411 + }
412 + if (argc > 2 && !strcmp(argv[1], "is_dotmailmap")) {
413 + return check_dotfile("mailmap", argv + 2,
414 + is_hfs_dotmailmap,
415 + is_ntfs_dotmailmap);
416 }
417
418 if (argc > 2 && !strcmp(argv[1], "file-size")) {
t/t0060-path-utils.sh
+30
@@ -468,6 +468,36 @@ test_expect_success 'match .gitmodules' '
468 .gitmodules,:\$DATA
469 '
470
471 +test_expect_success 'match .gitattributes' '
472 + test-tool path-utils is_dotgitattributes \
473 + .gitattributes \
474 + .git${u200c}attributes \
475 + .Gitattributes \
476 + .gitattributeS \
477 + GITATT~1 \
478 + GI7D29~1
479 +'
480 +
481 +test_expect_success 'match .gitignore' '
482 + test-tool path-utils is_dotgitignore \
483 + .gitignore \
484 + .git${u200c}ignore \
485 + .Gitignore \
486 + .gitignorE \
487 + GITIGN~1 \
488 + GI250A~1
489 +'
490 +
491 +test_expect_success 'match .mailmap' '
492 + test-tool path-utils is_dotmailmap \
493 + .mailmap \
494 + .mail${u200c}map \
495 + .Mailmap \
496 + .mailmaP \
497 + MAILMA~1 \
498 + MABA30~1
499 +'
500 +
501 test_expect_success MINGW 'is_valid_path() on Windows' '
502 test-tool path-utils is_valid_path \
503 win32 \
utf8.c
+5
@@ -777,6 +777,11 @@ int is_hfs_dotgitattributes(const char *path)
777 return is_hfs_dot_str(path, "gitattributes");
778 }
779
780 +int is_hfs_dotmailmap(const char *path)
781 +{
782 + return is_hfs_dot_str(path, "mailmap");
783 +}
784 +
785 const char utf8_bom[] = "\357\273\277";
786
787 int skip_utf8_bom(char **text, size_t len)
utf8.h
+1
@@ -61,6 +61,7 @@ int is_hfs_dotgit(const char *path);
61 int is_hfs_dotgitmodules(const char *path);
62 int is_hfs_dotgitignore(const char *path);
63 int is_hfs_dotgitattributes(const char *path);
64 +int is_hfs_dotmailmap(const char *path);
65
66 typedef enum {
67 ALIGN_LEFT,