From: Junio C Hamano Date: Wed, 21 Nov 2018 13:57:44 +0000 (+0900) Subject: Merge branch 'en/rerere-multi-stage-1-fix' into maint X-Git-Tag: v2.19.2~60 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/b4eafbcdb84fc406bff37f06fdf6310aca7d0249?hp=-c Merge branch 'en/rerere-multi-stage-1-fix' into maint A corner case bugfix in "git rerere" code. * en/rerere-multi-stage-1-fix: rerere: avoid buffer overrun t4200: demonstrate rerere segfault on specially crafted merge --- b4eafbcdb84fc406bff37f06fdf6310aca7d0249 diff --combined rerere.c index c7787aa07f,ee02dd3244..783d4dae2a --- a/rerere.c +++ b/rerere.c @@@ -9,7 -9,6 +9,7 @@@ #include "ll-merge.h" #include "attr.h" #include "pathspec.h" +#include "object-store.h" #include "sha1-lookup.h" #define RESOLVED 0 @@@ -201,7 -200,7 +201,7 @@@ static struct rerere_id *new_rerere_id( static void read_rr(struct string_list *rr) { struct strbuf buf = STRBUF_INIT; - FILE *in = fopen_or_warn(git_path_merge_rr(), "r"); + FILE *in = fopen_or_warn(git_path_merge_rr(the_repository), "r"); if (!in) return; @@@ -533,7 -532,7 +533,7 @@@ static int check_one_conflict(int i, in } *type = PUNTED; - while (ce_stage(active_cache[i]) == 1) + while (i < active_nr && ce_stage(active_cache[i]) == 1) i++; /* Only handle regular files with both stages #2 and #3 */ @@@ -704,9 -703,10 +704,9 @@@ out return ret; } -static struct lock_file index_lock; - static void update_paths(struct string_list *update) { + struct lock_file index_lock = LOCK_INIT; int i; hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); @@@ -896,8 -896,7 +896,8 @@@ int setup_rerere(struct string_list *me if (flags & RERERE_READONLY) fd = 0; else - fd = hold_lock_file_for_update(&write_lock, git_path_merge_rr(), + fd = hold_lock_file_for_update(&write_lock, + git_path_merge_rr(the_repository), LOCK_DIE_ON_ERROR); read_rr(merge_rr); return fd; @@@ -980,8 -979,8 +980,8 @@@ static int handle_cache(const char *pat break; i = ce_stage(ce) - 1; if (!mmfile[i].ptr) { - mmfile[i].ptr = read_sha1_file(ce->oid.hash, &type, - &size); + mmfile[i].ptr = read_object_file(&ce->oid, &type, + &size); mmfile[i].size = size; } } @@@ -1120,7 -1119,7 +1120,7 @@@ int rerere_forget(struct pathspec *path find_conflict(&conflict); for (i = 0; i < conflict.nr; i++) { struct string_list_item *it = &conflict.items[i]; - if (!match_pathspec(pathspec, it->string, + if (!match_pathspec(&the_index, pathspec, it->string, strlen(it->string), 0, NULL, 0)) continue; rerere_forget_one_path(it->string, &merge_rr); @@@ -1247,6 -1246,6 +1247,6 @@@ void rerere_clear(struct string_list *m rmdir(rerere_path(id, NULL)); } } - unlink_or_warn(git_path_merge_rr()); + unlink_or_warn(git_path_merge_rr(the_repository)); rollback_lock_file(&write_lock); } diff --combined t/t4200-rerere.sh index 65da74c766,8da998f661..313222d0d6 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@@ -166,7 -166,7 +166,7 @@@ test_expect_success 'first postimage wi git commit -q -a -m "prefer first over second" && test -f $rr/postimage && - oldmtimepost=$(test-chmtime -v -60 $rr/postimage | cut -f 1) && + oldmtimepost=$(test-tool chmtime --get -60 $rr/postimage) && git checkout -b third master && git show second^:a1 | sed "s/To die: t/To die! T/" >a1 && @@@ -179,7 -179,7 +179,7 @@@ ' test_expect_success 'rerere updates postimage timestamp' ' - newmtimepost=$(test-chmtime -v +0 $rr/postimage | cut -f 1) && + newmtimepost=$(test-tool chmtime --get $rr/postimage) && test $oldmtimepost -lt $newmtimepost ' @@@ -220,9 -220,9 +220,9 @@@ test_expect_success 'set up for garbag almost_60_days_ago=$((60-60*86400)) && just_over_60_days_ago=$((-1-60*86400)) && - test-chmtime =$just_over_60_days_ago $rr/preimage && - test-chmtime =$almost_60_days_ago $rr/postimage && - test-chmtime =$almost_15_days_ago $rr2/preimage + test-tool chmtime =$just_over_60_days_ago $rr/preimage && + test-tool chmtime =$almost_60_days_ago $rr/postimage && + test-tool chmtime =$almost_15_days_ago $rr2/preimage ' test_expect_success 'gc preserves young or recently used records' ' @@@ -232,8 -232,8 +232,8 @@@ ' test_expect_success 'old records rest in peace' ' - test-chmtime =$just_over_60_days_ago $rr/postimage && - test-chmtime =$just_over_15_days_ago $rr2/preimage && + test-tool chmtime =$just_over_60_days_ago $rr/postimage && + test-tool chmtime =$just_over_15_days_ago $rr2/preimage && git rerere gc && ! test -f $rr/preimage && ! test -f $rr2/preimage @@@ -243,14 -243,14 +243,14 @@@ rerere_gc_custom_expiry_test () five_days="$1" right_now="$2" test_expect_success "rerere gc with custom expiry ($five_days, $right_now)" ' rm -fr .git/rr-cache && - rr=.git/rr-cache/$_z40 && + rr=.git/rr-cache/$ZERO_OID && mkdir -p "$rr" && >"$rr/preimage" && >"$rr/postimage" && two_days_ago=$((-2*86400)) && - test-chmtime =$two_days_ago "$rr/preimage" && - test-chmtime =$two_days_ago "$rr/postimage" && + test-tool chmtime =$two_days_ago "$rr/preimage" && + test-tool chmtime =$two_days_ago "$rr/postimage" && find .git/rr-cache -type f | sort >original && @@@ -267,7 -267,8 +267,7 @@@ git -c "gc.rerereresolved=$right_now" \ -c "gc.rerereunresolved=$right_now" rerere gc && find .git/rr-cache -type f | sort >actual && - >expect && - test_cmp expect actual + test_must_be_empty actual ' } @@@ -511,7 -512,7 +511,7 @@@ test_expect_success 'multiple identica count_pre_post 2 0 && # Pretend that the conflicts were made quite some time ago - find .git/rr-cache/ -type f | xargs test-chmtime -172800 && + test-tool chmtime -172800 $(find .git/rr-cache/ -type f) && # Unresolved entries have not expired yet git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc && @@@ -535,8 -536,9 +535,8 @@@ # We resolved file1 and file2 git rerere && - >expect && git rerere remaining >actual && - test_cmp expect actual && + test_must_be_empty actual && # We must have recorded both of them count_pre_post 2 2 && @@@ -546,8 -548,9 +546,8 @@@ test_must_fail git merge six.1 && git rerere && - >expect && git rerere remaining >actual && - test_cmp expect actual && + test_must_be_empty actual && concat_insert short 6.1 6.2 >file1.expect && concat_insert long 6.1 6.2 >file2.expect && @@@ -565,7 -568,7 +565,7 @@@ git rerere && # Pretend that the resolutions are old again - find .git/rr-cache/ -type f | xargs test-chmtime -172800 && + test-tool chmtime -172800 $(find .git/rr-cache/ -type f) && # Resolved entries have not expired yet git -c gc.rerereresolved=5 -c gc.rerereunresolved=5 rerere gc && @@@ -577,4 -580,33 +577,33 @@@ count_pre_post 0 0 ' + test_expect_success 'setup simple stage 1 handling' ' + test_create_repo stage_1_handling && + ( + cd stage_1_handling && + + test_seq 1 10 >original && + git add original && + git commit -m original && + + git checkout -b A master && + git mv original A && + git commit -m "rename to A" && + + git checkout -b B master && + git mv original B && + git commit -m "rename to B" + ) + ' + + test_expect_success 'test simple stage 1 handling' ' + ( + cd stage_1_handling && + + git config rerere.enabled true && + git checkout A^0 && + test_must_fail git merge B^0 + ) + ' + test_done