Bug: Commit a merge resolution with non-closed conflict markers leads to errs, segfault
To
git@vger.kernel.org
From
BENTZ Sylvain
Date
2021-07-22 09:28:13 UTC
Hello,

I've stumbled on a segmentation fault while resolving merge conflicts.
Basically, I missed to remove some conflict markers, tried to commit the
(faulty) merge resolution, and Git mishandles that.

The original issue happened applying a patch using 3-way merge.  The minimal
working example below creates a conflict with a simple `git merge` command.


Thank you for filling out a Git bug report!
Please answer the following questions to help us understand your issue.

What did you do before the bug happened? (Steps to reproduce your issue)

1. Create a merge conflict
2. Edit the conflicted file, keep some conflict markers (more on that below [1])
3. Commit (works but errors are reported!)
4. Fix the file, by removing all conflict markers
5. Commit (works but segmentation fault!)
6. Commit again, with some changes or with an empty commit (fatal error!)

See shell script (MWE) below [2].


What did you expect to happen? (Expected behavior)

At step 3, Git should return an error without committing.


What happened instead? (Actual behavior)

Git works and breaks at the same time.
Step 3 : It throws error messages without returning an error, and it does commit.
Step 5 : It breaks (segfault), manages to commit, but fails to remove a lockfile.

See terminal output below [3].

Then, if I reset hard to the commit named "master", delete the lockfile, and
repeat the process, I still get errors in step 3, but no segfault in step 5.


What's different between what you expected and what actually happened?

Git shouldn't segfault obviously. See gdb output below [4].


Anything else you want to add:

Tested versions: 2.20 (debian stable), 2.32 (alpine 3.14), next (alpine 3.14)

[1] Some configurations of conflict markers triggers that bug, others don't.
    The minimal working example shows the case (A).

Failure cases:
(A)        (B)        (C)
<<<<<<<<<  <<<<<<<<<  <<<<<<<<<
           >>>>>>>>>  =========

Not failure cases:
(D)        (E)        (F)
=========  =========  >>>>>>>>>
>>>>>>>>>                      

[2] Shell script (MWE)

# Setup conflicting branches `master' and `conflict'

FOLDER=${1:-git-break}
mkdir "$FOLDER"
cd "$FOLDER"
git init
echo '' > README
git add README
git commit -m "First commit"
echo master > README
git commit -i README -m "master"
git checkout -b conflict HEAD~
echo conflict > README
git commit -i README -m "conflict"
git checkout master

# Convenience functions

mer() { set -x; git merge conflict; }
com() { set -x; git add README; git commit -m "$1"; }
del() { set -x; for arg; do sed -i "/$arg/ d" README; done; cat README; }
see() { set -x; git log -p -n2; }

# Script

mer                  # Create a merge conflict
del = '>'            # Keep the conflict marker `<<<<<<<<<<<'
com "Merge commit"   # Commit (errors reported)
del '<'              # Fix by deleting the remaining marker
com "Fix the merge"  # Commit (segfault)
echo next >> README  # Do some changes...
com "next"           # Commit (fatal error)

[3] Terminal output

####### START TERMINAL OUTPUT ########

/git-min # see
+ see
+ set -x
+ git log -p -n2
commit 9a9dd03509b8cf45c8037c60c256d6ef67f9e431 (HEAD -> master)
Author: sylvain.bentz <sylvain.bentz@md6.fr>
Date:   Wed Jul 21 14:50:37 2021 +0200

    master

diff --git a/README b/README
index 8b13789..1f7391f 100644
--- a/README
+++ b/README
@@ -1 +1 @@
-
+master

commit cfb5d5cd9f28e1dcca7a1d1088405d8ec4ebf713
Author: sylvain.bentz <sylvain.bentz@md6.fr>
Date:   Wed Jul 21 14:49:36 2021 +0200

    First commit

diff --git a/README b/README
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+

/git-min # mer
+ mer
+ set -x
+ git merge conflict
Auto-merging README
CONFLICT (content): Merge conflict in README
Recorded preimage for 'README'
Automatic merge failed; fix conflicts and then commit the result.

/git-min # del = '>'
+ del '=' '>'
+ set -x
+ sed -i '/=/ d' README
+ sed -i '/>/ d' README
+ cat README
<<<<<<< HEAD
master
conflict

/git-min # com merge
+ com merge
+ set -x
+ git add README
+ git commit -m merge
error: could not parse conflict hunks in 'README'
error: could not parse conflict hunks in 'README'
Recorded preimage for 'README'
[master ab6c525] merge

/git-min # del '<'
+ del '<'
+ set -x
+ sed -i '/</ d' README
+ cat README
master
conflict

/git-min # com mergefix
+ com mergefix
+ set -x
+ git add README
+ git commit -m mergefix
Segmentation fault

/git-min # see
+ see
+ set -x
+ git log -p -n2
commit 8ea1a55602ba5ae505b43f2ae3a49b3a9a26b2fe (HEAD -> master)
Author: Your Name <you@example.com>
Date:   Wed Jul 21 15:38:35 2021 +0000

    mergefix

diff --git a/README b/README
index 59c1bc9..6ecc231 100644
--- a/README
+++ b/README
@@ -1,3 +1,2 @@
-<<<<<<< HEAD
 master
 conflict

commit ab6c52591506ac2e75745814527f062d767b4e11
Merge: 9a9dd03 42a166a
Author: Your Name <you@example.com>
Date:   Wed Jul 21 15:38:18 2021 +0000

    merge

/git-min # echo 'next' >> README
+ echo next

/git-min # com next
+ com next
+ set -x
+ git add README
+ git commit -m next
fatal: Unable to create '/git-min/.git/MERGE_RR.lock': File exists.

Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.

/git-min # git --version
+ git --version
git version 2.32.0.473.g1bb01aad6f

/git-min # git config --list
+ git config --list
user.email=you@example.com
user.name=Your Name
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.pager=cat
color.ui=never

####### END TERMINAL OUTPUT ########

[4] GDB Output

(gdb) run
Starting program: /usr/local/bin/git commit -m Fix\ the\ merge
warning: Error disabling address space randomization: Operation not permitted

Program received signal SIGSEGV, Segmentation fault.
0x000055dbdff61748 in do_rerere_one_path (update=0x7ffffce68720, rr_item=0x7f5ed8e20340,
    istate=0x55dbe00ef520 <the_index>) at rerere.c:736
736


Please review the rest of the bug report below.
You can delete any lines you don't wish to share.

[System Info]
git version:
git version 2.32.0.473.g1bb01aad6f
cpu: x86_64
built from commit: 1bb01aad6fdafaac7a11bed18a67384f28ab735b
sizeof-long: 8
sizeof-size_t: 8
shell-path: /bin/sh
uname: Linux 5.4.72-microsoft-standard-WSL2 #1 SMP Wed Oct 28 23:40:43 UTC 2020 x86_64
compiler info: gnuc: 10.3
libc info: no libc information available
$SHELL (typically, interactive shell): <unset>

[Enabled Hooks]