Problem
Explorer.removeFile (src/explore.zig:1497) cleans dep_graph, symbol_index, contents, the word and trigram indexes, then frees the outlines key (src/explore.zig:1514) — but never removes the file's skip_trigram_files entry, whose key aliases that freed outlines key. Files enter skip_trigram_files via outline-only indexing (#507) and the skip_trigram path. After a delete, the tier-3 search scan iterates the dangling path and hands it to readContentForSearch — a freed-memory read (UB); with reused memory, an arbitrary string used as a file path.
Failing Test
test_explore.zig — fails on current release tip (count stays 1):
test "issue-587: removeFile drops the path from skip_trigram_files" {
var explorer = Explorer.init(testing.allocator, Explorer.DEFAULT_CONTENT_CACHE_CAPACITY);
defer explorer.deinit();
// Outline-only indexing registers the file in skip_trigram_files (#507).
try explorer.indexFileOutlineOnly("src/gone.zig", "pub fn ghostFn() void {}\n");
try testing.expectEqual(@as(usize, 1), explorer.skip_trigram_files.count());
explorer.removeFile("src/gone.zig");
try testing.expectEqual(@as(usize, 0), explorer.skip_trigram_files.count());
}
Expected
After removeFile, the path is absent from every Explorer-side structure; no map retains a pointer into the freed outlines key.
Fix
_ = self.skip_trigram_files.remove(path); in Explorer.removeFile, before the outlines entry is freed (keys alias the outlines key, so removal — not freeing — is the correct cleanup, matching the commitParsedFileOwnedOutline re-index path at src/explore.zig:892).
Problem
Explorer.removeFile(src/explore.zig:1497) cleansdep_graph,symbol_index,contents, the word and trigram indexes, then frees the outlines key (src/explore.zig:1514) — but never removes the file'sskip_trigram_filesentry, whose key aliases that freed outlines key. Files enterskip_trigram_filesvia outline-only indexing (#507) and theskip_trigrampath. After a delete, the tier-3 search scan iterates the dangling path and hands it toreadContentForSearch— a freed-memory read (UB); with reused memory, an arbitrary string used as a file path.Failing Test
test_explore.zig— fails on current release tip (count stays 1):Expected
After
removeFile, the path is absent from every Explorer-side structure; no map retains a pointer into the freed outlines key.Fix
_ = self.skip_trigram_files.remove(path);inExplorer.removeFile, before the outlines entry is freed (keys alias the outlines key, so removal — not freeing — is the correct cleanup, matching thecommitParsedFileOwnedOutlinere-index path at src/explore.zig:892).