diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2022-10-17 11:35:23 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2022-10-17 11:35:23 -0400 |
commit | 62b263bf779ed5d1ad0ae3fb0a5790f773423beb (patch) | |
tree | 4c206ab50acecda3e93f0774a04c5c4e0bebd4c6 /src | |
parent | bc7a40b42eef717026d29b687157cd0af5adaadb (diff) | |
download | postgresql-62b263bf779ed5d1ad0ae3fb0a5790f773423beb.tar.gz postgresql-62b263bf779ed5d1ad0ae3fb0a5790f773423beb.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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 8a0fed8ab6e..063c6fa8942 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -125,6 +125,22 @@ 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. + */ + 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)))); + } + /* Temporary and unlogged relations are inaccessible during recovery. */ if (relation->rd_rel->relpersistence != RELPERSISTENCE_PERMANENT && RecoveryInProgress()) |