v46-0002-Check-pointer-NULLness-before-cleanup-in-ExecEnd.patch
application/octet-stream
Filename: v46-0002-Check-pointer-NULLness-before-cleanup-in-ExecEnd.patch
Type: application/octet-stream
Part: 7
Patch
Format: format-patch
Series: patch v46-0002
Subject: Check pointer NULLness before cleanup in ExecEnd* routines
| File | + | − |
|---|---|---|
| src/backend/executor/nodeAgg.c | 2 | 1 |
| src/backend/executor/nodeBitmapHeapscan.c | 2 | 1 |
| src/backend/executor/nodeForeignscan.c | 8 | 13 |
| src/backend/executor/nodeMemoize.c | 1 | 0 |
| src/backend/executor/nodeRecursiveunion.c | 4 | 2 |
| src/backend/executor/nodeWindowAgg.c | 16 | 8 |
From 3dfe81f48a58a92e8c81469600d3502f18a8b137 Mon Sep 17 00:00:00 2001
From: Amit Langote <amitlan@postgresql.org>
Date: Fri, 1 Sep 2023 22:05:35 +0900
Subject: [PATCH v46 2/8] Check pointer NULLness before cleanup in ExecEnd*
routines
Many routines already perform this check, but a few instances remain.
Currently, these NULLness checks might seem redundant since ExecEnd*
routines operate under the assumption that their matching ExecInit*
routine would have fully executed, ensuring pointers are set. However,
a forthcoming patch will modify ExecInit* routines to sometimes exit
early, potentially leaving some pointers in an undetermined state.
---
src/backend/executor/nodeAgg.c | 3 ++-
src/backend/executor/nodeBitmapHeapscan.c | 3 ++-
src/backend/executor/nodeForeignscan.c | 21 ++++++++------------
src/backend/executor/nodeMemoize.c | 1 +
src/backend/executor/nodeRecursiveunion.c | 6 ++++--
src/backend/executor/nodeWindowAgg.c | 24 +++++++++++++++--------
6 files changed, 33 insertions(+), 25 deletions(-)
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index f154f28902..aac9e9fc80 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -3150,7 +3150,8 @@ hashagg_reset_spill_state(AggState *aggstate)
}
/* free batches */
- list_free_deep(aggstate->hash_batches);
+ if (aggstate->hash_batches)
+ list_free_deep(aggstate->hash_batches);
aggstate->hash_batches = NIL;
/* close tape set */
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 2db0acfc76..ffa51c06b4 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -681,7 +681,8 @@ ExecEndBitmapHeapScan(BitmapHeapScanState *node)
/*
* close heap scan
*/
- table_endscan(scanDesc);
+ if (scanDesc)
+ table_endscan(scanDesc);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index c2139acca0..d5aaa983f7 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -301,25 +301,20 @@ ExecEndForeignScan(ForeignScanState *node)
EState *estate = node->ss.ps.state;
/* Let the FDW shut down */
- if (plan->operation != CMD_SELECT)
+ if (node->fdwroutine)
{
- if (estate->es_epq_active == NULL)
- node->fdwroutine->EndDirectModify(node);
+ if (plan->operation != CMD_SELECT)
+ {
+ if (estate->es_epq_active == NULL)
+ node->fdwroutine->EndDirectModify(node);
+ }
+ else
+ node->fdwroutine->EndForeignScan(node);
}
- else
- node->fdwroutine->EndForeignScan(node);
/* Shut down any outer plan. */
if (outerPlanState(node))
ExecEndNode(outerPlanState(node));
-
- /* Free the exprcontext */
- ExecFreeExprContext(&node->ss.ps);
-
- /* clean out the tuple table */
- if (node->ss.ps.ps_ResultTupleSlot)
- ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
- ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c
index 94bf479287..5352ca10c8 100644
--- a/src/backend/executor/nodeMemoize.c
+++ b/src/backend/executor/nodeMemoize.c
@@ -1043,6 +1043,7 @@ ExecEndMemoize(MemoizeState *node)
{
#ifdef USE_ASSERT_CHECKING
/* Validate the memory accounting code is correct in assert builds. */
+ if (node->hashtable)
{
int count;
uint64 mem = 0;
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index e781003934..3dfcb4cafb 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -272,8 +272,10 @@ void
ExecEndRecursiveUnion(RecursiveUnionState *node)
{
/* Release tuplestores */
- tuplestore_end(node->working_table);
- tuplestore_end(node->intermediate_table);
+ if (node->working_table)
+ tuplestore_end(node->working_table);
+ if (node->intermediate_table)
+ tuplestore_end(node->intermediate_table);
/* free subsidiary stuff including hashtable */
if (node->tempContext)
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 77724a6daa..3849d2f847 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -1351,11 +1351,14 @@ release_partition(WindowAggState *winstate)
* any aggregate temp data). We don't rely on retail pfree because some
* aggregates might have allocated data we don't have direct pointers to.
*/
- MemoryContextResetAndDeleteChildren(winstate->partcontext);
- MemoryContextResetAndDeleteChildren(winstate->aggcontext);
+ if (winstate->partcontext)
+ MemoryContextResetAndDeleteChildren(winstate->partcontext);
+ if (winstate->aggcontext)
+ MemoryContextResetAndDeleteChildren(winstate->aggcontext);
for (i = 0; i < winstate->numaggs; i++)
{
- if (winstate->peragg[i].aggcontext != winstate->aggcontext)
+ if (winstate->peragg[i].aggcontext &&
+ winstate->peragg[i].aggcontext != winstate->aggcontext)
MemoryContextResetAndDeleteChildren(winstate->peragg[i].aggcontext);
}
@@ -2688,14 +2691,19 @@ ExecEndWindowAgg(WindowAggState *node)
for (i = 0; i < node->numaggs; i++)
{
- if (node->peragg[i].aggcontext != node->aggcontext)
+ if (node->peragg[i].aggcontext &&
+ node->peragg[i].aggcontext != node->aggcontext)
MemoryContextDelete(node->peragg[i].aggcontext);
}
- MemoryContextDelete(node->partcontext);
- MemoryContextDelete(node->aggcontext);
+ if (node->partcontext)
+ MemoryContextDelete(node->partcontext);
+ if (node->aggcontext)
+ MemoryContextDelete(node->aggcontext);
- pfree(node->perfunc);
- pfree(node->peragg);
+ if (node->perfunc)
+ pfree(node->perfunc);
+ if (node->peragg)
+ pfree(node->peragg);
outerPlan = outerPlanState(node);
ExecEndNode(outerPlan);
--
2.35.3