rerere: fix crashes due to unmatched opening conflict markers

When rerere handles a conflict with an unmatched opening conflict marker
in a file with other conflicts, it will fail create a preimage and also
fail allocate the status member of struct rerere_dir. Currently the
status member is allocated after the error handling. This will lead to a
SEGFAULT when the status member is accessed during cleanup of the failed
parse.

Additionally, in subsequent executions of rerere, after removing the
MERGE_RR.lock manually, rerere crashes for a similar reason. MERGE_RR
points to a conflict id that has no preimage, therefore the status
member is not allocated and a SEGFAULT happens when trying to check if a
preimage exists.

Solve this by making sure the status field is allocated correctly and add
tests to prevent the bug from reoccurring.

This does not fix the root cause, failing to parse stray conflict
markers, but I don't think we can do much better than recognizing it,
printing an error, and moving on gracefully.

Signed-off-by: Marcel Röthke <marcel@roethke.info>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Marcel Röthke 2024-04-16 12:52:48 +02:00 committed by Junio C Hamano
parent 9bbde12fee
commit 167395bb47
2 changed files with 68 additions and 0 deletions

View file

@ -214,6 +214,11 @@ static void read_rr(struct repository *r, struct string_list *rr)
buf.buf[hexsz] = '\0';
id = new_rerere_id_hex(buf.buf);
id->variant = variant;
/*
* make sure id->collection->status has enough space
* for the variant we are interested in
*/
fit_variant(id->collection, variant);
string_list_insert(rr, path)->util = id;
}
strbuf_release(&buf);

View file

@ -671,4 +671,67 @@ test_expect_success 'test simple stage 1 handling' '
)
'
test_expect_success 'rerere does not crash with missing preimage' '
git config rerere.enabled true &&
echo bar >test &&
git add test &&
git commit -m "one" &&
git branch rerere_no_crash &&
echo foo >>test &&
git add test &&
git commit -m "two" &&
git checkout rerere_no_crash &&
echo "bar" >>test &&
git add test &&
git commit -m "three" &&
test_must_fail git rebase main &&
rm .git/rr-cache/*/preimage &&
git rebase --abort
'
test_expect_success 'rerere does not crash with unmatched conflict marker' '
git config rerere.enabled true &&
echo bar >test &&
git add test &&
git commit -m "one" &&
git branch rerere_no_preimage &&
cat >test <<-EOF &&
test
bar
foobar
EOF
git add test &&
git commit -m "two" &&
git checkout rerere_no_preimage &&
echo "bar" >>test &&
git add test &&
git commit -m "three" &&
cat >test <<-EOF &&
foobar
bar
bar
EOF
git add test &&
git commit -m "four" &&
test_must_fail git rebase main &&
cat >test <<-EOF &&
test
bar
<<<<<<< HEAD
foobar
bar
EOF
git add test &&
test_must_fail git rebase --continue
'
test_done