@@ -10773,6 +10773,8 @@ ProcessGUCArray(ArrayType *array,
1077310773 char * s ;
1077410774 char * name ;
1077510775 char * value ;
10776+ char * namecopy ;
10777+ char * valuecopy ;
1077610778
1077710779 d = array_ref (array , 1 , & i ,
1077810780 -1 /* varlenarray */ ,
@@ -10797,13 +10799,18 @@ ProcessGUCArray(ArrayType *array,
1079710799 continue ;
1079810800 }
1079910801
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 ,
1080110809 context , source ,
1080210810 action , true, 0 , false);
1080310811
10804- free (name );
10805- if (value )
10806- free (value );
10812+ pfree (namecopy );
10813+ pfree (valuecopy );
1080710814 pfree (s );
1080810815 }
1080910816}
@@ -11235,34 +11242,50 @@ static bool
1123511242call_string_check_hook (struct config_string * conf , char * * newval , void * * extra ,
1123611243 GucSource source , int elevel )
1123711244{
11245+ volatile bool result = true;
11246+
1123811247 /* Quick success if no hook */
1123911248 if (!conf -> check_hook )
1124011249 return true;
1124111250
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 ;
1124711263
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 ();
1124911282 {
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 ();
1126311285 }
11286+ PG_END_TRY ();
1126411287
11265- return true ;
11288+ return result ;
1126611289}
1126711290
1126811291static bool
0 commit comments