Conversation
pdo_dblib_stmt_execute() published &S->err to the DBPROCESS through dbsetuserdata(), but FreeTDS keeps handing that pointer to the error and message handlers for the life of the connection, long after the statement is freed. A statement cannot retract it from its own destructor, since a GC cycle can free the connection handle first, so every function that hands H->link to libdblib now installs the pdo_dblib_err it owns. get_column_meta() also stops allocating return_value before the dbcoltypeinfo() check that can fail, which the new test would otherwise leak. Fixes phpGH-23741
iliaal
force-pushed
the
fix/gh-23741-dblib-stmt-err-lifetime
branch
from
September 17, 2026 23:08
a1eb33e to
32d1793
Compare
Owner
Author
|
Submitted upstream as php#23751. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
pdo_dblib_stmt_execute()publishes the statement's error struct to the DBPROCESS withdbsetuserdata(), and FreeTDS keeps handing that pointer to the message handlers for the rest of the connection's life, long after the statement is freed. A statement cannot take the pointer back from its own destructor, since a GC cycle can free the connection handle first, so every function that hands the link to libdblib now installs the error struct it owns.A failing beginTransaction(), commit(), rollBack() or lastInsertId() now reports its error; the stale SQLSTATE write previously left dbh->error_code untouched, so PDO stayed silent. rollBack() returns false in the reporter's script for an unrelated reason, SQL Server having already rolled the batch back itself, so the test does not assert its return value.