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

Commitaa55d05

Browse files
committed
Provide a HINT listing the allowed unit names when a GUC variable seems to
contain a wrong unit specification, per discussion.In passing, fix the code to avoid unnecessary integer overflows whenconverting units, and to detect overflows when they do occur.
1 parent9f6aacd commitaa55d05

File tree

1 file changed

+194
-98
lines changed
  • src/backend/utils/misc

1 file changed

+194
-98
lines changed

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

Lines changed: 194 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* Written by Peter Eisentraut <peter_e@gmx.net>.
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.400 2007/06/20 18:31:39 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.401 2007/06/21 18:14:21 tgl Exp $
1414
*
1515
*--------------------------------------------------------------------
1616
*/
@@ -94,8 +94,13 @@
9494
#defineKB_PER_GB (1024*1024)
9595

9696
#defineMS_PER_S 1000
97+
#defineS_PER_MIN 60
9798
#defineMS_PER_MIN (1000 * 60)
99+
#defineMIN_PER_H 60
100+
#defineS_PER_H (60 * 60)
98101
#defineMS_PER_H (1000 * 60 * 60)
102+
#defineMIN_PER_D (60 * 24)
103+
#defineS_PER_D (60 * 60 * 24)
99104
#defineMS_PER_D (1000 * 60 * 60 * 24)
100105

101106
/* XXX these should appear in other modules' header files */
@@ -3783,124 +3788,209 @@ parse_bool(const char *value, bool *result)
37833788

