commit-graph: clean up leaked memory during write
authorDerrick Stolee <dstolee@microsoft.com>
Wed, 3 Oct 2018 17:12:15 +0000 (10:12 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sat, 6 Oct 2018 23:25:05 +0000 (08:25 +0900)
The write_commit_graph() method in commit-graph.c leaks some lits
and strings during execution. In addition, a list of strings is
leaked in write_commit_graph_reachable(). Clean these up so our
memory checking is cleaner.

Further, if we use a list of pack-files to find the commits, we
can leak the packed_git structs after scanning them for commits.

Running the following commands demonstrates the leak before and
the fix after:

* valgrind --leak-check=full ./git commit-graph write --reachable
* valgrind --leak-check=full ./git commit-graph write --stdin-packs

Signed-off-by: Martin Ă…gren <martin.agren@gmail.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit-graph.c

index 2a24eb8..ceca602 100644 (file)
@@ -693,11 +693,12 @@ static int add_ref_to_list(const char *refname,
 void write_commit_graph_reachable(const char *obj_dir, int append,
                                  int report_progress)
 {
 void write_commit_graph_reachable(const char *obj_dir, int append,
                                  int report_progress)
 {
-       struct string_list list;
+       struct string_list list = STRING_LIST_INIT_DUP;
 
 
-       string_list_init(&list, 1);
        for_each_ref(add_ref_to_list, &list);
        write_commit_graph(obj_dir, NULL, &list, append, report_progress);
        for_each_ref(add_ref_to_list, &list);
        write_commit_graph(obj_dir, NULL, &list, append, report_progress);
+
+       string_list_clear(&list, 0);
 }
 
 void write_commit_graph(const char *obj_dir,
 }
 
 void write_commit_graph(const char *obj_dir,
@@ -764,6 +765,7 @@ void write_commit_graph(const char *obj_dir,
                                die(_("error opening index for %s"), packname.buf);
                        for_each_object_in_pack(p, add_packed_commits, &oids, 0);
                        close_pack(p);
                                die(_("error opening index for %s"), packname.buf);
                        for_each_object_in_pack(p, add_packed_commits, &oids, 0);
                        close_pack(p);
+                       free(p);
                }
                stop_progress(&oids.progress);
                strbuf_release(&packname);
                }
                stop_progress(&oids.progress);
                strbuf_release(&packname);
@@ -846,9 +848,11 @@ void write_commit_graph(const char *obj_dir,
        compute_generation_numbers(&commits, report_progress);
 
        graph_name = get_commit_graph_filename(obj_dir);
        compute_generation_numbers(&commits, report_progress);
 
        graph_name = get_commit_graph_filename(obj_dir);
-       if (safe_create_leading_directories(graph_name))
+       if (safe_create_leading_directories(graph_name)) {
+               UNLEAK(graph_name);
                die_errno(_("unable to create leading directories of %s"),
                          graph_name);
                die_errno(_("unable to create leading directories of %s"),
                          graph_name);
+       }
 
        hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
        f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
 
        hold_lock_file_for_update(&lk, graph_name, LOCK_DIE_ON_ERROR);
        f = hashfd(lk.tempfile->fd, lk.tempfile->filename.buf);
@@ -893,9 +897,9 @@ void write_commit_graph(const char *obj_dir,
        finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
        commit_lock_file(&lk);
 
        finalize_hashfile(f, NULL, CSUM_HASH_IN_STREAM | CSUM_FSYNC);
        commit_lock_file(&lk);
 
+       free(graph_name);
+       free(commits.list);
        free(oids.list);
        free(oids.list);
-       oids.alloc = 0;
-       oids.nr = 0;
 }
 
 #define VERIFY_COMMIT_GRAPH_ERROR_HASH 2
 }
 
 #define VERIFY_COMMIT_GRAPH_ERROR_HASH 2