Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit80ca846

Browse files
committed
Fix list-manipulation bug in WITH RECURSIVE processing.
makeDependencyGraphWalker and checkWellFormedRecursionWalkerthought they could hold onto a pointer to a list's firstcons cell while the list was modified by recursive calls.That was okay when the cons cell was actually separatelypalloc'd ... but since commit1cff1b9, it's quite unsafe,leading to core dumps or incorrect complaints of faultyWITH nesting.In the field this'd require at least a seven-deep WITH nestto cause an issue, but enabling DEBUG_LIST_MEMORY_USAGEallows the bug to be seen with lesser nesting depths.Per bug #16801 from Alexander Lakhin. Back-patch to v13.Michael Paquier and Tom LaneDiscussion:https://postgr.es/m/16801-393c7922143eaa4d@postgresql.org
1 parent2376361 commit80ca846

File tree

3 files changed

+109
-6
lines changed

3 files changed

+109
-6
lines changed

‎src/backend/parser/parse_cte.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -730,15 +730,15 @@ makeDependencyGraphWalker(Node *node, CteState *cstate)
730730
* In the non-RECURSIVE case, query names are visible to the
731731
* WITH items after them and to the main query.
732732
*/
733-
ListCell*cell1;
734-
735733
cstate->innerwiths=lcons(NIL,cstate->innerwiths);
736-
cell1=list_head(cstate->innerwiths);
737734
foreach(lc,stmt->withClause->ctes)
738735
{
739736
CommonTableExpr*cte= (CommonTableExpr*)lfirst(lc);
737+
ListCell*cell1;
740738

741739
(void)makeDependencyGraphWalker(cte->ctequery,cstate);
740+
/* note that recursion could mutate innerwiths list */
741+
cell1=list_head(cstate->innerwiths);
742742
lfirst(cell1)=lappend((List*)lfirst(cell1),cte);
743743
}
744744
(void)raw_expression_tree_walker(node,
@@ -1006,15 +1006,15 @@ checkWellFormedRecursionWalker(Node *node, CteState *cstate)
10061006
* In the non-RECURSIVE case, query names are visible to the
10071007
* WITH items after them and to the main query.
10081008
*/
1009-
ListCell*cell1;
1010-
10111009
cstate->innerwiths=lcons(NIL,cstate->innerwiths);
1012-
cell1=list_head(cstate->innerwiths);
10131010
foreach(lc,stmt->withClause->ctes)
10141011
{
10151012
CommonTableExpr*cte= (CommonTableExpr*)lfirst(lc);
1013+
ListCell*cell1;
10161014

10171015
(void)checkWellFormedRecursionWalker(cte->ctequery,cstate);
1016+
/* note that recursion could mutate innerwiths list */
1017+
cell1=list_head(cstate->innerwiths);
10181018
lfirst(cell1)=lappend((List*)lfirst(cell1),cte);
10191019
}
10201020
checkWellFormedSelectStmt(stmt,cstate);

‎src/test/regress/expected/with.out

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,65 @@ ERROR: operator does not exist: text + integer
176176
LINE 4: SELECT n+1 FROM t WHERE n < 10
177177
^
178178
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
179+
-- Deeply nested WITH caused a list-munging problem in v13
180+
-- Detection of cross-references and self-references
181+
WITH RECURSIVE w1(c1) AS
182+
(WITH w2(c2) AS
183+
(WITH w3(c3) AS
184+
(WITH w4(c4) AS
185+
(WITH w5(c5) AS
186+
(WITH RECURSIVE w6(c6) AS
187+
(WITH w6(c6) AS
188+
(WITH w8(c8) AS
189+
(SELECT 1)
190+
SELECT * FROM w8)
191+
SELECT * FROM w6)
192+
SELECT * FROM w6)
193+
SELECT * FROM w5)
194+
SELECT * FROM w4)
195+
SELECT * FROM w3)
196+
SELECT * FROM w2)
197+
SELECT * FROM w1;
198+
c1
199+
----
200+
1
201+
(1 row)
202+
203+
-- Detection of invalid self-references
204+
WITH RECURSIVE outermost(x) AS (
205+
SELECT 1
206+
UNION (WITH innermost1 AS (
207+
SELECT 2
208+
UNION (WITH innermost2 AS (
209+
SELECT 3
210+
UNION (WITH innermost3 AS (
211+
SELECT 4
212+
UNION (WITH innermost4 AS (
213+
SELECT 5
214+
UNION (WITH innermost5 AS (
215+
SELECT 6
216+
UNION (WITH innermost6 AS
217+
(SELECT 7)
218+
SELECT * FROM innermost6))
219+
SELECT * FROM innermost5))
220+
SELECT * FROM innermost4))
221+
SELECT * FROM innermost3))
222+
SELECT * FROM innermost2))
223+
SELECT * FROM outermost
224+
UNION SELECT * FROM innermost1)
225+
)
226+
SELECT * FROM outermost ORDER BY 1;
227+
x
228+
---
229+
1
230+
2
231+
3
232+
4
233+
5
234+
6
235+
7
236+
(7 rows)
237+
179238
--
180239
-- Some examples with a tree
181240
--

‎src/test/regress/sql/with.sql

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,50 @@ UNION ALL
9595
)
9696
SELECT n, pg_typeof(n)FROM t;
9797

98+
-- Deeply nested WITH caused a list-munging problem in v13
99+
-- Detection of cross-references and self-references
100+
WITH RECURSIVE w1(c1)AS
101+
(WITH w2(c2)AS
102+
(WITH w3(c3)AS
103+
(WITH w4(c4)AS
104+
(WITH w5(c5)AS
105+
(WITH RECURSIVE w6(c6)AS
106+
(WITH w6(c6)AS
107+
(WITH w8(c8)AS
108+
(SELECT1)
109+
SELECT*FROM w8)
110+
SELECT*FROM w6)
111+
SELECT*FROM w6)
112+
SELECT*FROM w5)
113+
SELECT*FROM w4)
114+
SELECT*FROM w3)
115+
SELECT*FROM w2)
116+
SELECT*FROM w1;
117+
-- Detection of invalid self-references
118+
WITH RECURSIVE outermost(x)AS (
119+
SELECT1
120+
UNION (WITH innermost1AS (
121+
SELECT2
122+
UNION (WITH innermost2AS (
123+
SELECT3
124+
UNION (WITH innermost3AS (
125+
SELECT4
126+
UNION (WITH innermost4AS (
127+
SELECT5
128+
UNION (WITH innermost5AS (
129+
SELECT6
130+
UNION (WITH innermost6AS
131+
(SELECT7)
132+
SELECT*FROM innermost6))
133+
SELECT*FROM innermost5))
134+
SELECT*FROM innermost4))
135+
SELECT*FROM innermost3))
136+
SELECT*FROM innermost2))
137+
SELECT*FROM outermost
138+
UNIONSELECT*FROM innermost1)
139+
)
140+
SELECT*FROM outermostORDER BY1;
141+
98142
--
99143
-- Some examples with a tree
100144
--

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp