From d29cc80d400e206e13566748d9c20903725a5211 Mon Sep 17 00:00:00 2001 From: Vignesh C Date: Wed, 9 Sep 2026 09:21:27 +0530 Subject: [PATCH v1 2/5] Fix ALTER PUBLICATION validation race AlterPublication() calls CheckAlterPublication() before acquiring the publication lock. A concurrent ALTER PUBLICATION can modify pg_publication_rel while the command waits for the lock, allowing the validation to pass based on stale state. The command then re-fetches the publication tuple after acquiring the lock, but does not revalidate the publication relations. This can leave pg_publication_rel containing a mixture of inclusion and exclusion rows. Re-run CheckAlterPublication() after acquiring the lock so that the validation uses the current publication state. --- src/backend/commands/publicationcmds.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 79276c842cc..96d5c0453a1 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -1695,8 +1695,6 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt) ObjectsInPublicationToOids(stmt->pubobjects, pstate, &relations, &exceptrelations, &schemaidlist); - CheckAlterPublication(stmt, tup, relations, schemaidlist); - heap_freetuple(tup); /* Lock the publication so nobody else can do anything with it. */ @@ -1716,6 +1714,17 @@ AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt) errmsg("publication \"%s\" does not exist", stmt->pubname)); + /* + * Validate after acquiring the lock so that the checks see the + * publication state we are about to modify. A concurrent ALTER + * PUBLICATION may otherwise change the state while we wait for the + * lock, causing both commands to pass their checks independently. + * LockDatabaseObject() accepts invalidation messages after acquiring + * the lock, so the catalog scans below see concurrently committed + * changes. + */ + CheckAlterPublication(stmt, tup, relations, schemaidlist); + relations = list_concat(relations, exceptrelations); AlterPublicationTables(stmt, tup, relations, pstate->p_sourcetext, schemaidlist != NIL); -- 2.55.0