summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
authorJameson Miller <jamill@microsoft.com>2018-07-02 19:49:39 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-07-03 17:58:27 (GMT)
commit8616a2d0cb57865540f1c00ac2e5385a6cc5d84e (patch)
treeaa15c9800bf6305fd1dd5491b3abb2a591b1d089 /read-cache.c
parent8e72d67529ba0adfb6f7d24a21e909c2a1e1d069 (diff)
downloadgit-8616a2d0cb57865540f1c00ac2e5385a6cc5d84e.zip
git-8616a2d0cb57865540f1c00ac2e5385a6cc5d84e.tar.gz
git-8616a2d0cb57865540f1c00ac2e5385a6cc5d84e.tar.bz2
block alloc: add validations around cache_entry lifecyle
Add an option (controlled by an environment variable) perform extra validations on mem_pool allocated cache entries. When set: 1) Invalidate cache_entry memory when discarding cache_entry. 2) When discarding index_state struct, verify that all cache_entries were allocated from expected mem_pool. 3) When discarding mem_pools, invalidate mem_pool memory. This should provide extra checks that mem_pools and their allocated cache_entries are being used as expected. Signed-off-by: Jameson Miller <jamill@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c55
1 files changed, 53 insertions, 2 deletions
diff --git a/read-cache.c b/read-cache.c
index b073696..fd67e2e 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -2050,8 +2050,10 @@ int discard_index(struct index_state *istate)
* Cache entries in istate->cache[] should have been allocated
* from the memory pool associated with this index, or from an
* associated split_index. There is no need to free individual
- * cache entries.
+ * cache entries. validate_cache_entries can detect when this
+ * assertion does not hold.
*/
+ validate_cache_entries(istate);
resolve_undo_clear_index(istate);
istate->cache_nr = 0;
@@ -2068,13 +2070,45 @@ int discard_index(struct index_state *istate)
istate->untracked = NULL;
if (istate->ce_mem_pool) {
- mem_pool_discard(istate->ce_mem_pool);
+ mem_pool_discard(istate->ce_mem_pool, should_validate_cache_entries());
istate->ce_mem_pool = NULL;
}
return 0;
}
+/*
+ * Validate the cache entries of this index.
+ * All cache entries associated with this index
+ * should have been allocated by the memory pool
+ * associated with this index, or by a referenced
+ * split index.
+ */
+void validate_cache_entries(const struct index_state *istate)
+{
+ int i;
+
+ if (!should_validate_cache_entries() ||!istate || !istate->initialized)
+ return;
+
+ for (i = 0; i < istate->cache_nr; i++) {
+ if (!istate) {
+ die("internal error: cache entry is not allocated from expected memory pool");
+ } else if (!istate->ce_mem_pool ||
+ !mem_pool_contains(istate->ce_mem_pool, istate->cache[i])) {
+ if (!istate->split_index ||
+ !istate->split_index->base ||
+ !istate->split_index->base->ce_mem_pool ||
+ !mem_pool_contains(istate->split_index->base->ce_mem_pool, istate->cache[i])) {
+ die("internal error: cache entry is not allocated from expected memory pool");
+ }
+ }
+ }
+
+ if (istate->split_index)
+ validate_cache_entries(istate->split_index->base);
+}
+
int unmerged_index(const struct index_state *istate)
{
int i;
@@ -2878,8 +2912,25 @@ struct cache_entry *dup_cache_entry(const struct cache_entry *ce,
void discard_cache_entry(struct cache_entry *ce)
{
+ if (ce && should_validate_cache_entries())
+ memset(ce, 0xCD, cache_entry_size(ce->ce_namelen));
+
if (ce && ce->mem_pool_allocated)
return;
free(ce);
}
+
+int should_validate_cache_entries(void)
+{
+ static int validate_index_cache_entries = -1;
+
+ if (validate_index_cache_entries < 0) {
+ if (getenv("GIT_TEST_VALIDATE_INDEX_CACHE_ENTRIES"))
+ validate_index_cache_entries = 1;
+ else
+ validate_index_cache_entries = 0;
+ }
+
+ return validate_index_cache_entries;
+}