@@ -250,6 +250,8 @@ static void write_auto_conf_file(int fd, const char *filename, ConfigVariable *h
250
250
static void replace_auto_config_value (ConfigVariable * * head_p , ConfigVariable * * tail_p ,
251
251
const char * name , const char * value );
252
252
static bool valid_custom_variable_name (const char * name );
253
+ static bool assignable_custom_variable_name (const char * name , bool skip_errors ,
254
+ int elevel );
253
255
static void do_serialize (char * * destptr , Size * maxbytes ,
254
256
const char * fmt ,...) pg_attribute_printf (3 , 4 );
255
257
static bool call_bool_check_hook (struct config_bool * conf , bool * newval ,
@@ -1063,7 +1065,7 @@ add_guc_variable(struct config_generic *var, int elevel)
1063
1065
*
1064
1066
* It must be two or more identifiers separated by dots, where the rules
1065
1067
* for what is an identifier agree with scan.l. (If you change this rule,
1066
- * adjust the errdetail in find_option ().)
1068
+ * adjust the errdetail in assignable_custom_variable_name ().)
1067
1069
*/
1068
1070
static bool
1069
1071
valid_custom_variable_name (const char * name )
@@ -1098,6 +1100,71 @@ valid_custom_variable_name(const char *name)
1098
1100
return saw_sep ;
1099
1101
}
1100
1102
1103
+ /*
1104
+ * Decide whether an unrecognized variable name is allowed to be SET.
1105
+ *
1106
+ * It must pass the syntactic rules of valid_custom_variable_name(),
1107
+ * and it must not be in any namespace already reserved by an extension.
1108
+ * (We make this separate from valid_custom_variable_name() because we don't
1109
+ * apply the reserved-namespace test when reading configuration files.)
1110
+ *
1111
+ * If valid, return true. Otherwise, return false if skip_errors is true,
1112
+ * else throw a suitable error at the specified elevel (and return false
1113
+ * if that's less than ERROR).
1114
+ */
1115
+ static bool
1116
+ assignable_custom_variable_name (const char * name , bool skip_errors , int elevel )
1117
+ {
1118
+ /* If there's no separator, it can't be a custom variable */
1119
+ const char * sep = strchr (name , GUC_QUALIFIER_SEPARATOR );
1120
+
1121
+ if (sep != NULL )
1122
+ {
1123
+ size_t classLen = sep - name ;
1124
+ ListCell * lc ;
1125
+
1126
+ /* The name must be syntactically acceptable ... */
1127
+ if (!valid_custom_variable_name (name ))
1128
+ {
1129
+ if (!skip_errors )
1130
+ ereport (elevel ,
1131
+ (errcode (ERRCODE_INVALID_NAME ),
1132
+ errmsg ("invalid configuration parameter name \"%s\"" ,
1133
+ name ),
1134
+ errdetail ("Custom parameter names must be two or more simple identifiers separated by dots." )));
1135
+ return false;
1136
+ }
1137
+ /* ... and it must not match any previously-reserved prefix */
1138
+ foreach (lc , reserved_class_prefix )
1139
+ {
1140
+ const char * rcprefix = lfirst (lc );
1141
+
1142
+ if (strlen (rcprefix ) == classLen &&
1143
+ strncmp (name , rcprefix , classLen ) == 0 )
1144
+ {
1145
+ if (!skip_errors )
1146
+ ereport (elevel ,
1147
+ (errcode (ERRCODE_INVALID_NAME ),
1148
+ errmsg ("invalid configuration parameter name \"%s\"" ,
1149
+ name ),
1150
+ errdetail ("\"%s\" is a reserved prefix." ,
1151
+ rcprefix )));
1152
+ return false;
1153
+ }
1154
+ }
1155
+ /* OK to create it */
1156
+ return true;
1157
+ }
1158
+
1159
+ /* Unrecognized single-part name */
1160
+ if (!skip_errors )
1161
+ ereport (elevel ,
1162
+ (errcode (ERRCODE_UNDEFINED_OBJECT ),
1163
+ errmsg ("unrecognized configuration parameter \"%s\"" ,
1164
+ name )));
1165
+ return false;
1166
+ }
1167
+
1101
1168
/*
1102
1169
* Create and add a placeholder variable for a custom variable name.
1103
1170
*/
@@ -1191,52 +1258,15 @@ find_option(const char *name, bool create_placeholders, bool skip_errors,
1191
1258
if (create_placeholders )
1192
1259
{
1193
1260
/*
1194
- * Check if the name is valid, and if so, add a placeholder. If it
1195
- * doesn't contain a separator, don't assume that it was meant to be a
1196
- * placeholder.
1261
+ * Check if the name is valid, and if so, add a placeholder.
1197
1262
*/
1198
- const char * sep = strchr (name , GUC_QUALIFIER_SEPARATOR );
1199
-
1200
- if (sep != NULL )
1201
- {
1202
- size_t classLen = sep - name ;
1203
- ListCell * lc ;
1204
-
1205
- /* The name must be syntactically acceptable ... */
1206
- if (!valid_custom_variable_name (name ))
1207
- {
1208
- if (!skip_errors )
1209
- ereport (elevel ,
1210
- (errcode (ERRCODE_INVALID_NAME ),
1211
- errmsg ("invalid configuration parameter name \"%s\"" ,
1212
- name ),
1213
- errdetail ("Custom parameter names must be two or more simple identifiers separated by dots." )));
1214
- return NULL ;
1215
- }
1216
- /* ... and it must not match any previously-reserved prefix */
1217
- foreach (lc , reserved_class_prefix )
1218
- {
1219
- const char * rcprefix = lfirst (lc );
1220
-
1221
- if (strlen (rcprefix ) == classLen &&
1222
- strncmp (name , rcprefix , classLen ) == 0 )
1223
- {
1224
- if (!skip_errors )
1225
- ereport (elevel ,
1226
- (errcode (ERRCODE_INVALID_NAME ),
1227
- errmsg ("invalid configuration parameter name \"%s\"" ,
1228
- name ),
1229
- errdetail ("\"%s\" is a reserved prefix." ,
1230
- rcprefix )));
1231
- return NULL ;
1232
- }
1233
- }
1234
- /* OK, create it */
1263
+ if (assignable_custom_variable_name (name , skip_errors , elevel ))
1235
1264
return add_placeholder_variable (name , elevel );
1236
- }
1265
+ else
1266
+ return NULL ; /* error message, if any, already emitted */
1237
1267
}
1238
1268
1239
- /* Unknown name */
1269
+ /* Unknown name and we're not supposed to make a placeholder */
1240
1270
if (!skip_errors )
1241
1271
ereport (elevel ,
1242
1272
(errcode (ERRCODE_UNDEFINED_OBJECT ),
@@ -1369,18 +1399,16 @@ convert_GUC_name_for_parameter_acl(const char *name)
1369
1399
/*
1370
1400
* Check whether we should allow creation of a pg_parameter_acl entry
1371
1401
* for the given name. (This can be applied either before or after
1372
- * canonicalizing it.)
1402
+ * canonicalizing it.) Throws error if not.
1373
1403
*/
1374
- bool
1404
+ void
1375
1405
check_GUC_name_for_parameter_acl (const char * name )
1376
1406
{
1377
1407
/* OK if the GUC exists. */
1378
- if (find_option (name , false, true, DEBUG1 ) != NULL )
1379
- return true ;
1408
+ if (find_option (name , false, true, DEBUG5 ) != NULL )
1409
+ return ;
1380
1410
/* Otherwise, it'd better be a valid custom GUC name. */
1381
- if (valid_custom_variable_name (name ))
1382
- return true;
1383
- return false;
1411
+ (void ) assignable_custom_variable_name (name , false, ERROR );
1384
1412
}
1385
1413
1386
1414
/*
@@ -4515,52 +4543,64 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
4515
4543
{
4516
4544
struct config_generic * record ;
4517
4545
4518
- record = find_option (name , false, false, ERROR );
4519
- Assert (record != NULL );
4520
-
4521
- /*
4522
- * Don't allow parameters that can't be set in configuration files to
4523
- * be set in PG_AUTOCONF_FILENAME file.
4524
- */
4525
- if ((record -> context == PGC_INTERNAL ) ||
4526
- (record -> flags & GUC_DISALLOW_IN_FILE ) ||
4527
- (record -> flags & GUC_DISALLOW_IN_AUTO_FILE ))
4528
- ereport (ERROR ,
4529
- (errcode (ERRCODE_CANT_CHANGE_RUNTIME_PARAM ),
4530
- errmsg ("parameter \"%s\" cannot be changed" ,
4531
- name )));
4532
-
4533
- /*
4534
- * If a value is specified, verify that it's sane.
4535
- */
4536
- if (value )
4546
+ /* We don't want to create a placeholder if there's not one already */
4547
+ record = find_option (name , false, true, DEBUG5 );
4548
+ if (record != NULL )
4537
4549
{
4538
- union config_var_val newval ;
4539
- void * newextra = NULL ;
4540
-
4541
- /* Check that it's acceptable for the indicated parameter */
4542
- if (! parse_and_validate_value (record , name , value ,
4543
- PGC_S_FILE , ERROR ,
4544
- & newval , & newextra ))
4550
+ /*
4551
+ * Don't allow parameters that can't be set in configuration files
4552
+ * to be set in PG_AUTOCONF_FILENAME file.
4553
+ */
4554
+ if ((record -> context == PGC_INTERNAL ) ||
4555
+ ( record -> flags & GUC_DISALLOW_IN_FILE ) ||
4556
+ ( record -> flags & GUC_DISALLOW_IN_AUTO_FILE ))
4545
4557
ereport (ERROR ,
4546
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4547
- errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
4548
- name , value )));
4558
+ (errcode (ERRCODE_CANT_CHANGE_RUNTIME_PARAM ),
4559
+ errmsg ("parameter \"%s\" cannot be changed" ,
4560
+ name )));
4561
+
4562
+ /*
4563
+ * If a value is specified, verify that it's sane.
4564
+ */
4565
+ if (value )
4566
+ {
4567
+ union config_var_val newval ;
4568
+ void * newextra = NULL ;
4549
4569
4550
- if (record -> vartype == PGC_STRING && newval .stringval != NULL )
4551
- guc_free (newval .stringval );
4552
- guc_free (newextra );
4570
+ if (!parse_and_validate_value (record , name , value ,
4571
+ PGC_S_FILE , ERROR ,
4572
+ & newval , & newextra ))
4573
+ ereport (ERROR ,
4574
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4575
+ errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
4576
+ name , value )));
4553
4577
4578
+ if (record -> vartype == PGC_STRING && newval .stringval != NULL )
4579
+ guc_free (newval .stringval );
4580
+ guc_free (newextra );
4581
+ }
4582
+ }
4583
+ else
4584
+ {
4554
4585
/*
4555
- * We must also reject values containing newlines, because the
4556
- * grammar for config files doesn't support embedded newlines in
4557
- * string literals.
4586
+ * Variable not known; check we'd be allowed to create it. (We
4587
+ * cannot validate the value, but that's fine. A non-core GUC in
4588
+ * the config file cannot cause postmaster start to fail, so we
4589
+ * don't have to be too tense about possibly installing a bad
4590
+ * value.)
4558
4591
*/
4559
- if (strchr (value , '\n' ))
4560
- ereport (ERROR ,
4561
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4562
- errmsg ("parameter value for ALTER SYSTEM must not contain a newline" )));
4592
+ (void ) assignable_custom_variable_name (name , false, ERROR );
4563
4593
}
4594
+
4595
+ /*
4596
+ * We must also reject values containing newlines, because the grammar
4597
+ * for config files doesn't support embedded newlines in string
4598
+ * literals.
4599
+ */
4600
+ if (value && strchr (value , '\n' ))
4601
+ ereport (ERROR ,
4602
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
4603
+ errmsg ("parameter value for ALTER SYSTEM must not contain a newline" )));
4564
4604
}
4565
4605
4566
4606
/*
0 commit comments