We read the tree objects with fill_tree_descriptor(), but
never actually free the resulting buffers, causing a memory
leak. This isn't a huge deal because we call this code at
most twice per program invocation. But it does potentially
double our heap usage if you have large root trees. Let's
free the trees before returning.


Signed-off-by: Jeff King <p...@peff.net>
---
Actually, in the two-call case we repeat one of the trees,
so we _could_ in theory stash it away. But we don't do that
currently, and it's probably not worth the effort. My main
motivation is just shutting up the leak checker so I can
find actual important leaks.

 builtin/reset.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/builtin/reset.c b/builtin/reset.c
index 34839db8ca..9e22b4a1dc 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -44,10 +44,11 @@ static inline int is_merge(void)
 
 static int reset_index(const struct object_id *oid, int reset_type, int quiet)
 {
-       int nr = 0;
+       int i, nr = 0;
        struct tree_desc desc[2];
        struct tree *tree;
        struct unpack_trees_options opts;
+       int ret = -1;
 
        memset(&opts, 0, sizeof(opts));
        opts.head_idx = 1;
@@ -81,19 +82,26 @@ static int reset_index(const struct object_id *oid, int 
reset_type, int quiet)
                opts.fn = twoway_merge;
        }
 
-       if (!fill_tree_descriptor(desc + nr, oid))
-               return error(_("Failed to find tree of %s."), oid_to_hex(oid));
+       if (!fill_tree_descriptor(desc + nr, oid)) {
+               error(_("Failed to find tree of %s."), oid_to_hex(oid));
+               goto out;
+       }
        nr++;
 
-       if (unpack_trees(nr, desc, &opts))
-               return -1;
+       if (unpack_trees(nr, desc, &opts)) 
+               goto out;
 
        if (reset_type == MIXED || reset_type == HARD) {
                tree = parse_tree_indirect(oid);
                prime_cache_tree(&the_index, tree);
        }
 
-       return 0;
+       ret = 0;
+
+out:
+       for (i = 0; i < nr; i++)
+               free((void *)desc[i].buffer);
+       return ret;
 }
 
 static void print_new_head_line(struct commit *commit)
-- 
2.14.1.721.gc5bc1565f1

Reply via email to