Code

Fix potential send-pack SIGSEGV
authorLinus Torvalds <torvalds@osdl.org>
Wed, 27 Jul 2005 03:04:22 +0000 (20:04 -0700)
committerJunio C Hamano <junkio@cox.net>
Wed, 27 Jul 2005 05:23:18 +0000 (22:23 -0700)
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
t/t5400-send-pack.sh [new file with mode: 0755]

index 2a7ab2d2b9428adcbe740390e78f164b462bb717..9b4be6130cad815384a3116be82af1264b9e286f 100644 (file)
@@ -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 (executable)
index 0000000..19a8f12
--- /dev/null
@@ -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
+'