Skip to content

Fix GH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction.#21870

Open
devnexen wants to merge 3 commits intophp:PHP-8.4from
devnexen:gh21869
Open

Fix GH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction.#21870
devnexen wants to merge 3 commits intophp:PHP-8.4from
devnexen:gh21869

Conversation

@devnexen
Copy link
Copy Markdown
Member

@devnexen devnexen commented Apr 24, 2026

On libpq < 17 the raw DEALLOCATE can fail (e.g. Aurora DSQL rejects it),
which aborts the user's transaction and turns the next COMMIT into a
silent ROLLBACK. Wrap it in a SAVEPOINT so a failure is contained, and
skip it when the transaction is already aborted or the connection is gone.

…closing transaction.

On libpq < 17 the raw DEALLOCATE can fail (e.g. Aurora DSQL rejects it),
which aborts the user's transaction and turns the next COMMIT into a
silent ROLLBACK. Wrap it in a SAVEPOINT so a failure is contained, and
skip it when the transaction is already aborted or the connection is gone.
@devnexen devnexen changed the title ext/pdo_pgsql: add failing regression test for GH-21869. @devnexen Fix phpGH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction. Apr 24, 2026
@devnexen devnexen changed the title @devnexen Fix phpGH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction. Fix phpGH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction. Apr 24, 2026
@devnexen devnexen changed the title Fix phpGH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction. Fix GH-21869: pdo_pgsql DEALLOCATE in destructor can poison the enclosing transaction. Apr 24, 2026
@devnexen devnexen marked this pull request as ready for review April 25, 2026 05:47
@devnexen devnexen requested a review from SakiTakamachi as a code owner April 25, 2026 05:47
Comment thread ext/pdo_pgsql/pgsql_statement.c Outdated
Comment on lines +91 to +92
* would poison the transaction (GH-21869); on any server the server
* frees the prepared statement when the transaction ends. */
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I believe the server will hang on to the prepared statement until the connection is dropped, so this could leak prepared statements

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Right, session-scoped not transaction-scoped, comment fixed. Skipping is still the lesser evil since on Aurora DSQL with libpq < 17, DEALLOCATE inside a tx silently
turns COMMIT into ROLLBACK. The leak is bounded to session lifetime. Lazy DEALLOCATE on next idle query as a follow-up if persistent connections make it worth the
complexity.


if (tstatus == PQTRANS_IDLE) {
spprintf(&q, 0, "DEALLOCATE %s", S->stmt_name);
res = PQexec(H->server, q);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think if this errors it should get bubbled up

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Dtor path, no return channel to userland. The pre-patch code already discarded the result the same way. Surfacing dtor cleanup failures across pdo_pgsql might be worth
doing, but as a separate PR.

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.

pdo_pgsql: DEALLOCATE on statement destruct silently aborts enclosing transaction if it fails

2 participants