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

Commit23b8a0c

Browse files
committed
Repair array subscript overrun identified by Yichen Xie. Reduce the
value of MAX_TIME_PRECISION in floating-point-timestamp-storage casefrom 13 to 10, which is as much as time_out is actually willing to print.(The alternative of increasing the number of digits we are willing toprint looks risky; we might find ourselves printing roundoff garbage.)
1 parentb8add56 commit23b8a0c

File tree

4 files changed

+56
-74
lines changed

4 files changed

+56
-74
lines changed

‎doc/src/sgml/datatype.sgml

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.111 2003/01/15 18:01:04 momjian Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.112 2003/01/2901:08:42 tgl Exp $
33
-->
44

55
<chapter id="datatype">
@@ -1297,8 +1297,7 @@ SELECT b, char_length(b) FROM test2;
12971297
fractional digits retained in the seconds field. By default, there
12981298
is no explicit bound on precision. The allowed range of
12991299
<replaceable>p</replaceable> is from 0 to 6 for the
1300-
<type>timestamp</type> and <type>interval</type> types, 0 to 13
1301-
for the <type>time</type> types.
1300+
<type>timestamp</type> and <type>interval</type> types.
13021301
</para>
13031302

13041303
<note>
@@ -1314,6 +1313,12 @@ SELECT b, char_length(b) FROM test2;
13141313
</para>
13151314
</note>
13161315

1316+
<para>
1317+
For the <type>time</type> types, the allowed range of
1318+
<replaceable>p</replaceable> is from 0 to 6 when eight-byte integer
1319+
storage is used, or from 0 to 10 when floating-point storage is used.
1320+
</para>
1321+
13171322
<para>
13181323
Time zones, and time-zone conventions, are influenced by
13191324
political decisions, not just earth geometry. Time zones around the
@@ -1485,7 +1490,7 @@ SELECT b, char_length(b) FROM test2;
14851490
<para>
14861491
The <type>time</type> type can be specified as <type>time</type> or
14871492
as <type>time without time zone</type>. The optional precision
1488-
<replaceable>p</replaceable> should be between 0 and13, and
1493+
<replaceable>p</replaceable> should be between 0 and6, and
14891494
defaults to the precision of the input time literal.
14901495
</para>
14911496

