From 89e653da5b1bee9cf645e9d4bdd95f6bb31cc4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C3=85gren?= Date: Sun, 20 May 2018 12:17:34 +0200 Subject: merge: setup `opts` later in `checkout_fast_forward()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After we initialize the various fields in `opts` but before we actually use them, we might return early. Move the initialization further down, to immediately before we use `opts`. This limits the scope of `opts` and will help a later commit fix a memory leak without having to worry about those early returns. This patch is best viewed using something like this (note the tab!): --color-moved --anchored=" trees[nr_trees] = parse_tree_indirect" Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- merge.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'merge.c') diff --git a/merge.c b/merge.c index f06a4773d4..f123658e58 100644 --- a/merge.c +++ b/merge.c @@ -94,8 +94,24 @@ int checkout_fast_forward(const struct object_id *head, return -1; memset(&trees, 0, sizeof(trees)); - memset(&opts, 0, sizeof(opts)); memset(&t, 0, sizeof(t)); + + trees[nr_trees] = parse_tree_indirect(head); + if (!trees[nr_trees++]) { + rollback_lock_file(&lock_file); + return -1; + } + trees[nr_trees] = parse_tree_indirect(remote); + if (!trees[nr_trees++]) { + rollback_lock_file(&lock_file); + return -1; + } + for (i = 0; i < nr_trees; i++) { + parse_tree(trees[i]); + init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); + } + + memset(&opts, 0, sizeof(opts)); if (overwrite_ignore) { memset(&dir, 0, sizeof(dir)); dir.flags |= DIR_SHOW_IGNORED; @@ -112,20 +128,6 @@ int checkout_fast_forward(const struct object_id *head, opts.fn = twoway_merge; setup_unpack_trees_porcelain(&opts, "merge"); - trees[nr_trees] = parse_tree_indirect(head); - if (!trees[nr_trees++]) { - rollback_lock_file(&lock_file); - return -1; - } - trees[nr_trees] = parse_tree_indirect(remote); - if (!trees[nr_trees++]) { - rollback_lock_file(&lock_file); - return -1; - } - for (i = 0; i < nr_trees; i++) { - parse_tree(trees[i]); - init_tree_desc(t+i, trees[i]->buffer, trees[i]->size); - } if (unpack_trees(nr_trees, t, &opts)) { rollback_lock_file(&lock_file); return -1; -- cgit v1.2.3 From 1c41d2805e42d77d943fd3d79ebf5136f74c9ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C3=85gren?= Date: Mon, 21 May 2018 16:54:28 +0200 Subject: unpack_trees_options: free messages when done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The strings allocated in `setup_unpack_trees_porcelain()` are never freed. Provide a function `clear_unpack_trees_porcelain()` to do so and call it where we use `setup_unpack_trees_porcelain()`. The only non-trivial user is `unpack_trees_start()`, where we should place the new call in `unpack_trees_finish()`. We keep the string pointers in an array, mixing pointers to static memory and memory that we allocate on the heap. We also keep several copies of the individual pointers. So we need to make sure that we do not free what we must not free and that we do not double-free. Let a separate argv_array take ownership of all the strings we create so that we can easily free them. Zero the whole array of string pointers to make sure that we do not leave any dangling pointers. Note that we only take responsibility for the memory allocated in `setup_unpack_trees_porcelain()` and not any other members of the `struct unpack_trees_options`. Helped-by: Junio C Hamano Signed-off-by: Junio C Hamano Signed-off-by: Martin Ågren Signed-off-by: Junio C Hamano --- merge.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'merge.c') diff --git a/merge.c b/merge.c index f123658e58..b433291d0c 100644 --- a/merge.c +++ b/merge.c @@ -130,8 +130,11 @@ int checkout_fast_forward(const struct object_id *head, if (unpack_trees(nr_trees, t, &opts)) { rollback_lock_file(&lock_file); + clear_unpack_trees_porcelain(&opts); return -1; } + clear_unpack_trees_porcelain(&opts); + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) return error(_("unable to write new index file")); return 0; -- cgit v1.2.3