]> git.ipfire.org Git - thirdparty/git.git/commitdiff
dir.c: free strings in sparse cone pattern hashmaps
authorJeff King <peff@peff.net>
Tue, 4 Jun 2024 10:13:14 +0000 (06:13 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 4 Jun 2024 17:38:23 +0000 (10:38 -0700)
The pattern_list structs used for cone-mode sparse lookups use a few
extra hashmaps. These store pattern_entry structs, each of which has its
own heap-allocated pattern string. When we clean up the hashmaps, we
free the individual pattern_entry structs, but forget to clean up the
embedded strings, causing memory leaks.

We can fix this by iterating over the hashmaps to free the extra
strings. This reduces the numbers of leaks in t7002 from 22 to 9.

One alternative here would be to make the string a FLEX_ARRAY member of
the pattern_entry. Then there's no extra free() required, and as a bonus
it would be a little more efficient. However, some of the refactoring
gets awkward, as we are often assigning strings allocated by helper
functions. So let's just fix the leak for now, and we can explore bigger
refactoring separately.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
dir.c

diff --git a/dir.c b/dir.c
index 2d83f3311a75131a98a22a1d278b433c32ada560..9cc4a68fbce3c1be6a24e71da829650e27ba23cd 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -726,6 +726,17 @@ static char *dup_and_filter_pattern(const char *pattern)
        return result;
 }
 
+static void clear_pattern_entry_hashmap(struct hashmap *map)
+{
+       struct hashmap_iter iter;
+       struct pattern_entry *entry;
+
+       hashmap_for_each_entry(map, &iter, entry, ent) {
+               free(entry->pattern);
+       }
+       hashmap_clear_and_free(map, struct pattern_entry, ent);
+}
+
 static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern *given)
 {
        struct pattern_entry *translated;
@@ -855,8 +866,8 @@ static void add_pattern_to_hashsets(struct pattern_list *pl, struct path_pattern
 
 clear_hashmaps:
        warning(_("disabling cone pattern matching"));
-       hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
-       hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
+       clear_pattern_entry_hashmap(&pl->recursive_hashmap);
+       clear_pattern_entry_hashmap(&pl->parent_hashmap);
        pl->use_cone_patterns = 0;
 }
 
@@ -956,8 +967,8 @@ void clear_pattern_list(struct pattern_list *pl)
                free(pl->patterns[i]);
        free(pl->patterns);
        free(pl->filebuf);
-       hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
-       hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
+       clear_pattern_entry_hashmap(&pl->recursive_hashmap);
+       clear_pattern_entry_hashmap(&pl->parent_hashmap);
 
        memset(pl, 0, sizeof(*pl));
 }