aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/auth_delay/auth_delay.c2
-rw-r--r--contrib/auto_explain/auto_explain.c2
-rw-r--r--contrib/basic_archive/basic_archive.c2
-rw-r--r--contrib/pg_prewarm/autoprewarm.c2
-rw-r--r--contrib/pg_stat_statements/pg_stat_statements.c2
-rw-r--r--contrib/pg_trgm/trgm_op.c2
-rw-r--r--contrib/postgres_fdw/option.c2
-rw-r--r--contrib/sepgsql/hooks.c2
-rw-r--r--src/backend/utils/misc/guc.c79
-rw-r--r--src/include/utils/guc.h5
-rw-r--r--src/pl/plperl/plperl.c2
-rw-r--r--src/pl/plpgsql/src/pl_handler.c2
-rw-r--r--src/pl/tcl/pltcl.c4
-rw-r--r--src/test/modules/delay_execution/delay_execution.c2
-rw-r--r--src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c2
-rw-r--r--src/test/modules/worker_spi/worker_spi.c2
-rw-r--r--src/test/regress/expected/guc.out11
-rw-r--r--src/test/regress/sql/guc.sql7
18 files changed, 101 insertions, 31 deletions
diff --git a/contrib/auth_delay/auth_delay.c b/contrib/auth_delay/auth_delay.c
index 38f4276db39..6b94d653ea4 100644
--- a/contrib/auth_delay/auth_delay.c
+++ b/contrib/auth_delay/auth_delay.c
@@ -68,7 +68,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("auth_delay");
+ MarkGUCPrefixReserved("auth_delay");
/* Install Hooks */
original_client_auth_hook = ClientAuthentication_hook;
diff --git a/contrib/auto_explain/auto_explain.c b/contrib/auto_explain/auto_explain.c
index 3e09abaecac..d3029f85efe 100644
--- a/contrib/auto_explain/auto_explain.c
+++ b/contrib/auto_explain/auto_explain.c
@@ -231,7 +231,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("auto_explain");
+ MarkGUCPrefixReserved("auto_explain");
/* Install hooks. */
prev_ExecutorStart = ExecutorStart_hook;
diff --git a/contrib/basic_archive/basic_archive.c b/contrib/basic_archive/basic_archive.c
index 16ddddccbbc..e7efbfb9c34 100644
--- a/contrib/basic_archive/basic_archive.c
+++ b/contrib/basic_archive/basic_archive.c
@@ -69,7 +69,7 @@ _PG_init(void)
0,
check_archive_directory, NULL, NULL);
- EmitWarningsOnPlaceholders("basic_archive");
+ MarkGUCPrefixReserved("basic_archive");
basic_archive_context = AllocSetContextCreate(TopMemoryContext,
"basic_archive",
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 1d4d74b171f..45e012a63a5 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -137,7 +137,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("pg_prewarm");
+ MarkGUCPrefixReserved("pg_prewarm");
RequestAddinShmemSpace(MAXALIGN(sizeof(AutoPrewarmSharedState)));
diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index 9d7d0812ac3..38d92a89cc4 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -437,7 +437,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("pg_stat_statements");
+ MarkGUCPrefixReserved("pg_stat_statements");
/*
* Request additional shared resources. (These are no-ops if we're not in
diff --git a/contrib/pg_trgm/trgm_op.c b/contrib/pg_trgm/trgm_op.c
index 0407c7dd644..e9b7981619f 100644
--- a/contrib/pg_trgm/trgm_op.c
+++ b/contrib/pg_trgm/trgm_op.c
@@ -101,7 +101,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("pg_trgm");
+ MarkGUCPrefixReserved("pg_trgm");
}
/*
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index af38e956e70..2c6b2894b96 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -538,5 +538,5 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("postgres_fdw");
+ MarkGUCPrefixReserved("postgres_fdw");
}
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index d71c802106a..97e61b8043f 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -455,7 +455,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("sepgsql");
+ MarkGUCPrefixReserved("sepgsql");
/* Initialize userspace access vector cache */
sepgsql_avc_init();
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 01f373815e0..eaa4bf2c304 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -150,6 +150,8 @@ extern bool optimize_bounded_sort;
static int GUC_check_errcode_value;
+static List *reserved_class_prefix = NIL;
+
/* global variables for check hook support */
char *GUC_check_errmsg_string;
char *GUC_check_errdetail_string;
@@ -5590,18 +5592,44 @@ find_option(const char *name, bool create_placeholders, bool skip_errors,
* doesn't contain a separator, don't assume that it was meant to be a
* placeholder.
*/
- if (strchr(name, GUC_QUALIFIER_SEPARATOR) != NULL)
+ const char *sep = strchr(name, GUC_QUALIFIER_SEPARATOR);
+
+ if (sep != NULL)
{
- if (valid_custom_variable_name(name))
- return add_placeholder_variable(name, elevel);
- /* A special error message seems desirable here */
- if (!skip_errors)
- ereport(elevel,
- (errcode(ERRCODE_INVALID_NAME),
- errmsg("invalid configuration parameter name \"%s\"",
- name),
- errdetail("Custom parameter names must be two or more simple identifiers separated by dots.")));
- return NULL;
+ size_t classLen = sep - name;
+ ListCell *lc;
+
+ /* The name must be syntactically acceptable ... */
+ if (!valid_custom_variable_name(name))
+ {
+ if (!skip_errors)
+ ereport(elevel,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid configuration parameter name \"%s\"",
+ name),
+ errdetail("Custom parameter names must be two or more simple identifiers separated by dots.")));
+ return NULL;
+ }
+ /* ... and it must not match any previously-reserved prefix */
+ foreach(lc, reserved_class_prefix)
+ {
+ const char *rcprefix = lfirst(lc);
+
+ if (strlen(rcprefix) == classLen &&
+ strncmp(name, rcprefix, classLen) == 0)
+ {
+ if (!skip_errors)
+ ereport(elevel,
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid configuration parameter name \"%s\"",
+ name),
+ errdetail("\"%s\" is a reserved prefix.",
+ rcprefix)));
+ return NULL;
+ }
+ }
+ /* OK, create it */
+ return add_placeholder_variable(name, elevel);
}
}
@@ -9355,15 +9383,26 @@ DefineCustomEnumVariable(const char *name,
}
/*
+ * Mark the given GUC prefix as "reserved".
+ *
+ * This deletes any existing placeholders matching the prefix,
+ * and then prevents new ones from being created.
* Extensions should call this after they've defined all of their custom
* GUCs, to help catch misspelled config-file entries.
*/
void
-EmitWarningsOnPlaceholders(const char *className)
+MarkGUCPrefixReserved(const char *className)
{
int classLen = strlen(className);
int i;
+ MemoryContext oldcontext;
+ /*
+ * Check for existing placeholders. We must actually remove invalid
+ * placeholders, else future parallel worker startups will fail. (We
+ * don't bother trying to free associated memory, since this shouldn't
+ * happen often.)
+ */
for (i = 0; i < num_guc_variables; i++)
{
struct config_generic *var = guc_variables[i];
@@ -9373,11 +9412,21 @@ EmitWarningsOnPlaceholders(const char *className)
var->name[classLen] == GUC_QUALIFIER_SEPARATOR)
{
ereport(WARNING,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("unrecognized configuration parameter \"%s\"",
- var->name)));
+ (errcode(ERRCODE_INVALID_NAME),
+ errmsg("invalid configuration parameter name \"%s\", removing it",
+ var->name),
+ errdetail("\"%s\" is now a reserved prefix.",
+ className)));
+ num_guc_variables--;
+ memmove(&guc_variables[i], &guc_variables[i + 1],
+ (num_guc_variables - i) * sizeof(struct config_generic *));
}
}
+
+ /* And remember the name so we can prevent future mistakes. */
+ oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+ reserved_class_prefix = lappend(reserved_class_prefix, pstrdup(className));
+ MemoryContextSwitchTo(oldcontext);
}
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index f1bfe79feb8..ea774968f07 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -354,7 +354,10 @@ extern void DefineCustomEnumVariable(const char *name,
GucEnumAssignHook assign_hook,
GucShowHook show_hook);
-extern void EmitWarningsOnPlaceholders(const char *className);
+extern void MarkGUCPrefixReserved(const char *className);
+
+/* old name for MarkGUCPrefixReserved, for backwards compatibility: */
+#define EmitWarningsOnPlaceholders(className) MarkGUCPrefixReserved(className)
extern const char *GetConfigOption(const char *name, bool missing_ok,
bool restrict_privileged);
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 3f785b1e8d5..b5879c29471 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -455,7 +455,7 @@ _PG_init(void)
PGC_SUSET, 0,
NULL, NULL, NULL);
- EmitWarningsOnPlaceholders("plperl");
+ MarkGUCPrefixReserved("plperl");
/*
* Create hash tables.
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index b4b85092806..190d286f1c8 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -197,7 +197,7 @@ _PG_init(void)
plpgsql_extra_errors_assign_hook,
NULL);
- EmitWarningsOnPlaceholders("plpgsql");
+ MarkGUCPrefixReserved("plpgsql");
plpgsql_HashTableInit();
RegisterXactCallback(plpgsql_xact_cb, NULL);
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 7c045f45607..ab759833db1 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -474,8 +474,8 @@ _PG_init(void)
PGC_SUSET, 0,
NULL, NULL, NULL);
- EmitWarningsOnPlaceholders("pltcl");
- EmitWarningsOnPlaceholders("pltclu");
+ MarkGUCPrefixReserved("pltcl");
+ MarkGUCPrefixReserved("pltclu");
pltcl_pm_init_done = true;
}
diff --git a/src/test/modules/delay_execution/delay_execution.c b/src/test/modules/delay_execution/delay_execution.c
index ad50383bf8a..cf34e8c2d7d 100644
--- a/src/test/modules/delay_execution/delay_execution.c
+++ b/src/test/modules/delay_execution/delay_execution.c
@@ -91,7 +91,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("delay_execution");
+ MarkGUCPrefixReserved("delay_execution");
/* Install our hook */
prev_planner_hook = planner_hook;
diff --git a/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c b/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
index 3ba33e501c3..7c469fd57e8 100644
--- a/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
+++ b/src/test/modules/ssl_passphrase_callback/ssl_passphrase_func.c
@@ -49,7 +49,7 @@ _PG_init(void)
NULL,
NULL);
- EmitWarningsOnPlaceholders("ssl_passphrase");
+ MarkGUCPrefixReserved("ssl_passphrase");
if (ssl_passphrase)
openssl_tls_init_hook = set_rot13;
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 05ced63780e..48829df29c3 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -322,7 +322,7 @@ _PG_init(void)
0,
NULL, NULL, NULL);
- EmitWarningsOnPlaceholders("worker_spi");
+ MarkGUCPrefixReserved("worker_spi");
/* set up common data for all our workers */
memset(&worker, 0, sizeof(worker));
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 75b6bfbf116..3de6404ba5b 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -548,6 +548,17 @@ ERROR: invalid configuration parameter name "special.weird name"
DETAIL: Custom parameter names must be two or more simple identifiers separated by dots.
SHOW special."weird name";
ERROR: unrecognized configuration parameter "special.weird name"
+-- Check what happens when you try to set a "custom" GUC within the
+-- namespace of an extension.
+SET plpgsql.extra_foo_warnings = true; -- allowed if plpgsql is not loaded yet
+LOAD 'plpgsql'; -- this will throw a warning and delete the variable
+WARNING: invalid configuration parameter name "plpgsql.extra_foo_warnings", removing it
+DETAIL: "plpgsql" is now a reserved prefix.
+SET plpgsql.extra_foo_warnings = true; -- now, it's an error
+ERROR: invalid configuration parameter name "plpgsql.extra_foo_warnings"
+DETAIL: "plpgsql" is a reserved prefix.
+SHOW plpgsql.extra_foo_warnings;
+ERROR: unrecognized configuration parameter "plpgsql.extra_foo_warnings"
--
-- Test DISCARD TEMP
--
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index 3e2819449c2..d5db101e486 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -163,6 +163,13 @@ SHOW custom."bad-guc";
SET special."weird name" = 'foo'; -- could be allowed, but we choose not to
SHOW special."weird name";
+-- Check what happens when you try to set a "custom" GUC within the
+-- namespace of an extension.
+SET plpgsql.extra_foo_warnings = true; -- allowed if plpgsql is not loaded yet
+LOAD 'plpgsql'; -- this will throw a warning and delete the variable
+SET plpgsql.extra_foo_warnings = true; -- now, it's an error
+SHOW plpgsql.extra_foo_warnings;
+
--
-- Test DISCARD TEMP
--