fast-import: disallow more path components
Instead of just disallowing '.' and '..', make use of verify_path() to ensure that fast-import will disallow anything we wouldn't allow into the index, such as anything under .git/, .gitmodules as a symlink, or a dos drive prefix on Windows. Since a few fast-export and fast-import tests that tried to stress-test the correct handling of quoting relied on filenames that fail is_valid_win32_path(), such as spaces or periods at the end of filenames or backslashes within the filename, turn off core.protectNTFS for those tests to ensure they keep passing. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Nov 30, 2024 at 01:09 UTC
da91a90c2f42f4b4e1fffa916a51e0e7ecb86ed9
3 files changed
+91
-7
builtin/fast-import.c
+6
-2
@@ -13,6 +13,7 @@
13
#include "delta.h"
14
#include "pack.h"
15
#include "path.h"
16
+#include "read-cache-ll.h"
17
#include "refs.h"
18
#include "csum-file.h"
19
#include "quote.h"
@@ -1468,8 +1469,6 @@ static int tree_content_set(
1469
root->tree = t = grow_tree_content(t, t->entry_count);
1470
e = new_tree_entry();
1471
e->name = to_atom(p, n);
1471
- if (is_dot_or_dotdot(e->name->str_dat))
1472
- die("path %s contains invalid component", p);
1472
e->versions[0].mode = 0;
1473
oidclr(&e->versions[0].oid, the_repository->hash_algo);
1474
t->entries[t->entry_count++] = e;
@@ -2416,6 +2415,9 @@ static void file_change_m(const char *p, struct branch *b)
2415
tree_content_replace(&b->branch_tree, &oid, mode, NULL);
2416
return;
2417
}
2418
+
2419
+ if (!verify_path(path.buf, mode))
2420
+ die("invalid path '%s'", path.buf);
2421
tree_content_set(&b->branch_tree, path.buf, &oid, mode, NULL);
2422
}
2423
@@ -2453,6 +2455,8 @@ static void file_change_cr(const char *p, struct branch *b, int rename)
2455
leaf.tree);
2456
return;
2457
}
2458
+ if (!verify_path(dest.buf, leaf.versions[1].mode))
2459
+ die("invalid path '%s'", dest.buf);
2460
tree_content_set(&b->branch_tree, dest.buf,
2461
&leaf.versions[1].oid,
2462
leaf.versions[1].mode,
t/t9300-fast-import.sh
+84
-4
@@ -522,7 +522,7 @@ test_expect_success 'B: fail on invalid committer (5)' '
522
test_must_fail git fast-import <input
523
'
524
525
-test_expect_success 'B: fail on invalid file path' '
525
+test_expect_success 'B: fail on invalid file path of ..' '
526
cat >input <<-INPUT_END &&
527
blob
528
mark :1
@@ -542,6 +542,86 @@ test_expect_success 'B: fail on invalid file path' '
542
test_must_fail git fast-import <input
543
'
544
545
+test_expect_success 'B: fail on invalid file path of .' '
546
+ cat >input <<-INPUT_END &&
547
+ blob
548
+ mark :1
549
+ data <<EOF
550
+ File contents
551
+ EOF
552
+
553
+ commit refs/heads/badpath
554
+ committer Name <email> $GIT_COMMITTER_DATE
555
+ data <<COMMIT
556
+ Commit Message
557
+ COMMIT
558
+ M 100644 :1 ./invalid-path
559
+ INPUT_END
560
+
561
+ test_when_finished "git update-ref -d refs/heads/badpath" &&
562
+ test_must_fail git fast-import <input
563
+'
564
+
565
+test_expect_success WINDOWS 'B: fail on invalid file path of C:' '
566
+ cat >input <<-INPUT_END &&
567
+ blob
568
+ mark :1
569
+ data <<EOF
570
+ File contents
571
+ EOF
572
+
573
+ commit refs/heads/badpath
574
+ committer Name <email> $GIT_COMMITTER_DATE
575
+ data <<COMMIT
576
+ Commit Message
577
+ COMMIT
578
+ M 100644 :1 C:/invalid-path
579
+ INPUT_END
580
+
581
+ test_when_finished "git update-ref -d refs/heads/badpath" &&
582
+ test_must_fail git fast-import <input
583
+'
584
+
585
+test_expect_success 'B: fail on invalid file path of .git' '
586
+ cat >input <<-INPUT_END &&
587
+ blob
588
+ mark :1
589
+ data <<EOF
590
+ File contents
591
+ EOF
592
+
593
+ commit refs/heads/badpath
594
+ committer Name <email> $GIT_COMMITTER_DATE
595
+ data <<COMMIT
596
+ Commit Message
597
+ COMMIT
598
+ M 100644 :1 .git/invalid-path
599
+ INPUT_END
600
+
601
+ test_when_finished "git update-ref -d refs/heads/badpath" &&
602
+ test_must_fail git fast-import <input
603
+'
604
+
605
+test_expect_success 'B: fail on invalid file path of .gitmodules' '
606
+ cat >input <<-INPUT_END &&
607
+ blob
608
+ mark :1
609
+ data <<EOF
610
+ File contents
611
+ EOF
612
+
613
+ commit refs/heads/badpath
614
+ committer Name <email> $GIT_COMMITTER_DATE
615
+ data <<COMMIT
616
+ Commit Message
617
+ COMMIT
618
+ M 120000 :1 .gitmodules
619
+ INPUT_END
620
+
621
+ test_when_finished "git update-ref -d refs/heads/badpath" &&
622
+ test_must_fail git fast-import <input
623
+'
624
+
625
###
626
### series C
627
###
@@ -966,7 +1046,7 @@ test_expect_success 'L: verify internal tree sorting' '
1046
:100644 100644 M ba
1047
EXPECT_END
1048
969
- git fast-import <input &&
1049
+ git -c core.protectNTFS=false fast-import <input &&
1050
GIT_PRINT_SHA1_ELLIPSIS="yes" git diff-tree --abbrev --raw L^ L >output &&
1051
cut -d" " -f1,2,5 output >actual &&
1052
test_cmp expect actual
@@ -3117,7 +3197,7 @@ test_path_eol_success () {
3197
test_expect_success "S: paths at EOL with $test must work" '
3198
test_when_finished "git branch -D S-path-eol" &&
3199
3120
- git fast-import --export-marks=marks.out <<-EOF >out 2>err &&
3200
+ git -c core.protectNTFS=false fast-import --export-marks=marks.out <<-EOF >out 2>err &&
3201
blob
3202
mark :401
3203
data <<BLOB
@@ -3226,7 +3306,7 @@ test_path_space_success () {
3306
test_expect_success "S: paths before space with $test must work" '
3307
test_when_finished "git branch -D S-path-space" &&
3308
3229
- git fast-import --export-marks=marks.out <<-EOF 2>err &&
3309
+ git -c core.protectNTFS=false fast-import --export-marks=marks.out <<-EOF 2>err &&
3310
blob
3311
mark :401
3312
data <<BLOB
t/t9350-fast-export.sh
+1
-1
@@ -631,7 +631,7 @@ test_expect_success 'fast-export quotes pathnames' '
631
git rev-list HEAD >expect &&
632
git init result &&
633
cd result &&
634
- git fast-import <../export.out &&
634
+ git -c core.protectNTFS=false fast-import <../export.out &&
635
git rev-list HEAD >actual &&
636
test_cmp ../expect actual
637
)