1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Track nesting depth correctly when drilling down into RECORD Vars.

expandRecordVariable() failed to adjust the parse nesting structure
correctly when recursing to inspect an outer-level Var.  This could
result in assertion failures or core dumps in corner cases.

Likewise, get_name_for_var_field() failed to adjust the deparse
namespace stack correctly when recursing to inspect an outer-level
Var.  In this case the likely result was a "bogus varno" error
while deparsing a view.

Per bug #18077 from Jingzhou Fu.  Back-patch to all supported
branches.

Richard Guo, with some adjustments by me

Discussion: https://postgr.es/m/18077-b9db97c6e0ab45d8@postgresql.org
This commit is contained in:
Tom Lane
2023-09-15 17:01:26 -04:00
parent 59bc0dfe44
commit c5b7f791da
4 changed files with 122 additions and 24 deletions

View File

@ -1475,7 +1475,8 @@ ExpandRowReference(ParseState *pstate, Node *expr,
* drill down to find the ultimate defining expression and attempt to infer
* the tupdesc from it. We ereport if we can't determine the tupdesc.
*
* levelsup is an extra offset to interpret the Var's varlevelsup correctly.
* levelsup is an extra offset to interpret the Var's varlevelsup correctly
* when recursing. Outside callers should pass zero.
*/
TupleDesc
expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
@ -1563,11 +1564,17 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
/*
* Recurse into the sub-select to see what its Var refers
* to. We have to build an additional level of ParseState
* to keep in step with varlevelsup in the subselect.
* to keep in step with varlevelsup in the subselect;
* furthermore, the subquery RTE might be from an outer
* query level, in which case the ParseState for the
* subselect must have that outer level as parent.
*/
ParseState mypstate;
ParseState mypstate = {0};
Index levelsup;
MemSet(&mypstate, 0, sizeof(mypstate));
/* this loop must work, since GetRTEByRangeTablePosn did */
for (levelsup = 0; levelsup < netlevelsup; levelsup++)
pstate = pstate->parentParseState;
mypstate.parentParseState = pstate;
mypstate.p_rtable = rte->subquery->rtable;
/* don't bother filling the rest of the fake pstate */
@ -1618,12 +1625,11 @@ expandRecordVariable(ParseState *pstate, Var *var, int levelsup)
* Recurse into the CTE to see what its Var refers to. We
* have to build an additional level of ParseState to keep
* in step with varlevelsup in the CTE; furthermore it
* could be an outer CTE.
* could be an outer CTE (compare SUBQUERY case above).
*/
ParseState mypstate;
ParseState mypstate = {0};
Index levelsup;
MemSet(&mypstate, 0, sizeof(mypstate));
/* this loop must work, since GetCTEForRTE did */
for (levelsup = 0;
levelsup < rte->ctelevelsup + netlevelsup;