aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-10-17 11:35:23 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-10-17 11:35:23 -0400
commit2e3326929b0ba9f421f2ab1270c57b294c208a99 (patch)
tree65740ac7e3315f9165900484701490418489a236
parent9ebcb5ffdf3a1f49388c38ba5273370f49bf7d19 (diff)
downloadpostgresql-2e3326929b0ba9f421f2ab1270c57b294c208a99.tar.gz
postgresql-2e3326929b0ba9f421f2ab1270c57b294c208a99.zip
Guard against table-AM-less relations in planner.
The executor will dump core if it's asked to execute a seqscan on a relation having no table AM, such as a view. While that shouldn't really happen, it's possible to get there via catalog corruption, such as a missing ON SELECT rule. It seems worth installing a defense against that. There are multiple plausible places for such a defense, but I picked the planner's get_relation_info(). Per discussion of bug #17646 from Kui Liu. Back-patch to v12 where the tableam APIs were introduced; in older versions you won't get a SIGSEGV, so it seems less pressing. Discussion: https://postgr.es/m/17646-70c93cfa40365776@postgresql.org
-rw-r--r--src/backend/optimizer/util/plancat.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index 5012bfe1425..c328a2f9129 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -126,6 +126,24 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
*/
relation = table_open(relationObjectId, NoLock);
+ /*
+ * Relations without a table AM can be used in a query only if they are of
+ * special-cased relkinds. This check prevents us from crashing later if,
+ * for example, a view's ON SELECT rule has gone missing. Note that
+ * table_open() already rejected indexes and composite types; spell the
+ * error the same way it does.
+ */
+ if (!relation->rd_tableam)
+ {
+ if (!(relation->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
+ relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("cannot open relation \"%s\"",
+ RelationGetRelationName(relation)),
+ errdetail_relkind_not_supported(relation->rd_rel->relkind)));
+ }
+
/* Temporary and unlogged relations are inaccessible during recovery. */
if (!RelationIsPermanent(relation) && RecoveryInProgress())
ereport(ERROR,