From bdf25142aaac016f4d992001f336d53ab4fbc75e Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@osdl.org>
Date: Tue, 26 Jul 2005 20:04:22 -0700
Subject: [PATCH] Fix potential send-pack SIGSEGV

The check that the source is ahead of the destination incorrectly expects
pop_most_recent_commit() to gracefully handle an empty list.

Fix by just checking the list itself, rather than the return value of the
pop function.

[jc: I did the test script that demonstrated the problem]

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 send-pack.c          |  3 ++-
 t/t5400-send-pack.sh | 54 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 1 deletion(-)
 create mode 100755 t/t5400-send-pack.sh

diff --git a/send-pack.c b/send-pack.c
index 2a7ab2d2b9..9b4be6130c 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -134,7 +134,8 @@ static int ref_newer(const unsigned char *new_sha1, const unsigned char *old_sha
 		return 0;
 	list = NULL;
 	commit_list_insert(new, &list);
-	while ((new = pop_most_recent_commit(&list, 1)) != NULL) {
+	while (list) {
+		new = pop_most_recent_commit(&list, 1);
 		if (new == old)
 			return 1;
 	}
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
new file mode 100755
index 0000000000..19a8f122c7
--- /dev/null
+++ b/t/t5400-send-pack.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='See why rewinding head breaks send-pack
+
+'
+. ./test-lib.sh
+
+cnt='1'
+test_expect_success setup '
+	tree=$(git-write-tree) &&
+	commit=$(echo "Commit #0" | git-commit-tree $tree) &&
+	zero=$commit &&
+	parent=$zero &&
+	for i in $cnt
+	do
+	    sleep 1 &&
+	    commit=$(echo "Commit #$i" | git-commit-tree $tree -p $parent) &&
+	    parent=$commit || exit
+	done &&
+	echo "$commit" >.git/HEAD &&
+	git clone -l ./. victim &&
+	cd victim &&
+	git log &&
+	cd .. &&
+	echo $zero >.git/HEAD &&
+	parent=$zero &&
+	for i in $cnt
+	do
+	    sleep 1 &&
+	    commit=$(echo "Rebase #$i" | git-commit-tree $tree -p $parent) &&
+	    parent=$commit || exit
+	done &&
+	echo "$commit" >.git/HEAD &&
+	echo Rebase &&
+	git log'
+
+test_expect_success \
+        'pushing rewound head should not barf but require --force' ' 
+	# should not fail but refuse to update.
+	git-send-pack ./victim/.git/ master &&
+	if cmp victim/.git/refs/heads/master .git/refs/heads/master
+	then
+		# should have been left as it was!
+		false
+	else
+		true
+	fi &&
+	# this should update
+	git-send-pack --force ./victim/.git/ master &&
+	cmp victim/.git/refs/heads/master .git/refs/heads/master
+'