mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Fix list-manipulation bug in WITH RECURSIVE processing.
makeDependencyGraphWalker and checkWellFormedRecursionWalker
thought they could hold onto a pointer to a list's first
cons cell while the list was modified by recursive calls.
That was okay when the cons cell was actually separately
palloc'd ... but since commit 1cff1b95a
, it's quite unsafe,
leading to core dumps or incorrect complaints of faulty
WITH nesting.
In the field this'd require at least a seven-deep WITH nest
to cause an issue, but enabling DEBUG_LIST_MEMORY_USAGE
allows the bug to be seen with lesser nesting depths.
Per bug #16801 from Alexander Lakhin. Back-patch to v13.
Michael Paquier and Tom Lane
Discussion: https://postgr.es/m/16801-393c7922143eaa4d@postgresql.org
This commit is contained in:
@ -537,15 +537,15 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
|
||||
* In the non-RECURSIVE case, query names are visible to the
|
||||
* WITH items after them and to the main query.
|
||||
*/
|
||||
ListCell *cell1;
|
||||
|
||||
cstate->innerwiths = lcons(NIL, cstate->innerwiths);
|
||||
cell1 = list_head(cstate->innerwiths);
|
||||
foreach(lc, stmt->withClause->ctes)
|
||||
{
|
||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
|
||||
ListCell *cell1;
|
||||
|
||||
(void) makeDependencyGraphWalker(cte->ctequery, cstate);
|
||||
/* note that recursion could mutate innerwiths list */
|
||||
cell1 = list_head(cstate->innerwiths);
|
||||
lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
|
||||
}
|
||||
(void) raw_expression_tree_walker(node,
|
||||
@ -813,15 +813,15 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
|
||||
* In the non-RECURSIVE case, query names are visible to the
|
||||
* WITH items after them and to the main query.
|
||||
*/
|
||||
ListCell *cell1;
|
||||
|
||||
cstate->innerwiths = lcons(NIL, cstate->innerwiths);
|
||||
cell1 = list_head(cstate->innerwiths);
|
||||
foreach(lc, stmt->withClause->ctes)
|
||||
{
|
||||
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
|
||||
ListCell *cell1;
|
||||
|
||||
(void) checkWellFormedRecursionWalker(cte->ctequery, cstate);
|
||||
/* note that recursion could mutate innerwiths list */
|
||||
cell1 = list_head(cstate->innerwiths);
|
||||
lfirst(cell1) = lappend((List *) lfirst(cell1), cte);
|
||||
}
|
||||
checkWellFormedSelectStmt(stmt, cstate);
|
||||
|
Reference in New Issue
Block a user