Skip to content

Commit 5308e08

Browse files
committed
Fix use-of-already-freed-memory problem in EvalPlanQual processing.
Up to now, the "child" executor state trees generated for EvalPlanQual rechecks have simply shared the ResultRelInfo arrays used for the original execution tree. However, this leads to dangling-pointer problems, because ExecInitModifyTable() is all too willing to scribble on some fields of the ResultRelInfo(s) even when it's being run in one of those child trees. This trashes those fields from the perspective of the parent tree, because even if the generated subtree is logically identical to what was in use in the parent, it's in a memory context that will go away when we're done with the child state tree. We do however want to share information in the direction from the parent down 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 his example. In an unpatched memory-clobber-enabled build it will reliably fail with "ctid is NULL" errors in all branches back to 9.1, as a consequence of junkfilter->jf_junkAttNo being overwritten with $7f7f. This test cannot be run as-is before that for lack of WITH syntax; but I have no doubt that some variant of this problem can arise in older branches, so apply the code change all the way back.
1 parent 0a67c00 commit 5308e08

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/backend/executor/execMain.c

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,14 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
19941994
* the snapshot, rangetable, result-rel info, and external Param info.
19951995
* They need their own copies of local state, including a tuple table,
19961996
* es_param_exec_vals, etc.
1997+
*
1998+
* The ResultRelInfo array management is trickier than it looks. We
1999+
* create a fresh array for the child but copy all the content from the
2000+
* parent. This is because it's okay for the child to share any
2001+
* per-relation state the parent has already created --- but if the child
2002+
* sets up any ResultRelInfo fields, such as its own junkfilter, that
2003+
* state must *not* propagate back to the parent. (For one thing, the
2004+
* pointed-to data is in a memory context that won't last long enough.)
19972005
*/
19982006
estate->es_direction = ForwardScanDirection;
19992007
estate->es_snapshot = parentestate->es_snapshot;
@@ -2002,9 +2010,19 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
20022010
estate->es_plannedstmt = parentestate->es_plannedstmt;
20032011
estate->es_junkFilter = parentestate->es_junkFilter;
20042012
estate->es_output_cid = parentestate->es_output_cid;
2005-
estate->es_result_relations = parentestate->es_result_relations;
2006-
estate->es_num_result_relations = parentestate->es_num_result_relations;
2007-
estate->es_result_relation_info = parentestate->es_result_relation_info;
2013+
if (parentestate->es_num_result_relations > 0)
2014+
{
2015+
int numResultRelations = parentestate->es_num_result_relations;
2016+
ResultRelInfo *resultRelInfos;
2017+
2018+
resultRelInfos = (ResultRelInfo *)
2019+
palloc(numResultRelations * sizeof(ResultRelInfo));
2020+
memcpy(resultRelInfos, parentestate->es_result_relations,
2021+
numResultRelations * sizeof(ResultRelInfo));
2022+
estate->es_result_relations = resultRelInfos;
2023+
estate->es_num_result_relations = numResultRelations;
2024+
}
2025+
/* es_result_relation_info must NOT be copied */
20082026
/* es_trig_target_relations must NOT be copied */
20092027
estate->es_rowMarks = parentestate->es_rowMarks;
20102028
estate->es_instrument = parentestate->es_instrument;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy