Skip to content

Fix GH-23728: crash when a callback destroys the statement being executed - #23736

Open
iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/gh-23728-stmt-close-during-step
Open

iliaal wants to merge 1 commit into
php:PHP-8.4from
iliaal:fix/gh-23728-stmt-close-during-step

Conversation

@iliaal

@iliaal iliaal commented Sep 17, 2026

Copy link
Copy Markdown
Member

SQLite3Stmt::close() and SQLite3Result::finalize() reach sqlite3_finalize() through the database free list, and SQLite3Stmt::reset(), SQLite3Result::reset() and a sibling result's destructor reach sqlite3_reset(). From a userland function, aggregate or collation callback, either destroys the statement sqlite3_step() is executing. Tracking per statement whether it is being stepped, throwing from the four methods and skipping the reset in the destructor, leaves the statement usable once the query finishes. The per-database in_callback counter GH-23650 added for SQLite3::close() is too coarse here, since finalizing an unrelated statement while another one steps is safe and keeps working, and sqlite3_stmt_busy() would reject a close after a partial fetch outside any callback.

Fixes #23728

…xecuted

SQLite3Stmt::close() and SQLite3Result::finalize() reach sqlite3_finalize()
through the database free list, and SQLite3Stmt::reset(), SQLite3Result::
reset() and a sibling result's destructor reach sqlite3_reset(). Called from
a userland function, aggregate or collation callback, either destroys the
statement sqlite3_step() is executing, so the step returns into freed memory
or the next one walks a reset VDBE. Track per statement whether it is being
stepped, throw from the four methods while it is, and skip the reset in the
result destructor, which cannot throw. phpGH-23650 added a per-database
in_callback counter for SQLite3::close(), which destroys every statement on
the connection, but that counter is too coarse here: finalizing an unrelated
statement while another one steps is safe and keeps working.
SQLite3Stmt::clear() is left alone, sqlite3_clear_bindings() mid-step is
tolerated.

Fixes phpGH-23728
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant