Skip to content

Commit 2d88ab0

Browse files
hanyang-tonygitster
authored andcommitted
diffcore-break: avoid segfault with freed entries
After we have freed the file pair, we should set the queue reference to null. When computing a diff in a partial clone, there is a chance that we could trigger a prefetch of missing objects when there are freed entries in the global diff queue due to break-rewrites detection. The segfault only occurs if an entry has been freed by break-rewrites and there is an entry to be prefetched. There is a new test in t4067 that trigger the segmentation fault that results in this case. The test explicitly fetch the necessary blobs to trigger the break rewrites, some blobs are left to be prefetched. The fix is to set the queue pointer to NULL after it is freed, the prefetch will skip NULL entries. Signed-off-by: Han Young <hanyang.tony@bytedance.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 67ad421 commit 2d88ab0

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

diffcore-break.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ void diffcore_break(struct repository *r, int break_score)
222222
free(p); /* not diff_free_filepair(), we are
223223
* reusing one and two here.
224224
*/
225+
q->queue[i] = NULL;
225226
continue;
226227
}
227228
}

t/t4067-diff-partial-clone.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,37 @@ test_expect_success 'diff with rename detection batches blobs' '
132132
test_line_count = 1 done_lines
133133
'
134134

135+
test_expect_success 'diff succeeds even if prefetch triggered by break-rewrites' '
136+
test_when_finished "rm -rf server client trace" &&
137+
138+
test_create_repo server &&
139+
echo xyz >server/foo &&
140+
mkdir server/bar &&
141+
test_seq -f "line %d" 1 100 >server/bar/baz &&
142+
git -C server add -A &&
143+
git -C server commit -m x &&
144+
145+
echo xyzz >server/foo &&
146+
test_seq -f "line %d" 90 190 >server/bar/baz &&
147+
git -C server add -A &&
148+
git -C server commit -m x &&
149+
150+
test_config -C server uploadpack.allowfilter 1 &&
151+
test_config -C server uploadpack.allowanysha1inwant 1 &&
152+
git clone --filter=blob:limit=0 "file://$(pwd)/server" client &&
153+
154+
# Fetch bar/baz without fetching foo.
155+
# Foo will be lazily fetched during break rewrites detection.
156+
git -C client checkout HEAD~1 bar &&
157+
158+
# Ensure baz in the working tree is different from baz in HEAD~1.
159+
# We need baz to trigger break-rewrites detection.
160+
git -C client reset --hard HEAD &&
161+
162+
# break-rewrites detction in reset.
163+
git -C client reset HEAD~1
164+
'
165+
135166
test_expect_success 'diff succeeds even if entries are removed from queue' '
136167
test_when_finished "rm -rf server client trace" &&
137168

0 commit comments

Comments
 (0)