postgres.git / summary / log / commit / refs

commit    ec8aaf845f4b7606ccf3b97247ebddd3548de917
Author:   Masahiko Sawada <msawada@postgresql.org>
Date:     Wed Aug 26 19:04:03 2026 +0000

    Fix crash in subscription refresh on concurrent relation drop.
    
    Commit 46b4f5c11b0 made the logical replication origin checks quote
    the schema and relation names they interpolate into the query sent to
    the publisher. Those names can be NULL, which that commit overlooked.
    
    AlterSubscription_refresh() collects the OIDs of the relations already
    present in pg_subscription_rel and hands them to
    check_publications_origin_tables() and
    check_publications_origin_sequences(), which append the
    schema-qualified name of each one to the query so that
    already-subscribed relations are excluded from the check. The
    relations are never locked, so one of them can be dropped concurrently
    before its name is read, and get_rel_name() and get_namespace_name()
    return NULL. quote_literal_cstr() dereferences it and crashes the
    backend.
    
    This commit fixes this by skipping a relation whose name is no longer
    available. A dropped relation is not synchronized anyway, and the
    appended clauses only exclude relations from a check whose sole effect
    is a WARNING, so omitting one can at most produce a spurious WARNING.
    
    The window is reachable from ALTER SUBSCRIPTION ... REFRESH
    PUBLICATION and from SET, ADD and DROP PUBLICATION, which refresh by
    default, but only when copy_data is true and origin is none. Backpatch
    to v16 as commit 46b4f5c11b0 was back-patched that far. The sequence
    path exists only in v19 and later.
    
    The test is applied to v19 and later only. Adding it to v17 and v18
    would require enabling injection point support in
    src/test/subscription there, and v16 predates injection points
    entirely. That is more test infrastructure churn on stable branches
    than this fix warrants.
    
    Reported-by: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
    Author: SATYANARAYANA NARLAPURAM <satyanarlapuram@gmail.com>
    Co-authored-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
    Reviewed-by: Ajin Cherian <itsajin@gmail.com>
    Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
    Discussion: https://postgr.es/m/CAHg+QDcd_o3707Ey8c8b7HkE-t14g8c0tk8ME3ctywDsh3ut8g@mail.gmail.com
    Backpatch-through: 16


src/backend/commands/subscriptioncmds.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 529abfdc13c..7aecd9d7419 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -2012,10 +2012,22 @@ check_publications_origin(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); [parent: 059aae612f57]