@@ -10591,6 +10591,8 @@ ProcessGUCArray(ArrayType *array,
10591
10591
char * s ;
10592
10592
char * name ;
10593
10593
char * value ;
10594
+ char * namecopy ;
10595
+ char * valuecopy ;
10594
10596
10595
10597
d = array_ref (array , 1 , & i ,
10596
10598
-1 /* varlenarray */ ,
@@ -10615,13 +10617,18 @@ ProcessGUCArray(ArrayType *array,
10615
10617
continue ;
10616
10618
}
10617
10619
10618
- (void ) set_config_option (name , value ,
10620
+ /* free malloc'd strings immediately to avoid leak upon error */
10621
+ namecopy = pstrdup (name );
10622
+ free (name );
10623
+ valuecopy = pstrdup (value );
10624
+ free (value );
10625
+
10626
+ (void ) set_config_option (namecopy , valuecopy ,
10619
10627
context , source ,
10620
10628
action , true, 0 , false);
10621
10629
10622
- free (name );
10623
- if (value )
10624
- free (value );
10630
+ pfree (namecopy );
10631
+ pfree (valuecopy );
10625
10632
pfree (s );
10626
10633
}
10627
10634
}
@@ -11053,34 +11060,50 @@ static bool
11053
11060
call_string_check_hook (struct config_string * conf , char * * newval , void * * extra ,
11054
11061
GucSource source , int elevel )
11055
11062
{
11063
+ volatile bool result = true;
11064
+
11056
11065
/* Quick success if no hook */
11057
11066
if (!conf -> check_hook )
11058
11067
return true;
11059
11068
11060
- /* Reset variables that might be set by hook */
11061
- GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
11062
- GUC_check_errmsg_string = NULL ;
11063
- GUC_check_errdetail_string = NULL ;
11064
- GUC_check_errhint_string = NULL ;
11069
+ /*
11070
+ * If elevel is ERROR, or if the check_hook itself throws an elog
11071
+ * (undesirable, but not always avoidable), make sure we don't leak the
11072
+ * already-malloc'd newval string.
11073
+ */
11074
+ PG_TRY ();
11075
+ {
11076
+ /* Reset variables that might be set by hook */
11077
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
11078
+ GUC_check_errmsg_string = NULL ;
11079
+ GUC_check_errdetail_string = NULL ;
11080
+ GUC_check_errhint_string = NULL ;
11065
11081
11066
- if (!conf -> check_hook (newval , extra , source ))
11082
+ if (!conf -> check_hook (newval , extra , source ))
11083
+ {
11084
+ ereport (elevel ,
11085
+ (errcode (GUC_check_errcode_value ),
11086
+ GUC_check_errmsg_string ?
11087
+ errmsg_internal ("%s" , GUC_check_errmsg_string ) :
11088
+ errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
11089
+ conf -> gen .name , * newval ? * newval : "" ),
11090
+ GUC_check_errdetail_string ?
11091
+ errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
11092
+ GUC_check_errhint_string ?
11093
+ errhint ("%s" , GUC_check_errhint_string ) : 0 ));
11094
+ /* Flush any strings created in ErrorContext */
11095
+ FlushErrorState ();
11096
+ result = false;
11097
+ }
11098
+ }
11099
+ PG_CATCH ();
11067
11100
{
11068
- ereport (elevel ,
11069
- (errcode (GUC_check_errcode_value ),
11070
- GUC_check_errmsg_string ?
11071
- errmsg_internal ("%s" , GUC_check_errmsg_string ) :
11072
- errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
11073
- conf -> gen .name , * newval ? * newval : "" ),
11074
- GUC_check_errdetail_string ?
11075
- errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
11076
- GUC_check_errhint_string ?
11077
- errhint ("%s" , GUC_check_errhint_string ) : 0 ));
11078
- /* Flush any strings created in ErrorContext */
11079
- FlushErrorState ();
11080
- return false;
11101
+ free (* newval );
11102
+ PG_RE_THROW ();
11081
11103
}
11104
+ PG_END_TRY ();
11082
11105
11083
- return true ;
11106
+ return result ;
11084
11107
}
11085
11108
11086
11109
static bool
0 commit comments