@@ -5334,6 +5334,45 @@ add_guc_variable(struct config_generic *var, int elevel)
5334
5334
return true;
5335
5335
}
5336
5336
5337
+ /*
5338
+ * Decide whether a proposed custom variable name is allowed.
5339
+ *
5340
+ * It must be "identifier.identifier", where the rules for what is an
5341
+ * identifier agree with scan.l.
5342
+ */
5343
+ static bool
5344
+ valid_custom_variable_name (const char * name )
5345
+ {
5346
+ int num_sep = 0 ;
5347
+ bool name_start = true;
5348
+
5349
+ for (const char * p = name ; * p ; p ++ )
5350
+ {
5351
+ if (* p == GUC_QUALIFIER_SEPARATOR )
5352
+ {
5353
+ if (name_start )
5354
+ return false; /* empty name component */
5355
+ num_sep ++ ;
5356
+ name_start = true;
5357
+ }
5358
+ else if (strchr ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
5359
+ "abcdefghijklmnopqrstuvwxyz" , * p ) != NULL ||
5360
+ IS_HIGHBIT_SET (* p ))
5361
+ {
5362
+ /* okay as first or non-first character */
5363
+ name_start = false;
5364
+ }
5365
+ else if (!name_start && strchr ("0123456789_$" , * p ) != NULL )
5366
+ /* okay as non-first character */ ;
5367
+ else
5368
+ return false;
5369
+ }
5370
+ if (name_start )
5371
+ return false; /* empty name component */
5372
+ /* OK if we had exactly one separator */
5373
+ return (num_sep == 1 );
5374
+ }
5375
+
5337
5376
/*
5338
5377
* Create and add a placeholder variable for a custom variable name.
5339
5378
*/
@@ -5381,12 +5420,23 @@ add_placeholder_variable(const char *name, int elevel)
5381
5420
}
5382
5421
5383
5422
/*
5384
- * Look up option NAME. If it exists, return a pointer to its record,
5385
- * else return NULL. If create_placeholders is true, we'll create a
5386
- * placeholder record for a valid-looking custom variable name.
5423
+ * Look up option "name". If it exists, return a pointer to its record.
5424
+ * Otherwise, if create_placeholders is true and name is a valid-looking
5425
+ * custom variable name, we'll create and return a placeholder record.
5426
+ * Otherwise, if skip_errors is true, then we silently return NULL for
5427
+ * an unrecognized or invalid name. Otherwise, the error is reported at
5428
+ * error level elevel (and we return NULL if that's less than ERROR).
5429
+ *
5430
+ * Note: internal errors, primarily out-of-memory, draw an elevel-level
5431
+ * report and NULL return regardless of skip_errors. Hence, callers must
5432
+ * handle a NULL return whenever elevel < ERROR, but they should not need
5433
+ * to emit any additional error message. (In practice, internal errors
5434
+ * can only happen when create_placeholders is true, so callers passing
5435
+ * false need not think terribly hard about this.)
5387
5436
*/
5388
5437
static struct config_generic *
5389
- find_option (const char * name , bool create_placeholders , int elevel )
5438
+ find_option (const char * name , bool create_placeholders , bool skip_errors ,
5439
+ int elevel )
5390
5440
{
5391
5441
const char * * key = & name ;
5392
5442
struct config_generic * * res ;
@@ -5414,19 +5464,38 @@ find_option(const char *name, bool create_placeholders, int elevel)
5414
5464
for (i = 0 ; map_old_guc_names [i ] != NULL ; i += 2 )
5415
5465
{
5416
5466
if (guc_name_compare (name , map_old_guc_names [i ]) == 0 )
5417
- return find_option (map_old_guc_names [i + 1 ], false, elevel );
5467
+ return find_option (map_old_guc_names [i + 1 ], false,
5468
+ skip_errors , elevel );
5418
5469
}
5419
5470
5420
5471
if (create_placeholders )
5421
5472
{
5422
5473
/*
5423
- * Check if the name is qualified, and if so, add a placeholder.
5474
+ * Check if the name is valid, and if so, add a placeholder. If it
5475
+ * doesn't contain a separator, don't assume that it was meant to be a
5476
+ * placeholder.
5424
5477
*/
5425
5478
if (strchr (name , GUC_QUALIFIER_SEPARATOR ) != NULL )
5426
- return add_placeholder_variable (name , elevel );
5479
+ {
5480
+ if (valid_custom_variable_name (name ))
5481
+ return add_placeholder_variable (name , elevel );
5482
+ /* A special error message seems desirable here */
5483
+ if (!skip_errors )
5484
+ ereport (elevel ,
5485
+ (errcode (ERRCODE_INVALID_NAME ),
5486
+ errmsg ("invalid configuration parameter name \"%s\"" ,
5487
+ name ),
5488
+ errdetail ("Custom parameter names must be of the form \"identifier.identifier\"." )));
5489
+ return NULL ;
5490
+ }
5427
5491
}
5428
5492
5429
5493
/* Unknown name */
5494
+ if (!skip_errors )
5495
+ ereport (elevel ,
5496
+ (errcode (ERRCODE_UNDEFINED_OBJECT ),
5497
+ errmsg ("unrecognized configuration parameter \"%s\"" ,
5498
+ name )));
5430
5499
return NULL ;
5431
5500
}
5432
5501
@@ -6444,7 +6513,7 @@ ReportChangedGUCOptions(void)
6444
6513
{
6445
6514
struct config_generic * record ;
6446
6515
6447
- record = find_option ("in_hot_standby" , false, ERROR );
6516
+ record = find_option ("in_hot_standby" , false, false, ERROR );
6448
6517
Assert (record != NULL );
6449
6518
record -> status |= GUC_NEEDS_REPORT ;
6450
6519
report_needed = true;
@@ -7218,14 +7287,9 @@ set_config_option(const char *name, const char *value,
7218
7287
(errcode (ERRCODE_INVALID_TRANSACTION_STATE ),
7219
7288
errmsg ("cannot set parameters during a parallel operation" )));
7220
7289
7221
- record = find_option (name , true, elevel );
7290
+ record = find_option (name , true, false, elevel );
7222
7291
if (record == NULL )
7223
- {
7224
- ereport (elevel ,
7225
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
7226
- errmsg ("unrecognized configuration parameter \"%s\"" , name )));
7227
7292
return 0 ;
7228
- }
7229
7293
7230
7294
/*
7231
7295
* Check if the option can be set at this time. See guc.h for the precise
@@ -7947,10 +8011,10 @@ set_config_sourcefile(const char *name, char *sourcefile, int sourceline)
7947
8011
*/
7948
8012
elevel = IsUnderPostmaster ? DEBUG3 : LOG ;
7949
8013
7950
- record = find_option (name , true, elevel );
8014
+ record = find_option (name , true, false, elevel );
7951
8015
/* should not happen */
7952
8016
if (record == NULL )
7953
- elog ( ERROR , "unrecognized configuration parameter \"%s\"" , name ) ;
8017
+ return ;
7954
8018
7955
8019
sourcefile = guc_strdup (elevel , sourcefile );
7956
8020
if (record -> sourcefile )
@@ -7999,16 +8063,9 @@ GetConfigOption(const char *name, bool missing_ok, bool restrict_privileged)
7999
8063
struct config_generic * record ;
8000
8064
static char buffer [256 ];
8001
8065
8002
- record = find_option (name , false, ERROR );
8066
+ record = find_option (name , false, missing_ok , ERROR );
8003
8067
if (record == NULL )
8004
- {
8005
- if (missing_ok )
8006
- return NULL ;
8007
- ereport (ERROR ,
8008
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
8009
- errmsg ("unrecognized configuration parameter \"%s\"" ,
8010
- name )));
8011
- }
8068
+ return NULL ;
8012
8069
if (restrict_privileged &&
8013
8070
(record -> flags & GUC_SUPERUSER_ONLY ) &&
8014
8071
!is_member_of_role (GetUserId (), ROLE_PG_READ_ALL_SETTINGS ))
@@ -8055,11 +8112,8 @@ GetConfigOptionResetString(const char *name)
8055
8112
struct config_generic * record ;
8056
8113
static char buffer [256 ];
8057
8114
8058
- record = find_option (name , false, ERROR );
8059
- if (record == NULL )
8060
- ereport (ERROR ,
8061
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
8062
- errmsg ("unrecognized configuration parameter \"%s\"" , name )));
8115
+ record = find_option (name , false, false, ERROR );
8116
+ Assert (record != NULL );
8063
8117
if ((record -> flags & GUC_SUPERUSER_ONLY ) &&
8064
8118
!is_member_of_role (GetUserId (), ROLE_PG_READ_ALL_SETTINGS ))
8065
8119
ereport (ERROR ,
@@ -8103,16 +8157,9 @@ GetConfigOptionFlags(const char *name, bool missing_ok)
8103
8157
{
8104
8158
struct config_generic * record ;
8105
8159
8106
- record = find_option (name , false, WARNING );
8160
+ record = find_option (name , false, missing_ok , ERROR );
8107
8161
if (record == NULL )
8108
- {
8109
- if (missing_ok )
8110
- return 0 ;
8111
- ereport (ERROR ,
8112
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
8113
- errmsg ("unrecognized configuration parameter \"%s\"" ,
8114
- name )));
8115
- }
8162
+ return 0 ;
8116
8163
return record -> flags ;
8117
8164
}
8118
8165
@@ -8144,7 +8191,7 @@ flatten_set_variable_args(const char *name, List *args)
8144
8191
* Get flags for the variable; if it's not known, use default flags.
8145
8192
* (Caller might throw error later, but not our business to do so here.)
8146
8193
*/
8147
- record = find_option (name , false, WARNING );
8194
+ record = find_option (name , false, true, WARNING );
8148
8195
if (record )
8149
8196
flags = record -> flags ;
8150
8197
else
@@ -8439,12 +8486,8 @@ AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
8439
8486
{
8440
8487
struct config_generic * record ;
8441
8488
8442
- record = find_option (name , false, ERROR );
8443
- if (record == NULL )
8444
- ereport (ERROR ,
8445
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
8446
- errmsg ("unrecognized configuration parameter \"%s\"" ,
8447
- name )));
8489
+ record = find_option (name , false, false, ERROR );
8490
+ Assert (record != NULL );
8448
8491
8449
8492
/*
8450
8493
* Don't allow parameters that can't be set in configuration files to
@@ -9460,19 +9503,12 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
9460
9503
{
9461
9504
struct config_generic * record ;
9462
9505
9463
- record = find_option (name , false, ERROR );
9506
+ record = find_option (name , false, missing_ok , ERROR );
9464
9507
if (record == NULL )
9465
9508
{
9466
- if (missing_ok )
9467
- {
9468
- if (varname )
9469
- * varname = NULL ;
9470
- return NULL ;
9471
- }
9472
-
9473
- ereport (ERROR ,
9474
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
9475
- errmsg ("unrecognized configuration parameter \"%s\"" , name )));
9509
+ if (varname )
9510
+ * varname = NULL ;
9511
+ return NULL ;
9476
9512
}
9477
9513
9478
9514
if ((record -> flags & GUC_SUPERUSER_ONLY ) &&
@@ -10318,7 +10354,7 @@ read_nondefault_variables(void)
10318
10354
if ((varname = read_string_with_null (fp )) == NULL )
10319
10355
break ;
10320
10356
10321
- if ((record = find_option (varname , true, FATAL )) == NULL )
10357
+ if ((record = find_option (varname , true, false, FATAL )) == NULL )
10322
10358
elog (FATAL , "failed to locate variable \"%s\" in exec config params file" , varname );
10323
10359
10324
10360
if ((varvalue = read_string_with_null (fp )) == NULL )
@@ -11008,7 +11044,7 @@ GUCArrayAdd(ArrayType *array, const char *name, const char *value)
11008
11044
(void ) validate_option_array_item (name , value , false);
11009
11045
11010
11046
/* normalize name (converts obsolete GUC names to modern spellings) */
11011
- record = find_option (name , false, WARNING );
11047
+ record = find_option (name , false, true, WARNING );
11012
11048
if (record )
11013
11049
name = record -> name ;
11014
11050
@@ -11087,7 +11123,7 @@ GUCArrayDelete(ArrayType *array, const char *name)
11087
11123
(void ) validate_option_array_item (name , NULL , false);
11088
11124
11089
11125
/* normalize name (converts obsolete GUC names to modern spellings) */
11090
- record = find_option (name , false, WARNING );
11126
+ record = find_option (name , false, true, WARNING );
11091
11127
if (record )
11092
11128
name = record -> name ;
11093
11129
@@ -11234,7 +11270,7 @@ validate_option_array_item(const char *name, const char *value,
11234
11270
* SUSET and user is superuser).
11235
11271
*
11236
11272
* name is not known, but exists or can be created as a placeholder (i.e.,
11237
- * it has a prefixed name). We allow this case if you're a superuser,
11273
+ * it has a valid custom name). We allow this case if you're a superuser,
11238
11274
* otherwise not. Superusers are assumed to know what they're doing. We
11239
11275
* can't allow it for other users, because when the placeholder is
11240
11276
* resolved it might turn out to be a SUSET variable;
@@ -11243,16 +11279,11 @@ validate_option_array_item(const char *name, const char *value,
11243
11279
* name is not known and can't be created as a placeholder. Throw error,
11244
11280
* unless skipIfNoPermissions is true, in which case return false.
11245
11281
*/
11246
- gconf = find_option (name , true, WARNING );
11282
+ gconf = find_option (name , true, skipIfNoPermissions , ERROR );
11247
11283
if (!gconf )
11248
11284
{
11249
11285
/* not known, failed to make a placeholder */
11250
- if (skipIfNoPermissions )
11251
- return false;
11252
- ereport (ERROR ,
11253
- (errcode (ERRCODE_UNDEFINED_OBJECT ),
11254
- errmsg ("unrecognized configuration parameter \"%s\"" ,
11255
- name )));
11286
+ return false;
11256
11287
}
11257
11288
11258
11289
if (gconf -> flags & GUC_CUSTOM_PLACEHOLDER )
0 commit comments