Skip to content

Commit 55a5bc7

Browse files
committed
Correctly handle bad characters in the generated slot name
1 parent d93b4e8 commit 55a5bc7

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

pglogical_functions.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1515,14 +1515,26 @@ static void
15151515
gen_slot_name(Name slot_name, char *dbname, const char *provider_node,
15161516
const char *subscription_name)
15171517
{
1518+
char *cp;
1519+
15181520
memset(NameStr(*slot_name), 0, NAMEDATALEN);
15191521
snprintf(NameStr(*slot_name), NAMEDATALEN,
15201522
"pgl_%s_%s_%s",
15211523
shorten_hash(dbname, 16),
15221524
shorten_hash(provider_node, 16),
15231525
shorten_hash(subscription_name, 16));
1524-
15251526
NameStr(*slot_name)[NAMEDATALEN-1] = '\0';
1527+
1528+
/* Replace all the invalid characters in slot name with underscore. */
1529+
for (cp = NameStr(*slot_name); *cp; cp++)
1530+
{
1531+
if (!((*cp >= 'a' && *cp <= 'z')
1532+
|| (*cp >= '0' && *cp <= '9')
1533+
|| (*cp == '_')))
1534+
{
1535+
*cp = '_';
1536+
}
1537+
}
15261538
}
15271539

15281540
Datum

pglogical_node.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,40 @@ typedef struct SubscriptionTuple
101101
#define Anum_sub_replication_sets 9
102102
#define Anum_sub_forward_origins 10
103103

104+
/*
105+
* We impose same validation rules as replication slot name validation does.
106+
*/
107+
static void
108+
validate_subscription_name(const char *name)
109+
{
110+
const char *cp;
111+
112+
if (strlen(name) == 0)
113+
ereport(ERROR,
114+
(errcode(ERRCODE_INVALID_NAME),
115+
errmsg("subscription name \"%s\" is too short", name)));
116+
117+
if (strlen(name) >= NAMEDATALEN)
118+
ereport(ERROR,
119+
(errcode(ERRCODE_NAME_TOO_LONG),
120+
errmsg("subscription name \"%s\" is too long", name)));
121+
122+
for (cp = name; *cp; cp++)
123+
{
124+
if (!((*cp >= 'a' && *cp <= 'z')
125+
|| (*cp >= '0' && *cp <= '9')
126+
|| (*cp == '_')))
127+
{
128+
ereport(ERROR,
129+
(errcode(ERRCODE_INVALID_NAME),
130+
errmsg("subscription name \"%s\" contains invalid character",
131+
name),
132+
errhint("Subscription names may only contain lower case "
133+
"letters, numbers, and the underscore character.")));
134+
}
135+
}
136+
}
137+
104138
/*
105139
* Add new node to catalog.
106140
*/
@@ -597,6 +631,9 @@ create_subscription(PGLogicalSubscription *sub)
597631
NameData sub_name;
598632
NameData slot_name;
599633

634+
/* Validate the new subscription name. */
635+
validate_subscription_name(sub->name);
636+
600637
if (get_subscription_by_name(sub->name, true) != NULL)
601638
elog(ERROR, "subscription %s already exists", sub->name);
602639

pglogical_sync.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "miscadmin.h"
2121

2222
#include "access/genam.h"
23+
#include "access/hash.h"
2324
#include "access/heapam.h"
2425
#include "access/skey.h"
2526
#include "access/stratnum.h"
@@ -794,8 +795,9 @@ pglogical_sync_main(Datum main_arg)
794795
copytable->relname);
795796

796797
initStringInfo(&slot_name);
797-
appendStringInfo(&slot_name, "%s_%s", MySubscription->slot_name,
798-
shorten_hash(tablename, 8));
798+
appendStringInfo(&slot_name, "%s_%08x", MySubscription->slot_name,
799+
DatumGetUInt32(hash_any((unsigned char *) tablename,
800+
strlen(tablename))));
799801
MySubscription->slot_name = slot_name.data;
800802

801803
elog(LOG, "starting sync of table %s.%s for subscriber %s",

0 commit comments

Comments
 (0)