提交 23b8a0ce 编写于 作者: T Tom Lane

Repair array subscript overrun identified by Yichen Xie. Reduce the

value of MAX_TIME_PRECISION in floating-point-timestamp-storage case
from 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 to
print looks risky; we might find ourselves printing roundoff garbage.)
上级 b8add56e
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.111 2003/01/15 18:01:04 momjian Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/datatype.sgml,v 1.112 2003/01/29 01:08:42 tgl Exp $
-->
<chapter id="datatype">
......@@ -1297,8 +1297,7 @@ SELECT b, char_length(b) FROM test2;
fractional digits retained in the seconds field. By default, there
is no explicit bound on precision. The allowed range of
<replaceable>p</replaceable> is from 0 to 6 for the
<type>timestamp</type> and <type>interval</type> types, 0 to 13
for the <type>time</type> types.
<type>timestamp</type> and <type>interval</type> types.
</para>
<note>
......@@ -1314,6 +1313,12 @@ SELECT b, char_length(b) FROM test2;
</para>
</note>
<para>
For the <type>time</type> types, the allowed range of
<replaceable>p</replaceable> is from 0 to 6 when eight-byte integer
storage is used, or from 0 to 10 when floating-point storage is used.
</para>
<para>
Time zones, and time-zone conventions, are influenced by
political decisions, not just earth geometry. Time zones around the
......@@ -1485,7 +1490,7 @@ SELECT b, char_length(b) FROM test2;
<para>
The <type>time</type> type can be specified as <type>time</type> or
as <type>time without time zone</type>. The optional precision
<replaceable>p</replaceable> should be between 0 and 13, and
<replaceable>p</replaceable> should be between 0 and 6, and
defaults to the precision of the input time literal.
</para>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.76 2003/01/22 20:44:20 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.77 2003/01/29 01:08:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -619,7 +619,7 @@ static void
AdjustTimeForTypmod(TimeADT *time, int32 typmod)
{
#ifdef HAVE_INT64_TIMESTAMP
static const int64 TimeScales[MAX_TIMESTAMP_PRECISION + 1] = {
static const int64 TimeScales[MAX_TIME_PRECISION + 1] = {
INT64CONST(1000000),
INT64CONST(100000),
INT64CONST(10000),
......@@ -629,7 +629,7 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
INT64CONST(1)
};
static const int64 TimeOffsets[MAX_TIMESTAMP_PRECISION + 1] = {
static const int64 TimeOffsets[MAX_TIME_PRECISION + 1] = {
INT64CONST(500000),
INT64CONST(50000),
INT64CONST(5000),
......@@ -640,14 +640,19 @@ AdjustTimeForTypmod(TimeADT *time, int32 typmod)
};
#else
static const double TimeScales[MAX_TIMESTAMP_PRECISION + 1] = {
/* note MAX_TIME_PRECISION differs in this case */
static const double TimeScales[MAX_TIME_PRECISION + 1] = {
1,
10,
100,
1000,
10000,
100000,
1000000
1000000,
10000000,
100000000,
1000000000,
10000000000
};
#endif
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.98 2003/01/16 00:26:45 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.99 2003/01/29 01:08:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -667,14 +667,13 @@ TrimTrailingZeros(char *str)
}
#endif
/* chop off trailing zeros... */
/* chop off trailing zeros... but leave at least 2 fractional digits */
while ((*(str + len - 1) == '0')
&& (*(str + len - 3) != '.'))
{
len--;
*(str + len) = '\0';
}
return;
}
......@@ -3145,33 +3144,22 @@ EncodeDateOnly(struct tm * tm, int style, char *str)
int
EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
{
#ifndef HAVE_INT64_TIMESTAMP
fsec_t sec;
#endif
if ((tm->tm_hour < 0) || (tm->tm_hour > 24))
return -1;
#ifndef HAVE_INT64_TIMESTAMP
sec = (tm->tm_sec + fsec);
#endif
sprintf(str, "%02d:%02d", tm->tm_hour, tm->tm_min);
/*
* If we have fractional seconds, then include a decimal point We will
* do up to 6 fractional digits, and we have rounded any inputs to
* eliminate anything to the right of 6 digits anyway. If there are no
* fractional seconds, then do not bother printing a decimal point at
* all. - thomas 2001-09-29
* Print fractional seconds if any. The field widths here should be
* at least equal to the larger of MAX_TIME_PRECISION and
* MAX_TIMESTAMP_PRECISION.
*/
if (fsec != 0)
{
#ifdef HAVE_INT64_TIMESTAMP
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
sprintf((str + strlen(str)), ".%06d", fsec);
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
#else
sprintf((str + strlen(str)), ":%013.10f", sec);
sprintf((str + strlen(str)), ":%013.10f", tm->tm_sec + fsec);
#endif
/* chop off trailing pairs of zeros... */
while ((strcmp((str + strlen(str) - 2), "00") == 0)
......@@ -3179,11 +3167,7 @@ EncodeTimeOnly(struct tm * tm, fsec_t fsec, int *tzp, int style, char *str)
*(str + strlen(str) - 2) = '\0';
}
else
#ifdef HAVE_INT64_TIMESTAMP
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
#else
sprintf((str + strlen(str)), ":%02.0f", sec);
#endif
if (tzp != NULL)
{
......@@ -3217,20 +3201,12 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
hour,
min;
#ifndef HAVE_INT64_TIMESTAMP
fsec_t sec;
#endif
/*
* Why are we checking only the month field? Change this to an
* assert... if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) return -1;
*/
Assert((tm->tm_mon >= 1) && (tm->tm_mon <= 12));
#ifndef HAVE_INT64_TIMESTAMP
sec = (tm->tm_sec + fsec);
#endif
switch (style)
{
case USE_ISO_DATES:
......@@ -3241,21 +3217,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
/*
* If we have fractional seconds, then include a decimal point
* We will do up to 6 fractional digits, and we have rounded
* any inputs to eliminate anything to the right of 6 digits
* anyway. If there are no fractional seconds, then do not
* bother printing a decimal point at all. - thomas 2001-09-29
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
*
* In float mode, don't print fractional seconds before 1 AD,
* since it's unlikely there's any precision left ...
*/
#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
sprintf((str + strlen(str)), ".%06d", fsec);
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
#else
if ((fsec != 0) && (tm->tm_year > 0))
{
sprintf((str + strlen(str)), ":%013.10f", sec);
sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
#endif
TrimTrailingZeros(str);
}
......@@ -3292,21 +3267,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
tm->tm_hour, tm->tm_min);
/*
* If we have fractional seconds, then include a decimal point
* We will do up to 6 fractional digits, and we have rounded
* any inputs to eliminate anything to the right of 6 digits
* anyway. If there are no fractional seconds, then do not
* bother printing a decimal point at all. - thomas 2001-09-29
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
*
* In float mode, don't print fractional seconds before 1 AD,
* since it's unlikely there's any precision left ...
*/
#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
sprintf((str + strlen(str)), ".%06d", fsec);
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
#else
if ((fsec != 0) && (tm->tm_year > 0))
{
sprintf((str + strlen(str)), ":%013.10f", sec);
sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
#endif
TrimTrailingZeros(str);
}
......@@ -3339,21 +3313,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
tm->tm_hour, tm->tm_min);
/*
* If we have fractional seconds, then include a decimal point
* We will do up to 6 fractional digits, and we have rounded
* any inputs to eliminate anything to the right of 6 digits
* anyway. If there are no fractional seconds, then do not
* bother printing a decimal point at all. - thomas 2001-09-29
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
*
* In float mode, don't print fractional seconds before 1 AD,
* since it's unlikely there's any precision left ...
*/
#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
sprintf((str + strlen(str)), ".%06d", fsec);
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
#else
if ((fsec != 0) && (tm->tm_year > 0))
{
sprintf((str + strlen(str)), ":%013.10f", sec);
sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
#endif
TrimTrailingZeros(str);
}
......@@ -3394,21 +3367,20 @@ EncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, cha
sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min);
/*
* If we have fractional seconds, then include a decimal point
* We will do up to 6 fractional digits, and we have rounded
* any inputs to eliminate anything to the right of 6 digits
* anyway. If there are no fractional seconds, then do not
* bother printing a decimal point at all. - thomas 2001-09-29
* Print fractional seconds if any. The field widths here should
* be at least equal to MAX_TIMESTAMP_PRECISION.
*
* In float mode, don't print fractional seconds before 1 AD,
* since it's unlikely there's any precision left ...
*/
#ifdef HAVE_INT64_TIMESTAMP
if (fsec != 0)
{
sprintf((str + strlen(str)), ":%02d", tm->tm_sec);
sprintf((str + strlen(str)), ".%06d", fsec);
sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);
#else
if ((fsec != 0) && (tm->tm_year > 0))
{
sprintf((str + strlen(str)), ":%013.10f", sec);
sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);
#endif
TrimTrailingZeros(str);
}
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: date.h,v 1.21 2002/09/04 20:31:45 momjian Exp $
* $Id: date.h,v 1.22 2003/01/29 01:08:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -41,7 +41,7 @@ typedef struct
#ifdef HAVE_INT64_TIMESTAMP
#define MAX_TIME_PRECISION 6
#else
#define MAX_TIME_PRECISION 13
#define MAX_TIME_PRECISION 10
#endif
/*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册