Error CONTEXT lines, and a fix for a crash in nested error propagation#23
Merged
Conversation
Errors, warnings, and notices raised while PL/php code runs now carry
a CONTEXT line, like every other PL:
ERROR: division by zero at line 7
CONTEXT: PL/php function "div_by_zero"
via error_context_stack callbacks in the call handler ("PL/php
function \"name\""), the inline handler ("PL/php anonymous code
block"), and the validator ("compilation of PL/php function").
Exercising nested calls surfaced a longstanding crasher, fixed here:
a PostgreSQL error longjmp'ing out of a handler's zend_try block
skips zend_end_try(), leaving EG(bailout) pointing into the dying
stack frame. When one PL/php function called another via SPI and the
inner one failed, execution continued in the outer function with the
stale bailout environment; its eventual bailout (an uncaught error)
longjmp'ed into garbage -- glibc's fortify checks abort with "longjmp
causes uninitialized stack frame", and without them it is arbitrary
stack corruption. Save EG(bailout) before each handler's zend_try
and restore it in the PG_CATCH that re-throws, in all three entry
points. Present since the zend_try blocks were introduced; the test
suite never exercised an error crossing nested calls.
Also guard the "at line N" suffix against double-appending, which the
nested flow made visible.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every existing error and notice in the expected files gains its CONTEXT line -- including the base_1/trigger_1 alternates that absorb older servers' message wording. New pgerror cases cover an uncaught error crossing nested calls (the former crasher), session health afterwards, and catching the nested failure as PgError in the outer function. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
Two things, found together — full suite green on PG 11–18 +
jsonb_plphpin the container sweep.CONTEXT lines (the feature)
Every message raised while PL/php code runs now carries context, like the other PLs:
with variants for anonymous blocks (
PL/php anonymous code block) and validation (compilation of PL/php function "f"), via standarderror_context_stackcallbacks in the three entry points. Every expected file gains its CONTEXT lines, including thebase_1/trigger_1alternates andjsonb_plphp.The crash (the discovery)
Writing the nested-call test surfaced a latent backend crasher, present since the
zend_tryblocks were introduced and reproducible on 2.3.0: a PostgreSQL error longjmp'ing out of a handler'szend_tryskipszend_end_try(), leavingEG(bailout)pointing into a dead stack frame. When one PL/php function calls another via SPI and the inner one fails, the outer function keeps running with the stale bailout environment — its eventual uncaught error longjmps into garbage (glibc fortify aborts with "longjmp causes uninitialized stack frame"; without fortify it's stack corruption).Fix: save
EG(bailout)before each handler'szend_tryand restore it in thePG_CATCHthat re-throws — all three entry points. Newpgerrorcases pin the formerly-crashing flow: uncaught nested error, session health afterwards, and catching the nested failure asPgErrorin the outer function.Also fixes the
at line Nsuffix double-appending the nested flow exposed.🤖 Generated with Claude Code