@@ -10361,6 +10361,8 @@ ProcessGUCArray(ArrayType *array,
10361
10361
char * s ;
10362
10362
char * name ;
10363
10363
char * value ;
10364
+ char * namecopy ;
10365
+ char * valuecopy ;
10364
10366
10365
10367
d = array_ref (array , 1 , & i ,
10366
10368
-1 /* varlenarray */ ,
@@ -10385,13 +10387,18 @@ ProcessGUCArray(ArrayType *array,
10385
10387
continue ;
10386
10388
}
10387
10389
10388
- (void ) set_config_option (name , value ,
10390
+ /* free malloc'd strings immediately to avoid leak upon error */
10391
+ namecopy = pstrdup (name );
10392
+ free (name );
10393
+ valuecopy = pstrdup (value );
10394
+ free (value );
10395
+
10396
+ (void ) set_config_option (namecopy , valuecopy ,
10389
10397
context , source ,
10390
10398
action , true, 0 , false);
10391
10399
10392
- free (name );
10393
- if (value )
10394
- free (value );
10400
+ pfree (namecopy );
10401
+ pfree (valuecopy );
10395
10402
pfree (s );
10396
10403
}
10397
10404
}
@@ -10823,34 +10830,50 @@ static bool
10823
10830
call_string_check_hook (struct config_string * conf , char * * newval , void * * extra ,
10824
10831
GucSource source , int elevel )
10825
10832
{
10833
+ volatile bool result = true;
10834
+
10826
10835
/* Quick success if no hook */
10827
10836
if (!conf -> check_hook )
10828
10837
return true;
10829
10838
10830
- /* Reset variables that might be set by hook */
10831
- GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
10832
- GUC_check_errmsg_string = NULL ;
10833
- GUC_check_errdetail_string = NULL ;
10834
- GUC_check_errhint_string = NULL ;
10839
+ /*
10840
+ * If elevel is ERROR, or if the check_hook itself throws an elog
10841
+ * (undesirable, but not always avoidable), make sure we don't leak the
10842
+ * already-malloc'd newval string.
10843
+ */
10844
+ PG_TRY ();
10845
+ {
10846
+ /* Reset variables that might be set by hook */
10847
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
10848
+ GUC_check_errmsg_string = NULL ;
10849
+ GUC_check_errdetail_string = NULL ;
10850
+ GUC_check_errhint_string = NULL ;
10835
10851
10836
- if (!conf -> check_hook (newval , extra , source ))
10852
+ if (!conf -> check_hook (newval , extra , source ))
10853
+ {
10854
+ ereport (elevel ,
10855
+ (errcode (GUC_check_errcode_value ),
10856
+ GUC_check_errmsg_string ?
10857
+ errmsg_internal ("%s" , GUC_check_errmsg_string ) :
10858
+ errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
10859
+ conf -> gen .name , * newval ? * newval : "" ),
10860
+ GUC_check_errdetail_string ?
10861
+ errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
10862
+ GUC_check_errhint_string ?
10863
+ errhint ("%s" , GUC_check_errhint_string ) : 0 ));
10864
+ /* Flush any strings created in ErrorContext */
10865
+ FlushErrorState ();
10866
+ result = false;
10867
+ }
10868
+ }
10869
+ PG_CATCH ();
10837
10870
{
10838
- ereport (elevel ,
10839
- (errcode (GUC_check_errcode_value ),
10840
- GUC_check_errmsg_string ?
10841
- errmsg_internal ("%s" , GUC_check_errmsg_string ) :
10842
- errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
10843
- conf -> gen .name , * newval ? * newval : "" ),
10844
- GUC_check_errdetail_string ?
10845
- errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
10846
- GUC_check_errhint_string ?
10847
- errhint ("%s" , GUC_check_errhint_string ) : 0 ));
10848
- /* Flush any strings created in ErrorContext */
10849
- FlushErrorState ();
10850
- return false;
10871
+ free (* newval );
10872
+ PG_RE_THROW ();
10851
10873
}
10874
+ PG_END_TRY ();
10852
10875
10853
- return true ;
10876
+ return result ;
10854
10877
}
10855
10878
10856
10879
static bool
0 commit comments