‎src/backend/utils/adt/date.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.76 2003/01/22 20:44:20 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.77 2003/01/29 01:08:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -619,7 +619,7 @@ static void
619619
AdjustTimeForTypmod(TimeADT*time,int32typmod)
620620
{
621621
#ifdefHAVE_INT64_TIMESTAMP
622-
staticconstint64TimeScales[MAX_TIMESTAMP_PRECISION+1]= {
622+
staticconstint64TimeScales[MAX_TIME_PRECISION+1]= {
623623
INT64CONST(1000000),
624624
INT64CONST(100000),
625625
INT64CONST(10000),
@@ -629,7 +629,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
629629
INT64CONST(1)
630630
};
631631

632-
staticconstint64TimeOffsets[MAX_TIMESTAMP_PRECISION+1]= {
632+
staticconstint64TimeOffsets[MAX_TIME_PRECISION+1]= {
633633
INT64CONST(500000),
634634
INT64CONST(50000),
635635
INT64CONST(5000),
@@ -640,14 +640,19 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
640640
};
641641

642642
#else
643-
staticconstdoubleTimeScales[MAX_TIMESTAMP_PRECISION+1]= {
643+
/* note MAX_TIME_PRECISION differs in this case */
644+
staticconstdoubleTimeScales[MAX_TIME_PRECISION+1]= {
644645
1,
645646
10,
646647
100,
647648
1000,
648649
10000,
649650
100000,
650-
1000000
651+
1000000,
652+
10000000,
653+
100000000,
654+
1000000000,
655+
10000000000
651656
};
652657
#endif
653658

‎src/backend/utils/adt/datetime.c

Lines changed: 35 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.98 2003/01/16 00:26:45 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.99 2003/01/29 01:08:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -667,14 +667,13 @@ TrimTrailingZeros(char *str)
667667
}
668668
#endif
669669

670-
/* chop off trailing zeros... */
670+
/* chop off trailing zeros...but leave at least 2 fractional digits*/
671671
while ((*(str+len-1)=='0')
672672
&& (*(str+len-3)!='.'))
673673
{
674674
len--;
675675
*(str+len)='\0';
676676
}
677-
return;
678677
}
679678

680679

@@ -3145,45 +3144,30 @@ EncodeDateOnly(struct tm * tm, int style, char *str)
31453144
int
31463145
EncodeTimeOnly(structtm*tm,fsec_tfsec,int*tzp,intstyle,char*str)
31473146
{
3148-
#ifndefHAVE_INT64_TIMESTAMP
3149-
fsec_tsec;
3150-
#endif
3151-
31523147
if ((tm->tm_hour<0)|| (tm->tm_hour>24))
31533148
return-1;
31543149

3155-
#ifndefHAVE_INT64_TIMESTAMP
3156-
sec= (tm->tm_sec+fsec);
3157-
#endif
3158-
31593150
sprintf(str,"%02d:%02d",tm->tm_hour,tm->tm_min);
31603151

31613152
/*
3162-
* If we have fractional seconds, then include a decimal point We will
3163-
* do up to 6 fractional digits, and we have rounded any inputs to
3164-
* eliminate anything to the right of 6 digits anyway. If there are no
3165-
* fractional seconds, then do not bother printing a decimal point at
3166-
* all. - thomas 2001-09-29
3153+
* Print fractional seconds if any. The field widths here should be
3154+
* at least equal to the larger of MAX_TIME_PRECISION and
3155+
* MAX_TIMESTAMP_PRECISION.
31673156
*/
31683157
if (fsec!=0)
31693158
{
31703159
#ifdefHAVE_INT64_TIMESTAMP
3171-
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3172-
sprintf((str+strlen(str)),".%06d",fsec);
3160+
sprintf((str+strlen(str)),":%02d.%06d",tm->tm_sec,fsec);
31733161
#else
3174-
sprintf((str+strlen(str)),":%013.10f",sec);
3162+
sprintf((str+strlen(str)),":%013.10f",tm->tm_sec+fsec);
31753163
#endif
31763164
/* chop off trailing pairs of zeros... */
31773165
while ((strcmp((str+strlen(str)-2),"00")==0)
31783166
&& (*(str+strlen(str)-3)!='.'))
31793167
*(str+strlen(str)-2)='\0';
31803168
}
31813169
else
3182-
#ifdefHAVE_INT64_TIMESTAMP
31833170
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3184-
#else
3185-
sprintf((str+strlen(str)),":%02.0f",sec);
3186-
#endif
31873171

31883172
if (tzp!=NULL)
31893173
{
@@ -3217,20 +3201,12 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
32173201
hour,
32183202
min;
32193203

3220-
#ifndefHAVE_INT64_TIMESTAMP
3221-
fsec_tsec;
3222-
#endif
3223-
32243204
/*
32253205
* Why are we checking only the month field? Change this to an
32263206
* assert... if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) return -1;
32273207
*/
32283208
Assert((tm->tm_mon >=1)&& (tm->tm_mon <=12));
32293209

3230-
#ifndefHAVE_INT64_TIMESTAMP
3231-
sec= (tm->tm_sec+fsec);
3232-
#endif
3233-
32343210
switch (style)
32353211
{
32363212
caseUSE_ISO_DATES:
@@ -3241,21 +3217,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
32413217
tm->tm_mon,tm->tm_mday,tm->tm_hour,tm->tm_min);
32423218

32433219
/*
3244-
*If we havefractional seconds, then include a decimal point
3245-
*We will do up to6 fractional digits, and we have rounded
3246-
* any inputs to eliminate anything to the right of 6 digits
3247-
*anyway. If there are no fractional seconds, then do not
3248-
*bother printing a decimal point at all. - thomas 2001-09-29
3220+
*Printfractional seconds if any. The field widths here should
3221+
*be at least equal toMAX_TIMESTAMP_PRECISION.
3222+
*
3223+
*In float mode, don't print fractional seconds before 1 AD,
3224+
*since it's unlikely there's any precision left ...
32493225
*/
32503226
#ifdefHAVE_INT64_TIMESTAMP
32513227
if (fsec!=0)
32523228
{
3253-
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3254-
sprintf((str+strlen(str)),".%06d",fsec);
3229+
sprintf((str+strlen(str)),":%02d.%06d",tm->tm_sec,fsec);
32553230
#else
32563231
if ((fsec!=0)&& (tm->tm_year>0))
32573232
{
3258-
sprintf((str+strlen(str)),":%013.10f",sec);
3233+
sprintf((str+strlen(str)),":%09.6f",tm->tm_sec+fsec);
32593234
#endif
32603235
TrimTrailingZeros(str);
32613236
}
@@ -3292,21 +3267,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
32923267
tm->tm_hour,tm->tm_min);
32933268

32943269
/*
3295-
*If we havefractional seconds, then include a decimal point
3296-
*We will do up to6 fractional digits, and we have rounded
3297-
* any inputs to eliminate anything to the right of 6 digits
3298-
*anyway. If there are no fractional seconds, then do not
3299-
*bother printing a decimal point at all. - thomas 2001-09-29
3270+
*Printfractional seconds if any. The field widths here should
3271+
*be at least equal toMAX_TIMESTAMP_PRECISION.
3272+
*
3273+
*In float mode, don't print fractional seconds before 1 AD,
3274+
*since it's unlikely there's any precision left ...
33003275
*/
33013276
#ifdefHAVE_INT64_TIMESTAMP
33023277
if (fsec!=0)
33033278
{
3304-
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3305-
sprintf((str+strlen(str)),".%06d",fsec);
3279+
sprintf((str+strlen(str)),":%02d.%06d",tm->tm_sec,fsec);
33063280
#else
33073281
if ((fsec!=0)&& (tm->tm_year>0))
33083282
{
3309-
sprintf((str+strlen(str)),":%013.10f",sec);
3283+
sprintf((str+strlen(str)),":%09.6f",tm->tm_sec+fsec);
33103284
#endif
33113285
TrimTrailingZeros(str);
33123286
}
@@ -3339,21 +3313,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
33393313
tm->tm_hour,tm->tm_min);
33403314

33413315
/*
3342-
*If we havefractional seconds, then include a decimal point
3343-
*We will do up to6 fractional digits, and we have rounded
3344-
* any inputs to eliminate anything to the right of 6 digits
3345-
*anyway. If there are no fractional seconds, then do not
3346-
*bother printing a decimal point at all. - thomas 2001-09-29
3316+
*Printfractional seconds if any. The field widths here should
3317+
*be at least equal toMAX_TIMESTAMP_PRECISION.
3318+
*
3319+
*In float mode, don't print fractional seconds before 1 AD,
3320+
*since it's unlikely there's any precision left ...
33473321
*/
33483322
#ifdefHAVE_INT64_TIMESTAMP
33493323
if (fsec!=0)
33503324
{
3351-
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3352-
sprintf((str+strlen(str)),".%06d",fsec);
3325+
sprintf((str+strlen(str)),":%02d.%06d",tm->tm_sec,fsec);
33533326
#else
33543327
if ((fsec!=0)&& (tm->tm_year>0))
33553328
{
3356-
sprintf((str+strlen(str)),":%013.10f",sec);
3329+
sprintf((str+strlen(str)),":%09.6f",tm->tm_sec+fsec);
33573330
#endif
33583331
TrimTrailingZeros(str);
33593332
}
@@ -3394,21 +3367,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
33943367
sprintf((str+10)," %02d:%02d",tm->tm_hour,tm->tm_min);
33953368

33963369
/*
3397-
*If we havefractional seconds, then include a decimal point
3398-
*We will do up to6 fractional digits, and we have rounded
3399-
* any inputs to eliminate anything to the right of 6 digits
3400-
*anyway. If there are no fractional seconds, then do not
3401-
*bother printing a decimal point at all. - thomas 2001-09-29
3370+
*Printfractional seconds if any. The field widths here should
3371+
*be at least equal toMAX_TIMESTAMP_PRECISION.
3372+
*
3373+
*In float mode, don't print fractional seconds before 1 AD,
3374+
*since it's unlikely there's any precision left ...
34023375
*/
34033376
#ifdefHAVE_INT64_TIMESTAMP
34043377
if (fsec!=0)
34053378
{
3406-
sprintf((str+strlen(str)),":%02d",tm->tm_sec);
3407-
sprintf((str+strlen(str)),".%06d",fsec);
3379+
sprintf((str+strlen(str)),":%02d.%06d",tm->tm_sec,fsec);
34083380
#else
34093381
if ((fsec!=0)&& (tm->tm_year>0))
34103382
{
3411-
sprintf((str+strlen(str)),":%013.10f",sec);
3383+
sprintf((str+strlen(str)),":%09.6f",tm->tm_sec+fsec);
34123384
#endif
34133385
TrimTrailingZeros(str);
34143386
}

‎src/include/utils/date.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: date.h,v 1.21 2002/09/04 20:31:45 momjian Exp $
10+
* $Id: date.h,v 1.22 2003/01/29 01:08:42 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -41,7 +41,7 @@ typedef struct
4141
#ifdefHAVE_INT64_TIMESTAMP
4242
#defineMAX_TIME_PRECISION 6
4343
#else
44-
#defineMAX_TIME_PRECISION13
44+
#defineMAX_TIME_PRECISION10
4545
#endif
4646

4747
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp