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

Commit34668c8

Browse files
committed
Fix use-of-already-freed-memory problem in EvalPlanQual processing.
Up to now, the "child" executor state trees generated for EvalPlanQualrechecks have simply shared the ResultRelInfo arrays used for the originalexecution tree. However, this leads to dangling-pointer problems, becauseExecInitModifyTable() is all too willing to scribble on some fields of theResultRelInfo(s) even when it's being run in one of those child trees.This trashes those fields from the perspective of the parent tree, becauseeven if the generated subtree is logically identical to what was in use inthe parent, it's in a memory context that will go away when we're donewith the child state tree.We do however want to share information in the direction from the parentdown to the children; in particular, fields such as es_instrument *must*be shared or we'll lose the stats arising from execution of the children.So the simplest fix is to make a copy of the parent's ResultRelInfo array,but not copy any fields back at end of child execution.Per report from Manuel Kniep. The added isolation test is based on hisexample. In an unpatched memory-clobber-enabled build it will reliablyfail with "ctid is NULL" errors in all branches back to 9.1, as aconsequence of junkfilter->jf_junkAttNo being overwritten with $7f7f.This test cannot be run as-is before that for lack of WITH syntax; butI have no doubt that some variant of this problem can arise in olderbranches, so apply the code change all the way back.
1 parent939f0fb commit34668c8

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

‎src/backend/executor/execMain.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,6 +2337,14 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
23372337
* the snapshot, rangetable, result-rel info, and external Param info.
23382338
* They need their own copies of local state, including a tuple table,
23392339
* es_param_exec_vals, etc.
2340+
*
2341+
* The ResultRelInfo array management is trickier than it looks. We
2342+
* create a fresh array for the child but copy all the content from the
2343+
* parent. This is because it's okay for the child to share any
2344+
* per-relation state the parent has already created --- but if the child
2345+
* sets up any ResultRelInfo fields, such as its own junkfilter, that
2346+
* state must *not* propagate back to the parent. (For one thing, the
2347+
* pointed-to data is in a memory context that won't last long enough.)
23402348
*/
23412349
estate->es_direction=ForwardScanDirection;
23422350
estate->es_snapshot=parentestate->es_snapshot;
@@ -2345,9 +2353,19 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
23452353
estate->es_plannedstmt=parentestate->es_plannedstmt;
23462354
estate->es_junkFilter=parentestate->es_junkFilter;
23472355
estate->es_output_cid=parentestate->es_output_cid;
2348-
estate->es_result_relations=parentestate->es_result_relations;
2349-
estate->es_num_result_relations=parentestate->es_num_result_relations;
2350-
estate->es_result_relation_info=parentestate->es_result_relation_info;
2356+
if (parentestate->es_num_result_relations>0)
2357+
{
2358+
intnumResultRelations=parentestate->es_num_result_relations;
2359+
ResultRelInfo*resultRelInfos;
2360+
2361+
resultRelInfos= (ResultRelInfo*)
2362+
palloc(numResultRelations*sizeof(ResultRelInfo));
2363+
memcpy(resultRelInfos,parentestate->es_result_relations,
2364+
numResultRelations*sizeof(ResultRelInfo));
2365+
estate->es_result_relations=resultRelInfos;
2366+
estate->es_num_result_relations=numResultRelations;
2367+
}
2368+
/* es_result_relation_info must NOT be copied */
23512369
/* es_trig_target_relations must NOT be copied */
23522370
estate->es_rowMarks=parentestate->es_rowMarks;
23532371
estate->es_top_eflags=parentestate->es_top_eflags;

‎src/test/isolation/expected/eval-plan-qual.out

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,35 @@ c2 (0,1) 1 0 0
7272
c3 (0,1) 2 0 0
7373
c3 (0,4) 2 1 0
7474
step c2: COMMIT;
75+
76+
starting permutation: writep2 returningp1 c1 c2
77+
step writep2: UPDATE p SET b = -b WHERE a = 1 AND c = 0;
78+
step returningp1:
79+
WITH u AS ( UPDATE p SET b = b WHERE a > 0 RETURNING * )
80+
SELECT * FROM u;
81+
<waiting ...>
82+
step c1: COMMIT;
83+
step returningp1: <... completed>
84+
a b c
85+
86+
1 0 0
87+
1 0 1
88+
1 0 2
89+
1 -1 0
90+
1 1 1
91+
1 1 2
92+
1 -2 0
93+
1 2 1
94+
1 2 2
95+
1 -3 0
96+
2 0 0
97+
2 0 1
98+
2 0 2
99+
2 1 0
100+
2 1 1
101+
2 1 2
102+
2 2 0
103+
2 2 1
104+
2 2 2
105+
2 3 0
106+
step c2: COMMIT;

‎src/test/isolation/specs/eval-plan-qual.spec

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,15 @@ step "upsert1"{
3939
INSERTINTOaccountsSELECT'savings',500
4040
WHERENOTEXISTS (SELECT1FROMupsert);
4141
}
42-
# tests with table p check inheritance cases, specifically a bug where
43-
# nodeLockRows did the wrong thing when the first updated tuple was in
44-
# a non-first child table
42+
43+
# tests with table p check inheritance cases:
44+
# readp1/writep1/readp2 tests a bug where nodeLockRows did the wrong thing
45+
# when the first updated tuple was in a non-first child table.
46+
# writep2/returningp1 tests a memory allocation issue
47+
4548
step"readp1"{SELECTtableoid::regclass,ctid,*FROMpWHEREbIN (0,1)ANDc=0FORUPDATE; }
4649
step"writep1"{UPDATEpSETb=-1WHEREa=1ANDb=1ANDc=0; }
50+
step"writep2"{UPDATEpSETb=-bWHEREa=1ANDc=0; }
4751
step"c1"{COMMIT; }
4852

4953
session"s2"
@@ -59,6 +63,10 @@ step "upsert2"{
5963
WHERENOTEXISTS (SELECT1FROMupsert);
6064
}
6165
step"readp2"{SELECTtableoid::regclass,ctid,*FROMpWHEREbIN (0,1)ANDc=0FORUPDATE; }
66+
step"returningp1" {
67+
WITHuAS (UPDATEpSETb=bWHEREa>0RETURNING* )
68+
SELECT*FROMu;
69+
}
6270
step"c2"{COMMIT; }
6371

6472
session"s3"
@@ -70,3 +78,4 @@ permutation "wx1" "wx2" "c1" "c2" "read"
7078
permutation"wy1""wy2""c1""c2""read"
7179
permutation"upsert1""upsert2""c1""c2""read"
7280
permutation"readp1""writep1""readp2""c1""c2"
81+
permutation"writep2""returningp1""c1""c2"

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp