Skip to content

Direct SQLite writer crashes on oversized cells during indexing (repro with netty on macOS arm64) #187

@Yegezw

Description

@Yegezw

Summary

Indexing a large Java repo can crash codebase-memory-mcp in the direct SQLite page writer path when a single record exceeds what fits in one leaf page. On macOS arm64 this shows up as a late crash in free() / _szone_free, but AddressSanitizer points to an earlier stack-buffer-underflow in internal/cbm/sqlite_writer.c.

I reproduced this reliably while indexing the Netty repository.

Environment

  • codebase-memory-mcp version: 0.5.7
  • OS: macOS 15.6.1
  • Arch: arm64
  • MCP client: Codex CLI / CLI mode
  • Repro repo: https://github.com/netty/netty

Reproduction

  1. Clone netty
  2. Run:
codebase-memory-mcp cli index_repository '{"repo_path":"/path/to/netty"}'

Actual behavior

The process crashes near the end of indexing.

In normal runs the last logs are around:

  • pass.timing pass=configlink ...
  • then the process exits/crashes before indexing completes

macOS crash reports show an EXC_BREAKPOINT in _szone_free, which makes it look like a late free bug.

With ASan/UBSan, the root problem is clearer:

base version: git checkout 148d951e1a51bcc5f11f6cee97be2aa86141623d

internal/cbm/sqlite_writer.c:435:21: runtime error: index ... out of bounds for type 'uint8_t[65536]'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior internal/cbm/sqlite_writer.c:435:21

ERROR: AddressSanitizer: stack-buffer-underflow
WRITE of size 508794
    #1 pb_add_cell sqlite_writer.c:435
    #2 pb_add_table_cell_with_flush sqlite_writer.c:865
    #3 cbm_write_db sqlite_writer.c:1301
    #4 cbm_gbuf_dump_to_sqlite graph_buffer.c:1237

Root cause

pb_add_table_cell_with_flush() only flushes when the current page is non-empty and the next cell does not fit.

That misses the case where:

  • the current page is empty, and
  • the new cell itself is larger than the maximum capacity of a single leaf page

In that situation pb_add_cell() still runs and does:

  • pb->content_offset -= cell_len
  • memcpy(pb->page + pb->content_offset, cell, cell_len)

which underflows the page buffer and corrupts memory.

Expected behavior

One of these should happen instead:

  1. Detect oversized cells and return a clean error
  2. Fall back to a safer SQLite-backed dump path
  3. Implement proper overflow-page handling in the direct writer

At minimum, this should never corrupt memory or crash the process.

Notes

I was able to locally fix this by:

  • adding an explicit empty-page cell fits check in the writer
  • returning a dedicated error for oversized cells
  • falling back in the graph-buffer dump path to the normal SQLite store/backup writer when that error occurs

That made netty index successfully instead of crashing.

If useful, I can open a PR with the patch.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions