Skip to content

Commit add1743

Browse files
committed
cache: fix cache eviction using deallocated key
When evicting cache entries, we first retrieve the object that is to be evicted, delete the object and then finally delete the key from the cache. In case where the cache eviction caused us to free the cached object, though, its key will point to invalid memory now when trying to remove it from the cache map. On my system, this causes us to not properly remove the key from the map, as its memory has been overwritten already and thus the key lookup it will fail and we cannot delete it. Fix this by only decrementing the refcount of the evictee after we have removed it from our cache map. Add a test that caused a segfault previous to that change.
1 parent 2b8a05c commit add1743

File tree

2 files changed

+9
-2
lines changed

2 files changed

+9
-2
lines changed

src/cache.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,8 @@ static void cache_evict_entries(git_cache *cache)
134134

135135
evict_count--;
136136
evicted_memory += evict->size;
137-
git_cached_obj_decref(evict);
138-
139137
git_oidmap_delete(cache->map, key);
138+
git_cached_obj_decref(evict);
140139
}
141140

142141
cache->used_memory -= evicted_memory;

tests/blame/simple.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ void test_blame_simple__trivial_libgit2(void)
203203
check_blame_hunk_index(g_repo, g_blame, 49, 60, 1, 0, "d12299fe", "src/git.h");
204204
}
205205

206+
/* This was leading to segfaults on some systems during cache eviction. */
207+
void test_blame_simple__trivial_libgit2_under_cache_pressure(void)
208+
{
209+
ssize_t old_max_storage = git_cache__max_storage;
210+
git_cache__max_storage = 1024 * 1024;
211+
test_blame_simple__trivial_libgit2();
212+
git_cache__max_storage = old_max_storage;
213+
}
206214

207215
/*
208216
* $ git blame -n b.txt -L 8

0 commit comments

Comments
 (0)