diff options
| author | Junio C Hamano <gitster@pobox.com> | 2026-01-08 16:40:11 +0900 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2026-01-08 16:40:11 +0900 |
| commit | c0754dc42305cb37823955722a5167755634c8c1 (patch) | |
| tree | 4336e1485b15606f6bd05edc18eb988335e1f59a | |
| parent | d28d2be5f2aa6acbd0c86b8fbae68cd222de3f4f (diff) | |
| parent | 56d388e6ad9e819935a902b6d5ce3a6b3485b6e2 (diff) | |
| download | git-c0754dc42305cb37823955722a5167755634c8c1.tar.xz | |
Merge branch 'ds/diff-lazy-fetch-with-name-only-fix'
Running "git diff" with "--name-only" and other options that allows
us not to look at the blob contents, while objects that are lazily
fetched from a promisor remote, caused use-after-free, which has
been corrected.
* ds/diff-lazy-fetch-with-name-only-fix:
diff: avoid segfault with freed entries
| -rw-r--r-- | diff.c | 5 | ||||
| -rwxr-xr-x | t/t4067-diff-partial-clone.sh | 35 |
2 files changed, 40 insertions, 0 deletions
@@ -7098,6 +7098,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) if (!diffopt->flags.no_index) diffopt->skip_stat_unmatch++; diff_free_filepair(p); + q->queue[i] = NULL; } } free(q->queue); @@ -7141,6 +7142,10 @@ void diff_queued_diff_prefetch(void *repository) for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; + + if (!p) + continue; + diff_add_if_missing(repo, &to_fetch, p->one); diff_add_if_missing(repo, &to_fetch, p->two); } diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index 581250dd2d..72f25de449 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -132,6 +132,41 @@ test_expect_success 'diff with rename detection batches blobs' ' test_line_count = 1 done_lines ' +test_expect_success 'diff succeeds even if entries are removed from queue' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + for l in a c e g i p + do + echo $l >server/$l && + git -C server add $l || return 1 + done && + git -C server commit -m x && + + for l in a e i + do + git -C server rm $l || return 1 + done && + + for l in b d f i + do + echo $l$l >server/$l && + git -C server add $l || return 1 + done && + git -C server commit -a -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --filter=blob:limit=0 "file://$(pwd)/server" client && + + for file in $(ls client) + do + cat client/$file >$file && + mv $file client/$file || return 1 + done && + git -C client diff --name-only --relative HEAD^ +' + test_expect_success 'diff does not fetch anything if inexact rename detection is not needed' ' test_when_finished "rm -rf server client trace" && |
