From 6e437ce5a6b64c443cf7c907db0988bf571e6042 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 15 Feb 2021 09:28:08 +0200 Subject: [PATCH] Make ExecGetInsertedCols() and friends more robust and improve comments. If ExecGetInsertedCols(), ExecGetUpdatedCols() or ExecGetExtraUpdatedCols() were called with a ResultRelInfo that's not in the range table and isn't a partition routing target, the functions would dereference a NULL pointer, relinfo->ri_RootResultRelInfo. Such ResultRelInfos are created when firing RI triggers in tables that are not modified directly. None of the current callers of these functions pass such relations, so this isn't a live bug, but let's make them more robust. Also update comment in ResultRelInfo; after commit 6214e2b228, ri_RangeTableIndex is zero for ResultRelInfos created for partition tuple routing. Noted by Coverity. Backpatch down to v11, like commit 6214e2b228. Reviewed-by: Tom Lane, Amit Langote --- src/backend/executor/execUtils.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index e91a6ebddd..1c2c69673c 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -1075,10 +1075,10 @@ Bitmapset * ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate) { /* - * The columns are stored in the range table entry. If this ResultRelInfo - * doesn't have an entry in the range table (i.e. if it represents a - * partition routing target), fetch the parent's RTE and map the columns - * to the order they are in the partition. + * The columns are stored in the range table entry. If this ResultRelInfo + * represents a partition routing target, and doesn't have an entry of its + * own in the range table, fetch the parent's RTE and map the columns to + * the order they are in the partition. */ if (relinfo->ri_RangeTableIndex != 0) { @@ -1087,7 +1087,7 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate) return rte->insertedCols; } - else + else if (relinfo->ri_RootResultRelInfo) { ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo; RangeTblEntry *rte = rt_fetch(rootRelInfo->ri_RangeTableIndex, @@ -1102,6 +1102,16 @@ ExecGetInsertedCols(ResultRelInfo *relinfo, EState *estate) else return rte->insertedCols; } + else + { + /* + * The relation isn't in the range table and it isn't a partition + * routing target. This ResultRelInfo must've been created only for + * firing triggers and the relation is not being inserted into. (See + * ExecGetTriggerResultRel.) + */ + return NULL; + } } /* Return a bitmap representing columns being updated */ @@ -1116,7 +1126,7 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate) return rte->updatedCols; } - else + else if (relinfo->ri_RootResultRelInfo) { ResultRelInfo *rootRelInfo = relinfo->ri_RootResultRelInfo; RangeTblEntry *rte = rt_fetch(rootRelInfo->ri_RangeTableIndex, @@ -1131,4 +1141,6 @@ ExecGetUpdatedCols(ResultRelInfo *relinfo, EState *estate) else return rte->updatedCols; } + else + return NULL; }