diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 5cf874e..e5ae453 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -715,7 +715,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data) * the origin might be already removed. For these reasons, * passing missing_ok = true. */ - ReplicationOriginNameForTablesync(sub->oid, relid, originname); + ReplicationOriginNameForTablesync(sub->oid, relid, originname, + sizeof(originname)); replorigin_drop_by_name(originname, true, false); } @@ -749,7 +750,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data) * dropped slots and fail. For these reasons, we allow * missing_ok = true for the drop. */ - ReplicationSlotNameForTablesync(sub->oid, sub_remove_rels[off].relid, syncslotname); + ReplicationSlotNameForTablesync(sub->oid, sub_remove_rels[off].relid, + syncslotname, sizeof(syncslotname)); ReplicationSlotDropAtPubNode(wrconn, syncslotname, true); } } @@ -1174,7 +1176,8 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) * worker so passing missing_ok = true. This can happen for the states * before SUBREL_STATE_FINISHEDCOPY. */ - ReplicationOriginNameForTablesync(subid, relid, originname); + ReplicationOriginNameForTablesync(subid, relid, originname, + sizeof(originname)); replorigin_drop_by_name(originname, true, false); } @@ -1254,7 +1257,8 @@ DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel) { char syncslotname[NAMEDATALEN] = {0}; - ReplicationSlotNameForTablesync(subid, relid, syncslotname); + ReplicationSlotNameForTablesync(subid, relid, syncslotname, + sizeof(syncslotname)); ReplicationSlotDropAtPubNode(wrconn, syncslotname, true); } } @@ -1532,7 +1536,8 @@ ReportSlotConnectionError(List *rstates, Oid subid, char *slotname, char *err) { char syncslotname[NAMEDATALEN] = {0}; - ReplicationSlotNameForTablesync(subid, relid, syncslotname); + ReplicationSlotNameForTablesync(subid, relid, syncslotname, + sizeof(syncslotname)); elog(WARNING, "could not drop tablesync replication slot \"%s\"", syncslotname); } diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index 19cc804..7fd110c 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -314,7 +314,8 @@ process_syncing_tables_for_sync(XLogRecPtr current_lsn) */ ReplicationSlotNameForTablesync(MyLogicalRepWorker->subid, MyLogicalRepWorker->relid, - syncslotname); + syncslotname, + sizeof(syncslotname)); /* * It is important to give an error if we are unable to drop the slot, @@ -462,7 +463,8 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) */ ReplicationOriginNameForTablesync(MyLogicalRepWorker->subid, rstate->relid, - originname); + originname, + sizeof(originname)); replorigin_drop_by_name(originname, true, false); /* @@ -872,7 +874,7 @@ copy_table(Relation rel) * length of slot_name will be 50. * * The returned slot name is either: - * - stored in the supplied buffer (syncslotname), or + * - stored in the supplied buffer (syncslotname) with the given size, or * - palloc'ed in current memory context (if syncslotname = NULL). * * Note: We don't use the subscription slot name as part of tablesync slot name @@ -882,15 +884,18 @@ copy_table(Relation rel) */ char * ReplicationSlotNameForTablesync(Oid suboid, Oid relid, - char syncslotname[NAMEDATALEN]) + char *syncslotname, int szslot) { if (syncslotname) - sprintf(syncslotname, "pg_%u_sync_%u_" UINT64_FORMAT, suboid, relid, - GetSystemIdentifier()); + snprintf(syncslotname, szslot, "pg_%u_sync_%u_" UINT64_FORMAT, suboid, + relid, GetSystemIdentifier()); else syncslotname = psprintf("pg_%u_sync_%u_" UINT64_FORMAT, suboid, relid, GetSystemIdentifier()); + /* Ensure slot name meets remote node constraints. */ + Assert(strlen(syncslotname) < NAMEDATALEN - 1); + return syncslotname; } @@ -901,9 +906,9 @@ ReplicationSlotNameForTablesync(Oid suboid, Oid relid, */ void ReplicationOriginNameForTablesync(Oid suboid, Oid relid, - char originname[NAMEDATALEN]) + char *originname, int szorgname) { - snprintf(originname, NAMEDATALEN, "pg_%u_%u", suboid, relid); + snprintf(originname, szorgname, "pg_%u_%u", suboid, relid); } /* @@ -953,7 +958,8 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos) /* Calculate the name of the tablesync slot. */ slotname = ReplicationSlotNameForTablesync(MySubscription->oid, MyLogicalRepWorker->relid, - NULL /* use palloc */ ); + NULL, + 0); /* * Here we use the slot name instead of the subscription name as the @@ -972,7 +978,8 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos) /* Assign the origin tracking record name. */ ReplicationOriginNameForTablesync(MySubscription->oid, MyLogicalRepWorker->relid, - originname); + originname, + sizeof(originname)); if (MyLogicalRepWorker->relstate == SUBREL_STATE_DATASYNC) { diff --git a/src/include/replication/slot.h b/src/include/replication/slot.h index 5f52335..5317b6f 100644 --- a/src/include/replication/slot.h +++ b/src/include/replication/slot.h @@ -212,7 +212,7 @@ extern bool ReplicationSlotsCountDBSlots(Oid dboid, int *nslots, int *nactive); extern void ReplicationSlotsDropDBSlots(Oid dboid); extern void InvalidateObsoleteReplicationSlots(XLogSegNo oldestSegno); extern ReplicationSlot *SearchNamedReplicationSlot(const char *name); -extern char *ReplicationSlotNameForTablesync(Oid suboid, Oid relid, char *syncslotname); +extern char *ReplicationSlotNameForTablesync(Oid suboid, Oid relid, char *syncslotname, int szslot); extern void ReplicationSlotDropAtPubNode(WalReceiverConn *wrconn, char *slotname, bool missing_ok); extern void StartupReplicationSlots(void); diff --git a/src/include/replication/worker_internal.h b/src/include/replication/worker_internal.h index 4a5adc2..1cac75e 100644 --- a/src/include/replication/worker_internal.h +++ b/src/include/replication/worker_internal.h @@ -82,7 +82,8 @@ extern void logicalrep_worker_wakeup_ptr(LogicalRepWorker *worker); extern int logicalrep_sync_worker_count(Oid subid); -extern void ReplicationOriginNameForTablesync(Oid suboid, Oid relid, char *originname); +extern void ReplicationOriginNameForTablesync(Oid suboid, Oid relid, + char *originname, int szorgname); extern char *LogicalRepSyncTableStart(XLogRecPtr *origin_startpos); void process_syncing_tables(XLogRecPtr current_lsn);