diff options
author | Karsten Blees <karsten.blees@gmail.com> | 2013-11-14 20:24:37 +0100 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2013-11-18 13:04:25 -0800 |
commit | 5699d17ee0949e6c01311a03dcfce485fcdd9b1a (patch) | |
tree | f12588558bd275204e058f2f5c7b88e003edea9e /read-cache.c | |
parent | 6bb69077b74b792ddef66e372c86e66dea8e449b (diff) | |
download | git-5699d17ee0949e6c01311a03dcfce485fcdd9b1a.tar.gz |
read-cache.c: fix memory leaks caused by removed cache entries
When cache_entry structs are removed from index_state.cache, they are not
properly freed. Freeing those entries wasn't possible before because we
couldn't remove them from index_state.name_hash.
Now that we _do_ remove the entries from name_hash, we can also free them.
Add 'free(cache_entry)' to all call sites of name-hash.c::remove_name_hash
in read-cache.c (we could free() directly in remove_name_hash(), but
name-hash.c isn't concerned with cache_entry allocation at all).
Accessing a cache_entry after removing it from the index is now no longer
allowed, as the memory has been freed. The following functions need minor
fixes (typically by copying ce->name before use):
- builtin/rm.c::cmd_rm
- builtin/update-index.c::do_reupdate
- read-cache.c::read_index_unmerged
- resolve-undo.c::unmerge_index_entry_at
Signed-off-by: Karsten Blees <blees@dcon.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'read-cache.c')
-rw-r--r-- | read-cache.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/read-cache.c b/read-cache.c index 00af9addd9..3f735f3c8e 100644 --- a/read-cache.c +++ b/read-cache.c @@ -47,6 +47,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache struct cache_entry *old = istate->cache[nr]; remove_name_hash(istate, old); + free(old); set_index_entry(istate, nr, ce); istate->cache_changed = 1; } @@ -478,6 +479,7 @@ int remove_index_entry_at(struct index_state *istate, int pos) record_resolve_undo(istate, ce); remove_name_hash(istate, ce); + free(ce); istate->cache_changed = 1; istate->cache_nr--; if (pos >= istate->cache_nr) @@ -499,8 +501,10 @@ void remove_marked_cache_entries(struct index_state *istate) unsigned int i, j; for (i = j = 0; i < istate->cache_nr; i++) { - if (ce_array[i]->ce_flags & CE_REMOVE) + if (ce_array[i]->ce_flags & CE_REMOVE) { remove_name_hash(istate, ce_array[i]); + free(ce_array[i]); + } else ce_array[j++] = ce_array[i]; } @@ -1894,7 +1898,7 @@ int read_index_unmerged(struct index_state *istate) new_ce->ce_mode = ce->ce_mode; if (add_index_entry(istate, new_ce, 0)) return error("%s: cannot drop to stage #0", - ce->name); + new_ce->name); i = index_name_pos(istate, new_ce->name, len); } return unmerged; |