v2-0001-Reject-negative-max_retention_duration-values.patch
application/octet-stream
Filename: v2-0001-Reject-negative-max_retention_duration-values.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v2-0001
Subject: Reject negative max_retention_duration values
| File | + | − |
|---|---|---|
| src/backend/commands/subscriptioncmds.c | 5 | 0 |
| src/test/regress/expected/subscription.out | 6 | 0 |
| src/test/regress/sql/subscription.sql | 6 | 0 |
From dd8100b84465275a7479247ef71a126c4dfd5da1 Mon Sep 17 00:00:00 2001
From: "Chao Li (Evan)" <lic@highgo.com>
Date: Tue, 9 Jun 2026 15:57:56 +0800
Subject: [PATCH v2] Reject negative max_retention_duration values
The subscription option max_retention_duration accepts an integer value,
where zero disables the retention timeout behavior. Negative values do not
have a useful meaning, but were accepted and stored in the subscription
catalog.
Reject negative values when parsing subscription options, covering both
CREATE SUBSCRIPTION and ALTER SUBSCRIPTION. Also treat non-positive values
as disabled in the apply worker as a defensive check.
Add regression tests for negative max_retention_duration values in both
CREATE SUBSCRIPTION and ALTER SUBSCRIPTION.
Author: Chao Li <lic@highgo.com>
Reviewed-by: Hayato Kuroda <kuroda.hayato@fujitsu.com>
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
Discussion: https://postgr.es/m/9232401A-DEEE-49E1-9D11-D14A776DB82B@gmail.com
---
src/backend/commands/subscriptioncmds.c | 5 +++++
src/test/regress/expected/subscription.out | 6 ++++++
src/test/regress/sql/subscription.sql | 6 ++++++
3 files changed, 17 insertions(+)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index fd026b304c2..87311f683e9 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -356,6 +356,11 @@ parse_subscription_options(ParseState *pstate, List *stmt_options,
opts->specified_opts |= SUBOPT_MAX_RETENTION_DURATION;
opts->maxretention = defGetInt32(defel);
+
+ if (opts->maxretention < 0)
+ ereport(ERROR,
+ errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("max_retention_duration cannot be negative"));
}
else if (IsSet(supported_opts, SUBOPT_ORIGIN) &&
strcmp(defel->defname, "origin") == 0)
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 8481056a702..a1b3cc96d83 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -518,6 +518,9 @@ DROP SUBSCRIPTION regress_testsub;
-- fail - max_retention_duration must be integer
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = foo);
ERROR: max_retention_duration requires an integer value
+-- fail - max_retention_duration must be non-negative
+CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = -1);
+ERROR: max_retention_duration cannot be negative
-- ok
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = 1000);
NOTICE: max_retention_duration is ineffective when retain_dead_tuples is disabled
@@ -530,6 +533,9 @@ HINT: To initiate replication, you must manually create the replication slot, e
regress_testsub | regress_subscription_user | f | {testpub} | f | parallel | d | f | any | t | f | f | | f | 1000 | f | off | dbname=regress_doesnotexist | -1 | 0/00000000 |
(1 row)
+-- fail - max_retention_duration must be non-negative
+ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = -1);
+ERROR: max_retention_duration cannot be negative
-- ok
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = 0);
\dRs+
diff --git a/src/test/regress/sql/subscription.sql b/src/test/regress/sql/subscription.sql
index 374fad6aa7b..528a10b5481 100644
--- a/src/test/regress/sql/subscription.sql
+++ b/src/test/regress/sql/subscription.sql
@@ -378,11 +378,17 @@ DROP SUBSCRIPTION regress_testsub;
-- fail - max_retention_duration must be integer
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = foo);
+-- fail - max_retention_duration must be non-negative
+CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = -1);
+
-- ok
CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUBLICATION testpub WITH (connect = false, max_retention_duration = 1000);
\dRs+
+-- fail - max_retention_duration must be non-negative
+ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = -1);
+
-- ok
ALTER SUBSCRIPTION regress_testsub SET (max_retention_duration = 0);
--
2.50.1 (Apple Git-155)