]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fix segfault with git log -c --follow
authorClemens Buchacher <drizzd@aon.at>
Mon, 27 May 2013 22:49:57 +0000 (00:49 +0200)
committerJunio C Hamano <gitster@pobox.com>
Tue, 28 May 2013 18:26:24 +0000 (11:26 -0700)
In diff_tree_combined we make a copy of diffopts. In
try_to_follow_renames, called via diff_tree_sha1, we free and
re-initialize diffopts->pathspec->items. Since we did not make a deep
copy of diffopts in diff_tree_combined, the original diffopts does not
get the update. By the time we return from diff_tree_combined,
rev->diffopt->pathspec->items points to an invalid memory address. We
get a segfault next time we try to access that pathspec.

Instead, along with the copy of diffopts, make a copy pathspec->items as
well.

We would also have to make a copy of pathspec->raw to keep it consistent
with pathspec->items, but nobody seems to rely on that.

Signed-off-by: Clemens Buchacher <drizzd@aon.at>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
combine-diff.c
t/t4202-log.sh

index 7f6187f9cd2fc44540cddbcf4bb853231c57397c..21fd00ff6156f7eb7af6b74dd569325af3f37820 100644 (file)
@@ -1120,6 +1120,7 @@ void diff_tree_combined(const unsigned char *sha1,
        int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
 
        diffopts = *opt;
+       diff_tree_setup_paths(diffopts.pathspec.raw, &diffopts);
        diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
        DIFF_OPT_SET(&diffopts, RECURSIVE);
        DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL);
@@ -1187,6 +1188,8 @@ void diff_tree_combined(const unsigned char *sha1,
                paths = paths->next;
                free(tmp);
        }
+
+       diff_tree_release_paths(&diffopts);
 }
 
 void diff_tree_combined_merge(const struct commit *commit, int dense,
index fa686b887d6b49ab8e6d30893501744645f72a91..d9e587a96ed095cf29b393e380e1697d753a367a 100755 (executable)
@@ -542,6 +542,20 @@ test_expect_success 'show added path under "--follow -M"' '
        )
 '
 
+test_expect_success 'git log -c --follow' '
+       test_create_repo follow-c &&
+       (
+               cd follow-c &&
+               test_commit initial file original &&
+               git rm file &&
+               test_commit rename file2 original &&
+               git reset --hard initial &&
+               test_commit modify file foo &&
+               git merge -m merge rename &&
+               git log -c --follow file2
+       )
+'
+
 cat >expect <<\EOF
 *   commit COMMIT_OBJECT_NAME
 |\  Merge: MERGE_PARENTS