[PATCH v12 13/13] fsmonitor: fix split-index bitmap bounds in tweak_fsmonitor()
STALE169d
From: Paul Tarjan via GitGitGadget <hidden>
Date: 2026-03-31 06:19:52
Subsystem:
the rest · Maintainer:
Linus Torvalds
From: Paul Tarjan <redacted>
When GIT_TEST_SPLIT_INDEX=yes is set and the fsmonitor daemon is
active, tweak_fsmonitor() can hit a BUG() assertion:
BUG: fsmonitor.c:27: fsmonitor_dirty has more entries than the index (2 > 0)
The fsmonitor_dirty EWAH bitmap may reference positions from a
previous index state. With split-index, cache_nr can be smaller
than the bitmap expects because entries have not been merged yet.
This is related to the issue that 05f28e4b3c (scalar: use
index.skipHash=true for performance, 2025-06-04) worked around by
disabling GIT_TEST_SPLIT_INDEX in t9210, noting "the issue should
be resolved in a series focused on the split index." This fixes
the fsmonitor bitmap side; the index.skipHash interaction remains.
Two places hit this:
- tweak_fsmonitor() calls assert_index_minimum() without the
!istate->split_index guard that the read path (line 98) and
write path (line 128) already have. Add the same guard.
- fsmonitor_ewah_callback() unconditionally asserts and then
accesses istate->cache[pos], which is out of bounds with
split-index. Replace the assertion with a bounds check that
silently skips positions beyond cache_nr.
Signed-off-by: Paul Tarjan <redacted>
---
fsmonitor.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fsmonitor.c b/fsmonitor.c
index d07dc18967..5e5a4fadea 100644
--- a/fsmonitor.c
+++ b/fsmonitor.c@@ -33,7 +33,8 @@ static void fsmonitor_ewah_callback(size_t pos, void *is) struct index_state *istate = (struct index_state *)is; struct cache_entry *ce; - assert_index_minimum(istate, pos + 1); + if (pos >= istate->cache_nr) + return; ce = istate->cache[pos]; ce->ce_flags &= ~CE_FSMONITOR_VALID;
@@ -805,7 +806,8 @@ void tweak_fsmonitor(struct index_state *istate) } /* Mark all previously saved entries as dirty */ - assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size); + if (!istate->split_index) + assert_index_minimum(istate, istate->fsmonitor_dirty->bit_size); ewah_each_bit(istate->fsmonitor_dirty, fsmonitor_ewah_callback, istate); refresh_fsmonitor(istate);
--
gitgitgadget