Skip to content

[bug] Fix bound BitVectorRangeIterator range_start to _end in JitAllocator#523

Open
puzpuzpuz wants to merge 1 commit into
asmjit:masterfrom
questdb:fix-jit-allocator-search-end-bounds
Open

[bug] Fix bound BitVectorRangeIterator range_start to _end in JitAllocator#523
puzpuzpuz wants to merge 1 commit into
asmjit:masterfrom
questdb:fix-jit-allocator-search-end-bounds

Conversation

@puzpuzpuz

Copy link
Copy Markdown

BitVectorRangeIterator::next_range() did not clamp *range_start against _end. The iterator's init() only masks bits before start, so the underlying BitWord can carry free bits past end. When ctz picked such a bit, the caller would compute range_size = range_end - range_start as size_t (range_end gets clamped to _end), the subtraction would underflow to a huge value, and a range that lies entirely past the search region would be accepted.

Inside JitAllocator::alloc this produced an area_index outside the block: the returned Span reported its requested size even though the underlying memory ran past the block boundary into unmapped pages. QuestDB caught this as a SIGSEGV inside JitRuntime::_add's memcpy: a production core dump shows a block with _area_size=4096, _search_end=4083 and 3 free bits at the tail (areas 4093-4095). A 7-area request let the iterator pick range_start=4093 with range_end clamped to 4083, _area_used over-incremented by 4, the Span claimed 448 bytes when only 192 were valid, and the JIT runtime memcpy walked off the end of the block.

The fix adds a single bound check: if *range_start >= _end after the ctz, the iterator reports end-of-iteration. Two regression tests cover the path:

  • test_bit_vector_range_iterator_bounds() exercises the iterator directly with two hand-crafted bitmaps (same-word and multi-word search regions). Without the fix EXPECT_LT(range_start, end) fails on the first iterator call.

  • test_jit_allocator_search_end_bounds() drives JitAllocator into the production state (area_used = area_size - 14, free bits both inside the search range and at the tail past _search_end). With the bug the alloc trips the existing offset <= block_size - size assertion at line ~999; with the fix the search reports no fit and a fresh block is allocated.

@puzpuzpuz puzpuzpuz changed the title fix(jit_allocator): bound BitVectorRangeIterator range_start to _end [bug] Fix bound BitVectorRangeIterator range_start to _end in JitAllocator May 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant