@matheusbsbs / matheus-bagliano / commits / 9abc60f801
Fork 0

sparse-checkout: warn on globs in cone patterns

In cone mode, the sparse-checkout commmand will write patterns that allow faster pattern matching. This matching only works if the patterns in the sparse-checkout file are those written by that command. Users can edit the sparse-checkout file and create patterns that cause the cone mode matching to fail. The cone mode patterns may end in "/*" but otherwise an un-escaped asterisk or other glob character is invalid. Add checks to disable cone mode when seeing these values. A later change will properly handle escaped globs. Signed-off-by: Derrick Stolee <dstolee@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Jan 31, 2020 at 20:16 UTC 9abc60f8015d060d3f3433b105648a4725c97bd1
2 files changed +75
dir.c
+36
@@ -635,6 +635,7 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
635 struct pattern_entry *translated;
636 char *truncated;
637 char *data = NULL;
638 + const char *prev, *cur, *next;
639
640 if (!pl->use_cone_patterns)
641 return;
@@ -652,12 +653,47 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
653 }
654
655 if (given->patternlen <= 2 ||
656 + *given->pattern == '*' ||
657 strstr(given->pattern, "**")) {
658 /* Not a cone pattern. */
659 warning(_("unrecognized pattern: '%s'"), given->pattern);
660 goto clear_hashmaps;
661 }
662
663 + prev = given->pattern;
664 + cur = given->pattern + 1;
665 + next = given->pattern + 2;
666 +
667 + while (*cur) {
668 + /* Watch for glob characters '*', '\', '[', '?' */
669 + if (!is_glob_special(*cur))
670 + goto increment;
671 +
672 + /* But only if *prev != '\\' */
673 + if (*prev == '\\')
674 + goto increment;
675 +
676 + /* But allow the initial '\' */
677 + if (*cur == '\\' &&
678 + is_glob_special(*next))
679 + goto increment;
680 +
681 + /* But a trailing '/' then '*' is fine */
682 + if (*prev == '/' &&
683 + *cur == '*' &&
684 + *next == 0)
685 + goto increment;
686 +
687 + /* Not a cone pattern. */
688 + warning(_("unrecognized pattern: '%s'"), given->pattern);
689 + goto clear_hashmaps;
690 +
691 + increment:
692 + prev++;
693 + cur++;
694 + next++;
695 + }
696 +
697 if (given->patternlen > 2 &&
698 !strcmp(given->pattern + given->patternlen - 2, "/*")) {
699 if (!(given->flags & PATTERN_FLAG_NEGATIVE)) {
t/t1091-sparse-checkout-builtin.sh
+39
@@ -348,4 +348,43 @@ test_expect_success 'pattern-checks: too short' '
348 check_read_tree_errors repo "a" "disabling cone pattern matching"
349 '
350
351 +test_expect_success 'pattern-checks: trailing "*"' '
352 + cat >repo/.git/info/sparse-checkout <<-\EOF &&
353 + /*
354 + !/*/
355 + /a*
356 + EOF
357 + check_read_tree_errors repo "a" "disabling cone pattern matching"
358 +'
359 +
360 +test_expect_success 'pattern-checks: starting "*"' '
361 + cat >repo/.git/info/sparse-checkout <<-\EOF &&
362 + /*
363 + !/*/
364 + *eep/
365 + EOF
366 + check_read_tree_errors repo "a deep" "disabling cone pattern matching"
367 +'
368 +
369 +test_expect_success 'pattern-checks: contained glob characters' '
370 + for c in "[a]" "\\" "?" "*"
371 + do
372 + cat >repo/.git/info/sparse-checkout <<-EOF &&
373 + /*
374 + !/*/
375 + something$c-else/
376 + EOF
377 + check_read_tree_errors repo "a" "disabling cone pattern matching"
378 + done
379 +'
380 +
381 +test_expect_success 'pattern-checks: escaped "*"' '
382 + cat >repo/.git/info/sparse-checkout <<-\EOF &&
383 + /*
384 + !/*/
385 + /does\*not\*exist/
386 + EOF
387 + check_read_tree_errors repo "a" ""
388 +'
389 +
390 test_done