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, as name-hash.c isn't concerned with cache_entry allocation.

cmd_rm and unmerge_index_entry_at use cache_entry.name after removing the
entry. Copy the name so that we don't access memory that has been freed.

Signed-off-by: Karsten Blees <bl...@dcon.de>
---
 builtin/rm.c   | 2 +-
 read-cache.c   | 6 +++++-
 resolve-undo.c | 7 +++++--
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/builtin/rm.c b/builtin/rm.c
index 0df0b4d..678da8a 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -324,7 +324,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
                if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, 
seen))
                        continue;
                ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
-               list.entry[list.nr].name = ce->name;
+               list.entry[list.nr].name = xstrdup(ce->name);
                list.entry[list.nr++].is_submodule = S_ISGITLINK(ce->ce_mode);
        }
 
diff --git a/read-cache.c b/read-cache.c
index 0b5c44b..4c570a1 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];
        }
diff --git a/resolve-undo.c b/resolve-undo.c
index 77101f5..64793db 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -119,6 +119,7 @@ int unmerge_index_entry_at(struct index_state *istate, int 
pos)
        struct string_list_item *item;
        struct resolve_undo_info *ru;
        int i, err = 0, matched;
+       char *name;
 
        if (!istate->resolve_undo)
                return pos;
@@ -138,20 +139,22 @@ int unmerge_index_entry_at(struct index_state *istate, 
int pos)
        if (!ru)
                return pos;
        matched = ce->ce_flags & CE_MATCHED;
+       name = xstrdup(ce->name);
        remove_index_entry_at(istate, pos);
        for (i = 0; i < 3; i++) {
                struct cache_entry *nce;
                if (!ru->mode[i])
                        continue;
                nce = make_cache_entry(ru->mode[i], ru->sha1[i],
-                                      ce->name, i + 1, 0);
+                                      name, i + 1, 0);
                if (matched)
                        nce->ce_flags |= CE_MATCHED;
                if (add_index_entry(istate, nce, ADD_CACHE_OK_TO_ADD)) {
                        err = 1;
-                       error("cannot unmerge '%s'", ce->name);
+                       error("cannot unmerge '%s'", name);
                }
        }
+       free(name);
        if (err)
                return pos;
        free(ru);
-- 
1.8.4.11.g4f52745.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to