@@ -9412,6 +9412,8 @@ ProcessGUCArray(ArrayType *array,
9412
9412
char * s ;
9413
9413
char * name ;
9414
9414
char * value ;
9415
+ char * namecopy ;
9416
+ char * valuecopy ;
9415
9417
9416
9418
d = array_ref (array , 1 , & i ,
9417
9419
-1 /* varlenarray */ ,
@@ -9436,13 +9438,18 @@ ProcessGUCArray(ArrayType *array,
9436
9438
continue ;
9437
9439
}
9438
9440
9439
- (void ) set_config_option (name , value ,
9441
+ /* free malloc'd strings immediately to avoid leak upon error */
9442
+ namecopy = pstrdup (name );
9443
+ free (name );
9444
+ valuecopy = pstrdup (value );
9445
+ free (value );
9446
+
9447
+ (void ) set_config_option (namecopy , valuecopy ,
9440
9448
context , source ,
9441
9449
action , true, 0 , false);
9442
9450
9443
- free (name );
9444
- if (value )
9445
- free (value );
9451
+ pfree (namecopy );
9452
+ pfree (valuecopy );
9446
9453
pfree (s );
9447
9454
}
9448
9455
}
@@ -9874,34 +9881,50 @@ static bool
9874
9881
call_string_check_hook (struct config_string * conf , char * * newval , void * * extra ,
9875
9882
GucSource source , int elevel )
9876
9883
{
9884
+ volatile bool result = true;
9885
+
9877
9886
/* Quick success if no hook */
9878
9887
if (!conf -> check_hook )
9879
9888
return true;
9880
9889
9881
- /* Reset variables that might be set by hook */
9882
- GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
9883
- GUC_check_errmsg_string = NULL ;
9884
- GUC_check_errdetail_string = NULL ;
9885
- GUC_check_errhint_string = NULL ;
9890
+ /*
9891
+ * If elevel is ERROR, or if the check_hook itself throws an elog
9892
+ * (undesirable, but not always avoidable), make sure we don't leak the
9893
+ * already-malloc'd newval string.
9894
+ */
9895
+ PG_TRY ();
9896
+ {
9897
+ /* Reset variables that might be set by hook */
9898
+ GUC_check_errcode_value = ERRCODE_INVALID_PARAMETER_VALUE ;
9899
+ GUC_check_errmsg_string = NULL ;
9900
+ GUC_check_errdetail_string = NULL ;
9901
+ GUC_check_errhint_string = NULL ;
9886
9902
9887
- if (!(* conf -> check_hook ) (newval , extra , source ))
9903
+ if (!(* conf -> check_hook ) (newval , extra , source ))
9904
+ {
9905
+ ereport (elevel ,
9906
+ (errcode (GUC_check_errcode_value ),
9907
+ GUC_check_errmsg_string ?
9908
+ errmsg_internal ("%s" , GUC_check_errmsg_string ) :
9909
+ errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
9910
+ conf -> gen .name , * newval ? * newval : "" ),
9911
+ GUC_check_errdetail_string ?
9912
+ errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
9913
+ GUC_check_errhint_string ?
9914
+ errhint ("%s" , GUC_check_errhint_string ) : 0 ));
9915
+ /* Flush any strings created in ErrorContext */
9916
+ FlushErrorState ();
9917
+ result = false;
9918
+ }
9919
+ }
9920
+ PG_CATCH ();
9888
9921
{
9889
- ereport (elevel ,
9890
- (errcode (GUC_check_errcode_value ),
9891
- GUC_check_errmsg_string ?
9892
- errmsg_internal ("%s" , GUC_check_errmsg_string ) :
9893
- errmsg ("invalid value for parameter \"%s\": \"%s\"" ,
9894
- conf -> gen .name , * newval ? * newval : "" ),
9895
- GUC_check_errdetail_string ?
9896
- errdetail_internal ("%s" , GUC_check_errdetail_string ) : 0 ,
9897
- GUC_check_errhint_string ?
9898
- errhint ("%s" , GUC_check_errhint_string ) : 0 ));
9899
- /* Flush any strings created in ErrorContext */
9900
- FlushErrorState ();
9901
- return false;
9922
+ free (* newval );
9923
+ PG_RE_THROW ();
9902
9924
}
9925
+ PG_END_TRY ();
9903
9926
9904
- return true ;
9927
+ return result ;
9905
9928
}
9906
9929
9907
9930
static bool
0 commit comments