37843789
/*
37853790
* Try to parse value as an integer. The accepted formats are the
3786-
* usual decimal, octal, or hexadecimal formats. If the string parses
3787-
* okay, return true, else false. If result is not NULL, return the
3788-
* value there.
3791+
* usual decimal, octal, or hexadecimal formats, optionally followed by
3792+
* a unit name if "flags" indicates a unit is allowed.
3793+
*
3794+
* If the string parses okay, return true, else false.
3795+
* If okay and result is not NULL, return the value in *result.
3796+
* If not okay and hintmsg is not NULL, *hintmsg is set to a suitable
3797+
*HINT message, or NULL if no hint provided.
37893798
*/
37903799
staticbool
3791-
parse_int(constchar*value,int*result,intflags)
3800+
parse_int(constchar*value,int*result,intflags,constchar**hintmsg)
37923801
{
3793-
longval;
3802+
int64val;
37943803
char*endptr;
37953804

3805+
/* To suppress compiler warnings, always set output params */
3806+
if (result)
3807+
*result=0;
3808+
if (hintmsg)
3809+
*hintmsg=NULL;
3810+
3811+
/* We assume here that int64 is at least as wide as long */
37963812
errno=0;
37973813
val=strtol(value,&endptr,0);
37983814

3799-
if ((flags&GUC_UNIT_MEMORY)&&endptr!=value)
3815+
if (endptr==value)
3816+
return false;/* no HINT for integer syntax error */
3817+
3818+
if (errno==ERANGE||val!= (int64) ((int32)val))
38003819
{
3801-
boolused= false;
3820+
if (hintmsg)
3821+
*hintmsg=gettext_noop("Value exceeds integer range.");
3822+
return false;
3823+
}
38023824

3803-
while (*endptr==' ')
3804-
endptr++;
3825+
/* allow whitespace between integer and unit */
3826+
while (isspace((unsignedchar)*endptr))
3827+
endptr++;
38053828

3806-
if (strcmp(endptr,"kB")==0)
3807-
{
3808-
used= true;
3809-
endptr+=2;
3810-
}
3811-
elseif (strcmp(endptr,"MB")==0)
3812-
{
3813-
val *=KB_PER_MB;
3814-
used= true;
3815-
endptr+=2;
3816-
}
3817-
elseif (strcmp(endptr,"GB")==0)
3829+
/* Handle possible unit */
3830+
if (*endptr!='\0')
3831+
{
3832+
/*
3833+
* Note: the multiple-switch coding technique here is a bit tedious,
3834+
* but seems necessary to avoid intermediate-value overflows.
3835+
*
3836+
* If INT64_IS_BUSTED (ie, it's really int32) we will fail to detect
3837+
* overflow due to units conversion, but there are few enough such
3838+
* machines that it does not seem worth trying to be smarter.
3839+
*/
3840+
if (flags&GUC_UNIT_MEMORY)
38183841
{
3819-
val *=KB_PER_GB;
3820-
used= true;
3821-
endptr+=2;
3822-
}
3842+
/* Set hint for use if no match or trailing garbage */
3843+
if (hintmsg)
3844+
*hintmsg=gettext_noop("Valid units for this parameter are \"kB\", \"MB\", and \"GB\".");
38233845

3824-
#ifBLCKSZ<1024
3825-
#error BLCKSZ must be >= 1024
3846+
#ifBLCKSZ<1024||BLCKSZ> (1024*1024)
3847+
#error BLCKSZ must be between 1KB and 1MB
3848+
#endif
3849+
#ifXLOG_BLCKSZ<1024||XLOG_BLCKSZ> (1024*1024)
3850+
#error XLOG_BLCKSZ must be between 1KB and 1MB
38263851
#endif
38273852

3828-
if (used)
3829-
{
3830-
switch (flags&GUC_UNIT_MEMORY)
3853+
if (strncmp(endptr,"kB",2)==0)
38313854
{
3832-
caseGUC_UNIT_BLOCKS:
3833-
val /= (BLCKSZ /1024);
3834-
break;
3835-
caseGUC_UNIT_XBLOCKS:
3836-
val /= (XLOG_BLCKSZ /1024);
3837-
break;
3855+
endptr+=2;
3856+
switch (flags&GUC_UNIT_MEMORY)
3857+
{
3858+
caseGUC_UNIT_BLOCKS:
3859+
val /= (BLCKSZ /1024);
3860+
break;
3861+
caseGUC_UNIT_XBLOCKS:
3862+
val /= (XLOG_BLCKSZ /1024);
3863+
break;
3864+
}
3865+
}
3866+
elseif (strncmp(endptr,"MB",2)==0)
3867+
{
3868+
endptr+=2;
3869+
switch (flags&GUC_UNIT_MEMORY)
3870+
{
3871+
caseGUC_UNIT_KB:
3872+
val *=KB_PER_MB;
3873+
break;
3874+
caseGUC_UNIT_BLOCKS:
3875+
val *=KB_PER_MB / (BLCKSZ /1024);
3876+
break;
3877+
caseGUC_UNIT_XBLOCKS:
3878+
val *=KB_PER_MB / (XLOG_BLCKSZ /1024);
3879+
break;
3880+
}
3881+
}
3882+
elseif (strncmp(endptr,"GB",2)==0)
3883+
{
3884+
endptr+=2;
3885+
switch (flags&GUC_UNIT_MEMORY)
3886+
{
3887+
caseGUC_UNIT_KB:
3888+
val *=KB_PER_GB;
3889+
break;
3890+
caseGUC_UNIT_BLOCKS:
3891+
val *=KB_PER_GB / (BLCKSZ /1024);
3892+
break;
3893+
caseGUC_UNIT_XBLOCKS:
3894+
val *=KB_PER_GB / (XLOG_BLCKSZ /1024);
3895+
break;
3896+
}
38383897
}
38393898
}
3840-
}
3899+
elseif (flags&GUC_UNIT_TIME)
3900+
{
3901+
/* Set hint for use if no match or trailing garbage */
3902+
if (hintmsg)
3903+
*hintmsg=gettext_noop("Valid units for this parameter are \"ms\", \"s\", \"min\", \"h\", and \"d\".");
38413904

3842-
if ((flags&GUC_UNIT_TIME)&&endptr!=value)
3843-
{
3844-
boolused= false;
3905+
if (strncmp(endptr,"ms",2)==0)
3906+
{
3907+
endptr+=2;
3908+
switch (flags&GUC_UNIT_TIME)
3909+
{
3910+
caseGUC_UNIT_S:
3911+
val /=MS_PER_S;
3912+
break;
3913+
caseGUC_UNIT_MIN:
3914+
val /=MS_PER_MIN;
3915+
break;
3916+
}
3917+
}
3918+
elseif (strncmp(endptr,"s",1)==0)
3919+
{
3920+
endptr+=1;
3921+
switch (flags&GUC_UNIT_TIME)
3922+
{
3923+
caseGUC_UNIT_MS:
3924+
val *=MS_PER_S;
3925+
break;
3926+
caseGUC_UNIT_MIN:
3927+
val /=S_PER_MIN;
3928+
break;
3929+
}
3930+
}
3931+
elseif (strncmp(endptr,"min",3)==0)
3932+
{
3933+
endptr+=3;
3934+
switch (flags&GUC_UNIT_TIME)
3935+
{
3936+
caseGUC_UNIT_MS:
3937+
val *=MS_PER_MIN;
3938+
break;
3939+
caseGUC_UNIT_S:
3940+
val *=S_PER_MIN;
3941+
break;
3942+
}
3943+
}
3944+
elseif (strncmp(endptr,"h",1)==0)
3945+
{
3946+
endptr+=1;
3947+
switch (flags&GUC_UNIT_TIME)
3948+
{
3949+
caseGUC_UNIT_MS:
3950+
val *=MS_PER_H;
3951+
break;
3952+
caseGUC_UNIT_S:
3953+
val *=S_PER_H;
3954+
break;
3955+
caseGUC_UNIT_MIN:
3956+
val *=MIN_PER_H;
3957+
break;
3958+
}
3959+
}
3960+
elseif (strncmp(endptr,"d",1)==0)
3961+
{
3962+
endptr+=1;
3963+
switch (flags&GUC_UNIT_TIME)
3964+
{
3965+
caseGUC_UNIT_MS:
3966+
val *=MS_PER_D;
3967+
break;
3968+
caseGUC_UNIT_S:
3969+
val *=S_PER_D;
3970+
break;
3971+
caseGUC_UNIT_MIN:
3972+
val *=MIN_PER_D;
3973+
break;
3974+
}
3975+
}
3976+
}
38453977

3846-
while (*endptr==' ')
3978+
/* allow whitespace after unit */
3979+
while (isspace((unsignedchar)*endptr))
38473980
endptr++;
38483981

3849-
if (strcmp(endptr,"ms")==0)
3850-
{
3851-
used= true;
3852-
endptr+=2;
3853-
}
3854-
elseif (strcmp(endptr,"s")==0)
3855-
{
3856-
val *=MS_PER_S;
3857-
used= true;
3858-
endptr+=1;
3859-
}
3860-
elseif (strcmp(endptr,"min")==0)
3861-
{
3862-
val *=MS_PER_MIN;
3863-
used= true;
3864-
endptr+=3;
3865-
}
3866-
elseif (strcmp(endptr,"h")==0)
3867-
{
3868-
val *=MS_PER_H;
3869-
used= true;
3870-
endptr+=1;
3871-
}
3872-
elseif (strcmp(endptr,"d")==0)
3873-
{
3874-
val *=MS_PER_D;
3875-
used= true;
3876-
endptr+=1;
3877-
}
3982+
if (*endptr!='\0')
3983+
return false;/* appropriate hint, if any, already set */
38783984

3879-
if (used)
3985+
/* Check for overflow due to units conversion */
3986+
if (val!= (int64) ((int32)val))
38803987
{
3881-
switch (flags&GUC_UNIT_TIME)
3882-
{
3883-
caseGUC_UNIT_S:
3884-
val /=MS_PER_S;
3885-
break;
3886-
caseGUC_UNIT_MIN:
3887-
val /=MS_PER_MIN;
3888-
break;
3889-
}
3988+
if (hintmsg)
3989+
*hintmsg=gettext_noop("Value exceeds integer range.");
3990+
return false;
38903991
}
38913992
}
38923993

3893-
if (endptr==value||*endptr!='\0'||errno==ERANGE
3894-
#ifdefHAVE_LONG_INT_64
3895-
/* if long > 32 bits, check for overflow of int4 */
3896-
||val!= (long) ((int32)val)
3897-
#endif
3898-
)
3899-
{
3900-
if (result)
3901-
*result=0;/* suppress compiler warning */
3902-
return false;
3903-
}
39043994
if (result)
39053995
*result= (int)val;
39063996
return true;
@@ -4243,12 +4333,15 @@ set_config_option(const char *name, const char *value,
42434333

42444334
if (value)
42454335
{
4246-
if (!parse_int(value,&newval,conf->gen.flags))
4336+
constchar*hintmsg;
4337+
4338+
if (!parse_int(value,&newval,conf->gen.flags,&hintmsg))
42474339
{
42484340
ereport(elevel,
42494341
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4250-
errmsg("parameter \"%s\" requires an integer value",
4251-
name)));
4342+
errmsg("invalid value for parameter \"%s\": \"%s\"",
4343+
name,value),
4344+
hintmsg ?errhint(hintmsg) :0));
42524345
return false;
42534346
}
42544347
if (newval<conf->min||newval>conf->max)
@@ -5674,21 +5767,24 @@ is_newvalue_equal(struct config_generic * record, const char *newvalue)
56745767
structconfig_bool*conf= (structconfig_bool*)record;
56755768
boolnewval;
56765769

5677-
returnparse_bool(newvalue,&newval)&&*conf->variable==newval;
5770+
returnparse_bool(newvalue,&newval)
5771+
&&*conf->variable==newval;
56785772
}
56795773
casePGC_INT:
56805774
{
56815775
structconfig_int*conf= (structconfig_int*)record;
56825776
intnewval;
56835777

5684-
returnparse_int(newvalue,&newval,record->flags)&&*conf->variable==newval;
5778+
returnparse_int(newvalue,&newval,record->flags,NULL)
5779+
&&*conf->variable==newval;
56855780
}
56865781
casePGC_REAL:
56875782
{
56885783
structconfig_real*conf= (structconfig_real*)record;
56895784
doublenewval;
56905785

5691-
returnparse_real(newvalue,&newval)&&*conf->variable==newval;
5786+
returnparse_real(newvalue,&newval)
5787+
&&*conf->variable==newval;
56925788
}
56935789
casePGC_STRING:
56945790
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp