@@ -10773,6 +10773,8 @@ ProcessGUCArray(ArrayType *array,
10773
10773
char * s ;
10774
10774
char * name ;
10775
10775
char * value ;
10776
+ char * namecopy ;
10777
+ char * valuecopy ;
10776
10778
10777
10779
d = array_ref (array , 1 , & i ,
10778
10780
-1 /* varlenarray */ ,
@@ -10797,13 +10799,18 @@ ProcessGUCArray(ArrayType *array,
10797
10799
continue ;
10798
10800
}
10799
10801
10800
- (void ) set_config_option (name , value ,
10802
+ /* free malloc'd strings immediately to avoid leak upon error */
10803
+ namecopy = pstrdup (name );
10804
+ free (name );
10805
+ valuecopy = pstrdup (value );
10806
+ free (value );
10807
+
10808
+ (void ) set_config_option (namecopy , valuecopy ,
10801
10809
context , source ,
10802
10810
action , true, 0 , false);
10803
10811
10804
- free (name );
10805
- if (value )
10806
- free (value );
10812
+ pfree (namecopy );
10813
+ pfree (valuecopy );
10807
10814
pfree (s );
10808
10815
}
10809
10816
}
@@ -11235,34 +11242,50 @@ static bool
11235
11242
call_string_check_hook (struct config_string * conf , char * * newval , void * * extra ,
11236
11243
GucSource source , int elevel )
11237
11244
{
11245
+ volatile bool result = true;
11246
+
11238
11247
/* Quick success if no hook */
11239
11248
if (!conf -> check_hook )
11240
11249
return true;
11241
11250
11242
- /* Reset variables that might be set by hook */
11243
- GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
11244
- GUC_check_errmsg_string = NULL ;
11245
- GUC_check_errdetail_string = NULL ;
11246
- GUC_check_errhint_string = NULL ;
11251
+ /*
11252
+ * If elevel is ERROR, or if the check_hook itself throws an elog
11253
+ * (undesirable, but not always avoidable), make sure we don't leak the
11254
+ * already-malloc'd newval string.
11255
+ */
11256
+ PG_TRY ();
11257
+ {
11258
+ /* Reset variables that might be set by hook */
11259
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
11260
+ GUC_check_errmsg_string = NULL ;
11261
+ GUC_check_errdetail_string = NULL ;
11262
+ GUC_check_errhint_string = NULL ;
11247
11263
11248
- if (!conf -> check_hook (newval , extra , source ))
11264
+ if (!conf -> check_hook (newval , extra , source ))
11265
+ {
11266
+ ereport (elevel ,
11267
+ (errcode (GUC_check_errcode_value ),
11268
+ GUC_check_errmsg_string ?
11269
+ errmsg_internal ("%s" , GUC_check_errmsg_string ) :
11270
+ errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
11271
+ conf -> gen .name , * newval ? * newval : "" ),
11272
+ GUC_check_errdetail_string ?
11273
+ errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
11274
+ GUC_check_errhint_string ?
11275
+ errhint ("%s" , GUC_check_errhint_string ) : 0 ));
11276
+ /* Flush any strings created in ErrorContext */
11277
+ FlushErrorState ();
11278
+ result = false;
11279
+ }
11280
+ }
11281
+ PG_CATCH ();
11249
11282
{
11250
- ereport (elevel ,
11251
- (errcode (GUC_check_errcode_value ),
11252
- GUC_check_errmsg_string ?
11253
- errmsg_internal ("%s" , GUC_check_errmsg_string ) :
11254
- errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
11255
- conf -> gen .name , * newval ? * newval : "" ),
11256
- GUC_check_errdetail_string ?
11257
- errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
11258
- GUC_check_errhint_string ?
11259
- errhint ("%s" , GUC_check_errhint_string ) : 0 ));
11260
- /* Flush any strings created in ErrorContext */
11261
- FlushErrorState ();
11262
- return false;
11283
+ free (* newval );
11284
+ PG_RE_THROW ();
11263
11285
}
11286
+ PG_END_TRY ();
11264
11287
11265
- return true ;
11288
+ return result ;
11266
11289
}
11267
11290
11268
11291
static bool
0 commit comments