mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-28 07:03:20 +08:00
fix(sqlite_writer): skip index cells that exceed a single page
write_index_btree() flushed the page buffer whenever the next cell didn't fit, on the assumption that a freshly-initialised page would always accept any cell. That invariant fails for index cells whose payload (qualified_name, file_path, etc.) is larger than a full SQLite page — after the flush, pb_cell_fits() is still false but the code calls pb_add_cell() anyway. The subsequent content_offset underflow corrupts the page header and the next write triggers SIGBUS on large repos (observed on a Ruby codebase with ~215K nodes). Re-check pb_cell_fits() after the flush and continue past cells that still don't fit. Index entries whose keys exceed a full page can't be stored and are not expected to survive the writer anyway — the rest of the index is correctly preserved and the indexer no longer crashes. Record overflow pages (#175) already covers the record-btree side of this same shape of bug.
This commit is contained in:
@@ -1213,9 +1213,16 @@ static uint32_t write_index_btree(FILE *fp, uint32_t *next_page, uint8_t **cells
|
||||
pb_init(&pb, fp, *next_page, true);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!pb_cell_fits(&pb, cell_lens[i]) && pb.cell_count > 0) {
|
||||
if (!pb_promote_and_flush(&pb, cells, cell_lens, i - SKIP_ONE)) {
|
||||
return 0;
|
||||
if (!pb_cell_fits(&pb, cell_lens[i])) {
|
||||
if (pb.cell_count > 0) {
|
||||
if (!pb_promote_and_flush(&pb, cells, cell_lens, i - SKIP_ONE)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// After flush, check if the cell still doesn't fit on an empty page.
|
||||
// Index cells larger than a full page can never be stored; skip them.
|
||||
if (!pb_cell_fits(&pb, cell_lens[i])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pb_add_cell(&pb, cells[i], cell_lens[i]);
|
||||
|
||||
Reference in New Issue
Block a user