Skip to content

Commit 46ec510

Browse files
Clemens Buchachergitster
authored andcommitted
fix segfault with git log -c --follow
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 04a74b6 commit 46ec510

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

combine-diff.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,7 @@ void diff_tree_combined(const unsigned char *sha1,
11201120
int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
11211121

11221122
diffopts = *opt;
1123+
diff_tree_setup_paths(diffopts.pathspec.raw, &diffopts);
11231124
diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
11241125
DIFF_OPT_SET(&diffopts, RECURSIVE);
11251126
DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL);
@@ -1187,6 +1188,8 @@ void diff_tree_combined(const unsigned char *sha1,
11871188
paths = paths->next;
11881189
free(tmp);
11891190
}
1191+
1192+
diff_tree_release_paths(&diffopts);
11901193
}
11911194

11921195
void diff_tree_combined_merge(const struct commit *commit, int dense,

t/t4202-log.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,20 @@ test_expect_success 'show added path under "--follow -M"' '
542542
)
543543
'
544544

545+
test_expect_success 'git log -c --follow' '
546+
test_create_repo follow-c &&
547+
(
548+
cd follow-c &&
549+
test_commit initial file original &&
550+
git rm file &&
551+
test_commit rename file2 original &&
552+
git reset --hard initial &&
553+
test_commit modify file foo &&
554+
git merge -m merge rename &&
555+
git log -c --follow file2
556+
)
557+
'
558+
545559
cat >expect <<\EOF
546560
* commit COMMIT_OBJECT_NAME
547561
|\ Merge: MERGE_PARENTS

0 commit comments

Comments
 (0)