]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix incorrect memory access in VACUUM FULL with invalid toast indexes
authorMichael Paquier <michael@paquier.xyz>
Fri, 27 Sep 2024 00:40:14 +0000 (09:40 +0900)
committerMichael Paquier <michael@paquier.xyz>
Fri, 27 Sep 2024 00:40:14 +0000 (09:40 +0900)
An invalid toast index is skipped in reindex_relation().  These would be
remnants of a failed REINDEX CONCURRENTLY and they should never been
rebuilt as there can only be one valid toast index at a time.

REINDEX_REL_SUPPRESS_INDEX_USE, used by CLUSTER and VACUUM FULL, needs
to maintain a list of the indexes being processed.  The list of indexes
is retrieved from the relation cache, and includes invalid indexes.  The
code has missed that invalid toast indexes are ignored in
reindex_relation() as this leads to a hard failure in reindex_index(),
and they were left in the reindex pending list, making the list
inconsistent when rechecked.  The incorrect memory access was happening
when scanning pg_class for the refresh of pg_database.datfrozenxid, when
doing a scan of pg_class.

This issue exists since REINDEX CONCURRENTLY exists, where invalid toast
indexes can exist, so backpatch all the way down.

Reported-by: Alexander Lakhin
Author: Tender Wang
Discussion: https://postgr.es/m/18630-9aed99c38830657d@postgresql.org
Backpatch-through: 12

src/backend/catalog/index.c

index ef8872000e92715a239e3d5e1f28f8caefaccc9e..3eaf1f2dcafec1edba2ffeb8130b735168da6828 100644 (file)
@@ -3982,6 +3982,14 @@ reindex_relation(const ReindexStmt *stmt, Oid relid, int flags,
                                         errmsg("cannot reindex invalid index \"%s.%s\" on TOAST table, skipping",
                                                        get_namespace_name(indexNamespaceId),
                                                        get_rel_name(indexOid))));
+
+                       /*
+                        * Remove this invalid toast index from the reindex pending list,
+                        * as it is skipped here due to the hard failure that would happen
+                        * in reindex_index(), should we try to process it.
+                        */
+                       if (flags & REINDEX_REL_SUPPRESS_INDEX_USE)
+                               RemoveReindexPending(indexOid);
                        continue;
                }