Skip to content

Evict finalized statement pointers to stop SQL aliasing across pointer reuse#4

Open
karans4 wants to merge 1 commit into
masterfrom
karan/finalize-eviction
Open

Evict finalized statement pointers to stop SQL aliasing across pointer reuse#4
karans4 wants to merge 1 commit into
masterfrom
karan/finalize-eviction

Conversation

@karans4

@karans4 karans4 commented Jul 10, 2026

Copy link
Copy Markdown

Statement pointers alias across finalize. sqlite3_finalize returns the stmt to the allocator, and a later prepare routinely gets the same address back, but neither side ever forgets the dead pointer:

  • sqlByStmt in probes/sqlite.js keeps mapping the reused pointer to the dead statement's SQL, so the new statement's executions show up wearing the old statement's text, with the new binds and latencies attached to it.
  • the known LRU in the BPF object still contains the pointer, which suppresses zSql recovery for the new statement on x86-64, so it can never self-correct.

This is easy to hit: the first prepare on a fresh connection triggers SQLite's lazy schema load, which nests sqlite3_exec -> sqlite3_prepare_v2 inside the outer prepare and clobbers the single per-thread scratch slot (the documented, accepted failure mode in sqlite.bpf.c). The header comment says the cost is one statement shown as «unknown» that self-corrects. Without eviction the actual cost is wrong SQL on unrelated statements: in a live run I watched a parameterized SELECT render as COMMIT with its binds attached (raw event dump confirms the missed outer PREPARE followed by BIND/STEP on a reused pointer).

Fix: hook sqlite3_finalize (entry-only, no pairing, so none of the scratch-slot/uretprobe concerns apply), delete the pointer from known in the kernel, and emit EV_FINALIZE so userspace flushes any lingering in-flight execution and drops its sqlByStmt entry. After the patch the same repro shows the missed statement as «unknown» with its own binds, which is exactly the failure mode the header comment promises, and it now truly self-corrects on both architectures.

Tested on Debian 13 (arm64, kernel 6.12, yeet master): make builds clean, FINALIZE events flow in the raw dump mode, and the TUI no longer attributes binds to dead statements' SQL. Touches the same region of probes/sqlite.js as #2; happy to rebase whichever lands second.

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