postgres.git / summary / log / commit / refs

commit    99b6b705d439fbf72aefe968941f38d571b9231c
Author:   Tom Lane <tgl@sss.pgh.pa.us>
Date:     Mon Oct 17 15:35:23 2022 +0000
First released in: 16.0, 12.13, 13.9, 14.6, 15.1

    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


src/backend/optimizer/util/plancat.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index bdb2f164295..d163cc45c4b 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -123,6 +123,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 (!RelationNeedsWAL(relation) && RecoveryInProgress()) ereport(ERROR, [parent: 3d7df87c4bba]