Skip to content

Fix SQLite B-tree iterator#5

Merged
SlugFiller merged 1 commit intoSlugFiller:masterfrom
davispuh:sqlite
Apr 19, 2026
Merged

Fix SQLite B-tree iterator#5
SlugFiller merged 1 commit intoSlugFiller:masterfrom
davispuh:sqlite

Conversation

@davispuh
Copy link
Copy Markdown
Contributor

Without this rows are being missed. This fixes #1.
Written by Claude but I tested that it now indeed works for me.

Bug Found: Missing Right-Most Pointer in Interior B-Tree Pages

The bug is in #iterateBTree. SQLite's B-tree interior pages (types 2 and 5) store N child pointers inside cells, plus one extra "right-most pointer" in the page header at offset +8. The current code iterates all cells but never follows this right-most pointer, so the entire rightmost subtree is silently skipped — causing rows to be missed for any table whose B-tree has interior pages.

Why this happens

SQLite interior B-tree pages have this structure:

Header (12 bytes for interior pages):
  +0  page type (1 byte)
  +1  first freeblock offset (2 bytes)
  +3  cell count (2 bytes)
  +5  cell content area offset (2 bytes)
  +7  fragmented free bytes (1 byte)
  +8  ► RIGHT-MOST POINTER (4 bytes)  ← was never read
  +12 cell pointer array starts here

Each cell in an interior page holds a left child pointer + a key. The right-most child (which contains all rows with keys greater than the last cell's key) is only stored in the header, not in any cell. For a table with N interior-page children, the loop visits N-1 of them and silently drops the last one — which can represent a large fraction of the rows.

Without this rows are being missed.
Fixes SlugFiller#1
Copilot AI review requested due to automatic review settings April 17, 2026 20:26
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes SQLite B-tree traversal in SQLiteDatabase.#iterateBTree so that interior B-tree pages (types 2 and 5) also follow the page-header “right-most pointer”, preventing the rightmost subtree (and its rows) from being skipped.

Changes:

  • After iterating all interior-page cells, additionally recurse into the interior page’s right-most child pointer at header offset +8.
  • Ensures full table/index scans don’t miss rows that live in the rightmost branch of interior nodes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@SlugFiller SlugFiller merged commit ec39041 into SlugFiller:master Apr 19, 2026
3 of 4 checks passed
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.

Could not find handle to decrypt synthetic password blob on Android 15.0

3 participants