Subject: [PATCH] rerere forget: grok files containing NUL

From: Johannes Sixt <[email-masked]>
Date: Mon, 01 Apr 2013 23:36:36 +0200

Using 'git rerere forget .' after a merge that involved binary files
runs into an infinite loop if the binary file contains a zero byte.
Replace a strchrnul by memchr because the former does not make progress
as soon as the NUL is encountered.

Signed-off-by: Johannes Sixt <[email-masked]>
---
 The new test case runs into the infinite loop if you back out
 the code change.

 There's another bug where an uninitialized pointer is accessed
 in the second for-loop in handle_cache(), presumably for a file
 with ADD-ADD conflicts. Will look into that one later this week.

 -- Hannes

 rerere.c                  |  6 ++++--
 t/t2030-unresolve-info.sh | 12 ++++++++++++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/rerere.c b/rerere.c
index a6a5cd5..4d940cd 100644
--- a/rerere.c
+++ b/rerere.c
@@ -284,8 +284,10 @@ static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)
 	strbuf_release(sb);
 	if (!io->input.len)
 		return -1;
-	ep = strchrnul(io->input.buf, '\n');
-	if (*ep == '\n')
+	ep = memchr(io->input.buf, '\n', io->input.len);
+	if (!ep)
+		ep = io->input.buf + io->input.len;
+	else if (*ep == '\n')
 		ep++;
 	len = ep - io->input.buf;
 	strbuf_add(sb, io->input.buf, len);
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
index f262065..0b699f5 100755
--- a/t/t2030-unresolve-info.sh
+++ b/t/t2030-unresolve-info.sh
@@ -44,9 +44,13 @@ prime_resolve_undo () {
 
 test_expect_success setup '
 	mkdir fi &&
+	printf "a\0a" >binary &&
+	git add binary &&
 	test_commit initial fi/le first &&
 	git branch side &&
 	git branch another &&
+	printf "a\0b" >binary &&
+	git add binary &&
 	test_commit second fi/le second &&
 	git checkout side &&
 	test_commit third fi/le third &&
@@ -167,4 +171,12 @@ test_expect_success 'rerere and rerere forget (subdirectory)' '
 	test_cmp expect actual
 '
 
+test_expect_success 'rerere forget (binary)' '
+	git checkout -f side &&
+	printf "a\0c" >binary &&
+	git commit -a -m binary &&
+	test_must_fail git merge second &&
+	git rerere forget binary
+'
+
 test_done
-- 
1.8.2.383.g5f2fd52