split-index: BUG() when cache entry refers to non-existing shared entry
authorSZEDER Gábor <szeder.dev@gmail.com>
Thu, 11 Oct 2018 09:53:57 +0000 (11:53 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 11 Oct 2018 22:23:29 +0000 (07:23 +0900)
When the split index feature is in use, then a cache entry is:

- either only present in the split index, in which case its 'index'
field must be 0,

- or it should refer to an existing entry in the shared index, i.e.
the 'index' field can't be greater than the size of the shared
index.

If a cache entry were to refer to a non-existing entry in the shared
index, then that's a sign of something being wrong in the index state,
either as a result of a bug in dealing with the split/shared index
entries, or perhaps a (potentially unrelated) memory corruption issue.

prepare_to_write_split_index() already has a condition to catch cache
entries with such bogus 'index' field, but instead of calling BUG() it
just sets cache entry's 'index = 0', and the entry will then be
written to the new split index.

Don't write a new index file from bogus index state, and call BUG()
upon encountering an cache entry referring to a non-existing shared
index entry.

Running the test suite repeatedly with 'GIT_TEST_SPLIT_INDEX=yes'
doesn't trigger this condition.

Signed-off-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
split-index.c
index 875f53880231b93c0e41bfbf625dd605a8196477..5820412dc5203032d1247575d79c6107a163295a 100644 (file)
@@ -254,8 +254,8 @@ void prepare_to_write_split_index(struct index_state *istate)
                                continue;
                        }
                        if (ce->index > si->base->cache_nr) {
-                               ce->index = 0;
-                               continue;
+                               BUG("ce refers to a shared ce at %d, which is beyond the shared index size %d",
+                                   ce->index, si->base->cache_nr);
                        }
                        ce->ce_flags |= CE_MATCHED; /* or "shared" */
                        base = si->base->cache[ce->index - 1];