Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit13671b4

Browse files
committed
Code review for GUC serialization/deserialization code.
The serialization code dumped core for a string-valued GUC whose valueis NULL, which is a legal state. The infrastructure isn't capable oftransmitting that state exactly, but fortunately, transmitting an emptystring instead should be close enough (compare, eg, commite45e990).The code potentially underestimated the space required to format areal-valued variable, both because it made an unwarranted assumption that%g output would never be longer than %e output, and because it didn't countright even for %e format. In practice this would pretty much always bemasked by overestimates for other variables, but it's still wrong.Also fix boundary-case error in read_gucstate, incorrect handling of thecase where guc_sourcefile is non-NULL but zero length (not clear that canhappen, but if it did, this code would get totally confused), andconfusingly useless check for a NULL result from read_gucstate.Andreas Seltenreich discovered the core dump; other issues noted whilereading nearby code. Back-patch to 9.5 where this code was introduced.Michael Paquier and Tom LaneDiscussion: <871sy78wno.fsf@credativ.de>
1 parent67dc4cc commit13671b4

File tree

1 file changed

+31
-21
lines changed
  • src/backend/utils/misc

1 file changed

+31
-21
lines changed

‎src/backend/utils/misc/guc.c

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8903,7 +8903,9 @@ can_skip_gucvar(struct config_generic * gconf)
89038903

89048904
/*
89058905
* estimate_variable_size:
8906-
* Estimate max size for dumping the given GUC variable.
8906+
*Compute space needed for dumping the given GUC variable.
8907+
*
8908+
* It's OK to overestimate, but not to underestimate.
89078909
*/
89088910
staticSize
89098911
estimate_variable_size(structconfig_generic*gconf)
@@ -8914,9 +8916,8 @@ estimate_variable_size(struct config_generic * gconf)
89148916
if (can_skip_gucvar(gconf))
89158917
return0;
89168918

8917-
size=0;
8918-
8919-
size=add_size(size,strlen(gconf->name)+1);
8919+
/* Name, plus trailing zero byte. */
8920+
size=strlen(gconf->name)+1;
89208921

89218922
/* Get the maximum display length of the GUC value. */
89228923
switch (gconf->vartype)
@@ -8937,7 +8938,7 @@ estimate_variable_size(struct config_generic * gconf)
89378938
* small values. Maximum value is 2147483647, i.e. 10 chars.
89388939
* Include one byte for sign.
89398940
*/
8940-
if (abs(*conf->variable)<1000)
8941+
if (Abs(*conf->variable)<1000)
89418942
valsize=3+1;
89428943
else
89438944
valsize=10+1;
@@ -8947,19 +8948,28 @@ estimate_variable_size(struct config_generic * gconf)
89478948
casePGC_REAL:
89488949
{
89498950
/*
8950-
* We are going to print it with %.17g. Account for sign,
8951-
* decimal point, and e+nnn notation. E.g.
8952-
* -3.9932904234000002e+110
8951+
* We are going to print it with %e with REALTYPE_PRECISION
8952+
* fractional digits. Account for sign, leading digit,
8953+
* decimal point, and exponent with up to 3 digits. E.g.
8954+
* -3.99329042340000021e+110
89538955
*/
8954-
valsize=REALTYPE_PRECISION+1+1+5;
8956+
valsize=1+1+1+REALTYPE_PRECISION+5;
89558957
}
89568958
break;
89578959

89588960
casePGC_STRING:
89598961
{
89608962
structconfig_string*conf= (structconfig_string*)gconf;
89618963

8962-
valsize=strlen(*conf->variable);
8964+
/*
8965+
* If the value is NULL, we transmit it as an empty string.
8966+
* Although this is not physically the same value, GUC
8967+
* generally treats a NULL the same as empty string.
8968+
*/
8969+
if (*conf->variable)
8970+
valsize=strlen(*conf->variable);
8971+
else
8972+
valsize=0;
89638973
}
89648974
break;
89658975

@@ -8972,17 +8982,17 @@ estimate_variable_size(struct config_generic * gconf)
89728982
break;
89738983
}
89748984

8975-
/* Allow space for terminating zero-byte */
8985+
/* Allow space for terminating zero-bytefor value*/
89768986
size=add_size(size,valsize+1);
89778987

89788988
if (gconf->sourcefile)
89798989
size=add_size(size,strlen(gconf->sourcefile));
89808990

8981-
/* Allow space for terminating zero-byte */
8991+
/* Allow space for terminating zero-bytefor sourcefile*/
89828992
size=add_size(size,1);
89838993

8984-
/* Include line wheneverwe include file. */
8985-
if (gconf->sourcefile)
8994+
/* Include line wheneverfile is nonempty. */
8995+
if (gconf->sourcefile&&gconf->sourcefile[0])
89868996
size=add_size(size,sizeof(gconf->sourceline));
89878997

89888998
size=add_size(size,sizeof(gconf->source));
@@ -9100,7 +9110,7 @@ serialize_variable(char **destptr, Size *maxbytes,
91009110
{
91019111
structconfig_real*conf= (structconfig_real*)gconf;
91029112

9103-
do_serialize(destptr,maxbytes,"%.*g",
9113+
do_serialize(destptr,maxbytes,"%.*e",
91049114
REALTYPE_PRECISION,*conf->variable);
91059115
}
91069116
break;
@@ -9109,7 +9119,9 @@ serialize_variable(char **destptr, Size *maxbytes,
91099119
{
91109120
structconfig_string*conf= (structconfig_string*)gconf;
91119121

9112-
do_serialize(destptr,maxbytes,"%s",*conf->variable);
9122+
/* NULL becomes empty string, see estimate_variable_size() */
9123+
do_serialize(destptr,maxbytes,"%s",
9124+
*conf->variable ?*conf->variable :"");
91139125
}
91149126
break;
91159127

@@ -9126,7 +9138,7 @@ serialize_variable(char **destptr, Size *maxbytes,
91269138
do_serialize(destptr,maxbytes,"%s",
91279139
(gconf->sourcefile ?gconf->sourcefile :""));
91289140

9129-
if (gconf->sourcefile)
9141+
if (gconf->sourcefile&&gconf->sourcefile[0])
91309142
do_serialize_binary(destptr,maxbytes,&gconf->sourceline,
91319143
sizeof(gconf->sourceline));
91329144

@@ -9193,7 +9205,7 @@ read_gucstate(char **srcptr, char *srcend)
91939205
for (ptr=*srcptr;ptr<srcend&&*ptr!='\0';ptr++)
91949206
;
91959207

9196-
if (ptr>srcend)
9208+
if (ptr >=srcend)
91979209
elog(ERROR,"could not find null terminator in GUC state");
91989210

91999211
/* Set the new position to the byte following the terminating NUL */
@@ -9247,9 +9259,7 @@ RestoreGUCState(void *gucstate)
92479259
{
92489260
intresult;
92499261

9250-
if ((varname=read_gucstate(&srcptr,srcend))==NULL)
9251-
break;
9252-
9262+
varname=read_gucstate(&srcptr,srcend);
92539263
varvalue=read_gucstate(&srcptr,srcend);
92549264
varsourcefile=read_gucstate(&srcptr,srcend);
92559265
if (varsourcefile[0])

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp