Skip to content

Commit 6ff264e

Browse files
René Scharfegitster
authored andcommitted
unpack-trees: plug minor memory leak
The allocations made by unpack_nondirectories() using create_ce_entry() are never freed. In the non-merge case, we duplicate them using add_entry() and later only look at the first allocated element (src[0]), perhaps even only by mistake. Split out the actual addition from add_entry() into the new helper do_add_entry() and call this non-duplicating function instead of add_entry() to avoid the leak. Valgrind reports this for the command "git archive v1.7.9" without the patch: ==13372== LEAK SUMMARY: ==13372== definitely lost: 230,986 bytes in 2,325 blocks ==13372== indirectly lost: 0 bytes in 0 blocks ==13372== possibly lost: 98 bytes in 1 blocks ==13372== still reachable: 2,259,198 bytes in 3,243 blocks ==13372== suppressed: 0 bytes in 0 blocks And with the patch applied: ==13375== LEAK SUMMARY: ==13375== definitely lost: 65 bytes in 1 blocks ==13375== indirectly lost: 0 bytes in 0 blocks ==13375== possibly lost: 0 bytes in 0 blocks ==13375== still reachable: 2,364,417 bytes in 3,245 blocks ==13375== suppressed: 0 bytes in 0 blocks Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 97e5954 commit 6ff264e

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

unpack-trees.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,21 +102,28 @@ void setup_unpack_trees_porcelain(struct unpack_trees_options *opts,
102102
opts->unpack_rejects[i].strdup_strings = 1;
103103
}
104104

105-
static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
106-
unsigned int set, unsigned int clear)
105+
static void do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
106+
unsigned int set, unsigned int clear)
107107
{
108-
unsigned int size = ce_size(ce);
109-
struct cache_entry *new = xmalloc(size);
110-
111108
clear |= CE_HASHED | CE_UNHASHED;
112109

113110
if (set & CE_REMOVE)
114111
set |= CE_WT_REMOVE;
115112

113+
ce->next = NULL;
114+
ce->ce_flags = (ce->ce_flags & ~clear) | set;
115+
add_index_entry(&o->result, ce,
116+
ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
117+
}
118+
119+
static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
120+
unsigned int set, unsigned int clear)
121+
{
122+
unsigned int size = ce_size(ce);
123+
struct cache_entry *new = xmalloc(size);
124+
116125
memcpy(new, ce, size);
117-
new->next = NULL;
118-
new->ce_flags = (new->ce_flags & ~clear) | set;
119-
add_index_entry(&o->result, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
126+
do_add_entry(o, new, set, clear);
120127
}
121128

122129
/*
@@ -587,7 +594,7 @@ static int unpack_nondirectories(int n, unsigned long mask,
587594

588595
for (i = 0; i < n; i++)
589596
if (src[i] && src[i] != o->df_conflict_entry)
590-
add_entry(o, src[i], 0, 0);
597+
do_add_entry(o, src[i], 0, 0);
591598
return 0;
592599
}
593600

0 commit comments

Comments
 (0)