summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@osdl.org>2005-07-26 20:04:22 -0700
committerJunio C Hamano <junkio@cox.net>2005-07-26 22:23:18 -0700
commitbdf25142aaac016f4d992001f336d53ab4fbc75e (patch)
tree41d575f73b853d02144086a55f643fe037a49b97
parent2779fad61302da0fe3a24995e343ab894f32fa42 (diff)
downloadgit-bdf25142aaac016f4d992001f336d53ab4fbc75e.tar.gz
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>
-rw-r--r--send-pack.c3
-rwxr-xr-xt/t5400-send-pack.sh54
2 files changed, 56 insertions, 1 deletions
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
+'