From 2896256bb05e7c8494802020069cdb119e0da8bb Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Wed, 19 Aug 2026 21:14:29 +0000 Subject: [PATCH v3] Fix crash in subscription REFRESH on concurrent relation drop. ALTER SUBSCRIPTION ... REFRESH PUBLICATION looks up the schema and name of each already-subscribed relation, without locking it, to exclude it from the origin check. If such a relation is dropped concurrently, the name lookups return NULL and the NULL is passed to quote_literal_cstr(), which dereferences it and crashes the backend. Fix this by skipping the relation when its name is NULL, as a dropped relation is not synchronized anyway. Backpatch the fix for tables to 16 and for sequences to 19. Author: Satya Narlapuram Co-authored-by: Bharath Rupireddy Reviewed-by: Ajin Cherian Reviewed-by: Masahiko Sawada Discussion: https://postgr.es/m/CAHg+QDcd_o3707Ey8c8b7HkE-t14g8c0tk8ME3ctywDsh3ut8g@mail.gmail.com Backpatch-through: 16 --- src/backend/commands/subscriptioncmds.c | 40 ++++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index bbbe5ddc921..2012f0062bb 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -2979,10 +2979,22 @@ check_publications_origin_tables(WalReceiverConn *wrconn, List *publications, for (i = 0; i < subrel_count; i++) { Oid relid = subrel_local_oids[i]; - char *schemaname = get_namespace_name(get_rel_namespace(relid)); - char *tablename = get_rel_name(relid); - char *schemaname_lit = quote_literal_cstr(schemaname); - char *tablename_lit = quote_literal_cstr(tablename); + char *schemaname; + char *tablename; + char *schemaname_lit; + char *tablename_lit; + + /* The table may have been dropped concurrently; skip if gone. */ + tablename = get_rel_name(relid); + if (tablename == NULL) + continue; + + schemaname = get_namespace_name(get_rel_namespace(relid)); + if (schemaname == NULL) + continue; + + schemaname_lit = quote_literal_cstr(schemaname); + tablename_lit = quote_literal_cstr(tablename); appendStringInfo(&cmd, "AND NOT (N.nspname = %s AND C.relname = %s)\n", schemaname_lit, tablename_lit); @@ -3106,10 +3118,22 @@ check_publications_origin_sequences(WalReceiverConn *wrconn, List *publications, for (int i = 0; i < subrel_count; i++) { Oid relid = subrel_local_oids[i]; - char *schemaname = get_namespace_name(get_rel_namespace(relid)); - char *seqname = get_rel_name(relid); - char *schemaname_lit = quote_literal_cstr(schemaname); - char *seqname_lit = quote_literal_cstr(seqname); + char *schemaname; + char *seqname; + char *schemaname_lit; + char *seqname_lit; + + /* The sequence may have been dropped concurrently; skip if gone. */ + seqname = get_rel_name(relid); + if (seqname == NULL) + continue; + + schemaname = get_namespace_name(get_rel_namespace(relid)); + if (schemaname == NULL) + continue; + + schemaname_lit = quote_literal_cstr(schemaname); + seqname_lit = quote_literal_cstr(seqname); appendStringInfo(&cmd, "AND NOT (N.nspname = %s AND C.relname = %s)\n", -- 2.47.3