diff options
author | Jeff King <peff@peff.net> | 2015-02-26 20:42:27 -0500 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2015-02-27 13:41:29 -0800 |
commit | 4d6be03b95c3db21db1bb8fee01128c1b13f70e7 (patch) | |
tree | 0f7900c095a79b828c04f25577896f8163518d13 /diffcore-rename.c | |
parent | f98c2f7e53062a59f67914337c0b45c82393e11f (diff) | |
download | git-4d6be03b95c3db21db1bb8fee01128c1b13f70e7.tar.gz |
diffcore-rename: avoid processing duplicate destinationsjk/diffcore-rename-duplicate
The rename code cannot handle an input where we have
duplicate destinations (i.e., more than one diff_filepair in
the queue with the same string in its pair->two->path). We
end up allocating only one slot in the rename_dst mapping.
If we fill in the diff_filepair for that slot, when we
re-queue the results, we may queue that filepair multiple
times. When the diff is finally flushed, the filepair is
processed and free()d multiple times, leading to heap
corruption.
This situation should only happen when a tree diff sees
duplicates in one of the trees (see the added test for a
detailed example). Rather than handle it, the sanest thing
is just to turn off rename detection altogether for the
diff.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'diffcore-rename.c')
-rw-r--r-- | diffcore-rename.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/diffcore-rename.c b/diffcore-rename.c index 0afe903de9..361eed9fbc 100644 --- a/diffcore-rename.c +++ b/diffcore-rename.c @@ -467,8 +467,12 @@ void diffcore_rename(struct diff_options *options) else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && is_empty_blob_sha1(p->two->sha1)) continue; - else - add_rename_dst(p->two); + else if (add_rename_dst(p->two) < 0) { + warning("skipping rename detection, detected" + " duplicate destination '%s'", + p->two->path); + goto cleanup; + } } else if (!DIFF_OPT_TST(options, RENAME_EMPTY) && is_empty_blob_sha1(p->one->sha1)) |