mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-12 18:34:36 +08:00
Fix several places where fractional-second inputs were misprocessed
in HAVE_INT64_TIMESTAMP cases, including two potential stack smashes when more than six fractional digits were supplied. Per bug report from Philipp Reisner.
This commit is contained in:
parent
b6f31f08dd
commit
9d41073f04
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.110 2003/08/04 02:40:04 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.111 2003/08/05 17:39:19 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1147,7 +1147,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return -1;
|
return -1;
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
*fsec = frac * 1000000;
|
*fsec = rint(frac * 1000000);
|
||||||
#else
|
#else
|
||||||
*fsec = frac;
|
*fsec = frac;
|
||||||
#endif
|
#endif
|
||||||
@ -1177,9 +1177,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
|
|||||||
|
|
||||||
tmask |= DTK_TIME_M;
|
tmask |= DTK_TIME_M;
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
dt2time((time * 86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
dt2time((time * 86400000000),
|
||||||
|
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||||
#else
|
#else
|
||||||
dt2time((time * 86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
dt2time((time * 86400),
|
||||||
|
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1882,9 +1884,16 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||||||
tmask = DTK_M(SECOND);
|
tmask = DTK_M(SECOND);
|
||||||
if (*cp == '.')
|
if (*cp == '.')
|
||||||
{
|
{
|
||||||
*fsec = strtod(cp, &cp);
|
double frac;
|
||||||
|
|
||||||
|
frac = strtod(cp, &cp);
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
*fsec = rint(frac * 1000000);
|
||||||
|
#else
|
||||||
|
*fsec = frac;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1910,9 +1919,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
|
|||||||
|
|
||||||
tmask |= DTK_TIME_M;
|
tmask |= DTK_TIME_M;
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
dt2time((time * 86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
dt2time((time * 86400000000),
|
||||||
|
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||||
#else
|
#else
|
||||||
dt2time((time * 86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
dt2time((time * 86400),
|
||||||
|
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2336,24 +2347,17 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
|
|||||||
*fsec = 0;
|
*fsec = 0;
|
||||||
else if (*cp == '.')
|
else if (*cp == '.')
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
double frac;
|
||||||
char fstr[MAXDATELEN + 1];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OK, we have at most six digits to work with. Let's
|
|
||||||
* construct a string and then do the conversion to an
|
|
||||||
* integer.
|
|
||||||
*/
|
|
||||||
strncpy(fstr, (cp + 1), 7);
|
|
||||||
strcpy((fstr + strlen(fstr)), "000000");
|
|
||||||
*(fstr + 6) = '\0';
|
|
||||||
*fsec = strtol(fstr, &cp, 10);
|
|
||||||
#else
|
|
||||||
str = cp;
|
str = cp;
|
||||||
*fsec = strtod(str, &cp);
|
frac = strtod(str, &cp);
|
||||||
#endif
|
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
*fsec = rint(frac * 1000000);
|
||||||
|
#else
|
||||||
|
*fsec = frac;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
@ -2396,6 +2400,8 @@ DecodeNumber(int flen, char *str, int fmask,
|
|||||||
|
|
||||||
if (*cp == '.')
|
if (*cp == '.')
|
||||||
{
|
{
|
||||||
|
double frac;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* More than two digits before decimal point? Then could be a date
|
* More than two digits before decimal point? Then could be a date
|
||||||
* or a run-together time: 2001.360 20011225 040506.789
|
* or a run-together time: 2001.360 20011225 040506.789
|
||||||
@ -2404,9 +2410,14 @@ DecodeNumber(int flen, char *str, int fmask,
|
|||||||
return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
|
return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
|
||||||
tmask, tm, fsec, is2digits);
|
tmask, tm, fsec, is2digits);
|
||||||
|
|
||||||
*fsec = strtod(cp, &cp);
|
frac = strtod(cp, &cp);
|
||||||
if (*cp != '\0')
|
if (*cp != '\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
|
*fsec = rint(frac * 1000000);
|
||||||
|
#else
|
||||||
|
*fsec = frac;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (*cp != '\0')
|
else if (*cp != '\0')
|
||||||
return -1;
|
return -1;
|
||||||
@ -2514,19 +2525,13 @@ DecodeNumberField(int len, char *str, int fmask,
|
|||||||
*/
|
*/
|
||||||
if ((cp = strchr(str, '.')) != NULL)
|
if ((cp = strchr(str, '.')) != NULL)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_INT64_TIMESTAMP
|
double frac;
|
||||||
char fstr[MAXDATELEN + 1];
|
|
||||||
|
|
||||||
/*
|
frac = strtod(cp, NULL);
|
||||||
* OK, we have at most six digits to care about. Let's construct a
|
#ifdef HAVE_INT64_TIMESTAMP
|
||||||
* string and then do the conversion to an integer.
|
*fsec = rint(frac * 1000000);
|
||||||
*/
|
|
||||||
strcpy(fstr, (cp + 1));
|
|
||||||
strcpy((fstr + strlen(fstr)), "000000");
|
|
||||||
*(fstr + 6) = '\0';
|
|
||||||
*fsec = strtol(fstr, NULL, 10);
|
|
||||||
#else
|
#else
|
||||||
*fsec = strtod(cp, NULL);
|
*fsec = frac;
|
||||||
#endif
|
#endif
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
len = strlen(str);
|
len = strlen(str);
|
||||||
|
Loading…
Reference in New Issue
Block a user