git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 10/11] read-cache.c: fix memory leaks caused by removed cache entries

From
Karsten Blees <karsten.blees@gmail.com>
Date
Oct 1, 2013, 09:40 UTC
Message-ID
<524A9886.2030508@gmail.com>
In-Reply-To
<524A96FF.5090604@gmail.com>

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 <blees@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
Previous: Karsten BleesNext: Thomas Rast
Message 11 of 14 in “New hash table implementation”
  1. 00/11 New hash table implementationKarsten Blees, Oct 1, 2013
  2. 01/11 add a hashtable implementation that supports O(1) removalKarsten Blees, Oct 1, 2013
  3. 02/11 buitin/describe.c: use new hash map implementationKarsten Blees, Oct 1, 2013
  4. 03/11 diffcore-rename.c: move code around to prepare for the next patchKarsten Blees, Oct 1, 2013
  5. 04/11 diffcore-rename.c: simplify finding exact renamesKarsten Blees, Oct 1, 2013
  6. 05/11 diffcore-rename.c: use new hash map implementationKarsten Blees, Oct 1, 2013
  7. 06/11 name-hash.c: use new hash map implementation for directoriesKarsten Blees, Oct 1, 2013
  8. 07/11 name-hash.c: remove unreferenced directory entriesKarsten Blees, Oct 1, 2013
  9. 08/11 name-hash.c: use new hash map implementation for cache entriesKarsten Blees, Oct 1, 2013
  10. 09/11 name-hash.c: remove cache entries instead of marking them CE_UNHASHEDKarsten Blees, Oct 1, 2013
  11. 10/11 read-cache.c: fix memory leaks caused by removed cache entriesKarsten Blees, Oct 1, 2013
  12. Thomas RastOct 19, 2013
  13. fixup! read-cache.c: fix memory leaks caused by removed cache, entriesKarsten Blees, Oct 22, 2013
  14. 11/11 remove old hash.[ch] implementationKarsten Blees, Oct 1, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.