summaryrefslogtreecommitdiff
path: root/rerere.c
diff options
context:
space:
mode:
authorJohannes Sixt <j6t@kdbg.org>2013-04-04 18:41:43 (GMT)
committerJunio C Hamano <gitster@pobox.com>2013-04-04 19:27:28 (GMT)
commitb9e31f59478eeae3e4230308f6fc06713c6fc547 (patch)
tree8efa207ccba7125535840a5dc6a90c601c8701dc /rerere.c
parent53d8afafbbf455d24b0a94e4114709a4d495d460 (diff)
downloadgit-b9e31f59478eeae3e4230308f6fc06713c6fc547.zip
git-b9e31f59478eeae3e4230308f6fc06713c6fc547.tar.gz
git-b9e31f59478eeae3e4230308f6fc06713c6fc547.tar.bz2
rerere forget: do not segfault if not all stages are present
The loop that fills in the buffers that are later passed to the merge driver exits early when not all stages of a path are present in the index. But since the buffer pointers are not initialized in advance, the subsequent accesses are undefined. Initialize buffer pointers in advance to avoid undefined behavior later. That is not sufficient, though, to get correct operation of handle_cache(). The function replays a conflicted merge to extract the part inside the conflict markers. As written, the loop exits early when a stage is missing. Consequently, the buffers for later stages that would be present in the index are not filled in and the merge is replayed with incomplete data. Fix it by investigating all stages of the given path. Signed-off-by: Johannes Sixt <j6t@kdbg.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'rerere.c')
-rw-r--r--rerere.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/rerere.c b/rerere.c
index 4d940cd..98e3e29 100644
--- a/rerere.c
+++ b/rerere.c
@@ -297,7 +297,7 @@ static int rerere_mem_getline(struct strbuf *sb, struct rerere_io *io_)
static int handle_cache(const char *path, unsigned char *sha1, const char *output)
{
- mmfile_t mmfile[3];
+ mmfile_t mmfile[3] = {{NULL}};
mmbuffer_t result = {NULL, 0};
struct cache_entry *ce;
int pos, len, i, hunk_no;
@@ -316,17 +316,16 @@ static int handle_cache(const char *path, unsigned char *sha1, const char *outpu
for (i = 0; i < 3; i++) {
enum object_type type;
unsigned long size;
+ int j;
- mmfile[i].size = 0;
- mmfile[i].ptr = NULL;
if (active_nr <= pos)
break;
ce = active_cache[pos++];
- if (ce_namelen(ce) != len || memcmp(ce->name, path, len)
- || ce_stage(ce) != i + 1)
- break;
- mmfile[i].ptr = read_sha1_file(ce->sha1, &type, &size);
- mmfile[i].size = size;
+ if (ce_namelen(ce) != len || memcmp(ce->name, path, len))
+ continue;
+ j = ce_stage(ce) - 1;
+ mmfile[j].ptr = read_sha1_file(ce->sha1, &type, &size);
+ mmfile[j].size = size;
}
for (i = 0; i < 3; i++) {
if (!mmfile[i].ptr && !mmfile[i].size)