From 590e7719c5149eba4f2e383525f1467c1ff2e178 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Wed, 3 Dec 2025 14:42:39 +0530
Subject: [PATCH] Fix START_REPLICATION failure when publication names contain
 backslashes

CREATE PUBLICATION already accepts quoted identifiers that may include
backslash characters in publication names. However, START_REPLICATION
could not handle such names correctly, causing unexpected syntax errors
when the subscriber sent the publication name back to the walsender.

This patch fixes the issue by passing the publication name as it is,
instead of applying escape-string processing. The replication grammar
does not require escape-string handling here.
---
 .../libpqwalreceiver/libpqwalreceiver.c       | 11 +-------
 src/test/subscription/t/100_bugs.pl           | 26 +++++++++++++++++--
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 239641bfbb6..d31e1dc21e2 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -538,7 +538,6 @@ libpqrcv_startstreaming(WalReceiverConn *conn,
 	{
 		char	   *pubnames_str;
 		List	   *pubnames;
-		char	   *pubnames_literal;
 
 		appendStringInfoString(&cmd, " (");
 
@@ -565,15 +564,7 @@ libpqrcv_startstreaming(WalReceiverConn *conn,
 					(errcode(ERRCODE_OUT_OF_MEMORY),	/* likely guess */
 					 errmsg("could not start WAL streaming: %s",
 							pchomp(PQerrorMessage(conn->streamConn)))));
-		pubnames_literal = PQescapeLiteral(conn->streamConn, pubnames_str,
-										   strlen(pubnames_str));
-		if (!pubnames_literal)
-			ereport(ERROR,
-					(errcode(ERRCODE_OUT_OF_MEMORY),	/* likely guess */
-					 errmsg("could not start WAL streaming: %s",
-							pchomp(PQerrorMessage(conn->streamConn)))));
-		appendStringInfo(&cmd, ", publication_names %s", pubnames_literal);
-		PQfreemem(pubnames_literal);
+		appendStringInfo(&cmd, ", publication_names '%s'", pubnames_str);
 		pfree(pubnames_str);
 
 		if (options->proto.logical.binary &&
diff --git a/src/test/subscription/t/100_bugs.pl b/src/test/subscription/t/100_bugs.pl
index 50223054918..7647d1b1e4a 100644
--- a/src/test/subscription/t/100_bugs.pl
+++ b/src/test/subscription/t/100_bugs.pl
@@ -585,11 +585,11 @@ $node_subscriber->stop('fast');
 # The bug is fixed by reducing the lock-level during DROP SUBSCRIPTION.
 $node_publisher->start();
 
-$publisher_connstr = $node_publisher->connstr . ' dbname=regress_db';
+my $publisher_connstr_regressdb = $node_publisher->connstr . ' dbname=regress_db';
 $node_publisher->safe_psql(
 	'postgres', qq(
 	CREATE DATABASE regress_db;
-	CREATE SUBSCRIPTION regress_sub1 CONNECTION '$publisher_connstr' PUBLICATION regress_pub WITH (connect=false);
+	CREATE SUBSCRIPTION regress_sub1 CONNECTION '$publisher_connstr_regressdb' PUBLICATION regress_pub WITH (connect=false);
 ));
 
 my ($ret, $stdout, $stderr) =
@@ -605,4 +605,26 @@ $node_publisher->safe_psql('postgres', "DROP DATABASE regress_db");
 
 $node_publisher->stop('fast');
 
+# The bug occurred because START_REPLICATION could not handle publication
+# names containing backslash escaped characters (such as NULL and newline).
+# When such a name was sent back by the WAL receiver, the walsender failed to
+# parse it, leading to a syntax error.
+$node_publisher->start();
+$node_subscriber->start();
+
+$node_publisher->safe_psql('postgres',
+	"CREATE PUBLICATION \"regress_pub_\\0\\n\"");
+$node_subscriber->safe_psql('postgres',
+	"CREATE SUBSCRIPTION regress_sub2 CONNECTION '$publisher_connstr' PUBLICATION \"regress_pub_\\0\\n\""
+);
+$node_subscriber->wait_for_subscription_sync($node_publisher, 'regress_sub2');
+
+# Clean up
+$node_subscriber->safe_psql('postgres', "DROP SUBSCRIPTION regress_sub2");
+$node_publisher->safe_psql('postgres',
+	"DROP PUBLICATION \"regress_pub_\\0\\n\"");
+
+$node_subscriber->stop('fast');
+$node_publisher->stop('fast');
+
 done_testing();
-- 
2.43.0

