Skip to content

Commit 9d41073

Browse files
committed
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.
1 parent b6f31f0 commit 9d41073

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

src/backend/utils/adt/datetime.c

Lines changed: 38 additions & 33 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.110 2003/08/04 02:40:04 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.111 2003/08/05 17:39:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1147,7 +1147,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
11471147
if (*cp != '\0')
11481148
return -1;
11491149
#ifdef HAVE_INT64_TIMESTAMP
1150-
*fsec = frac * 1000000;
1150+
*fsec = rint(frac * 1000000);
11511151
#else
11521152
*fsec = frac;
11531153
#endif
@@ -1177,9 +1177,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
11771177

11781178
tmask |= DTK_TIME_M;
11791179
#ifdef HAVE_INT64_TIMESTAMP
1180-
dt2time((time * 86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1180+
dt2time((time * 86400000000),
1181+
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
11811182
#else
1182-
dt2time((time * 86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1183+
dt2time((time * 86400),
1184+
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
11831185
#endif
11841186
}
11851187
break;
@@ -1882,9 +1884,16 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
18821884
tmask = DTK_M(SECOND);
18831885
if (*cp == '.')
18841886
{
1885-
*fsec = strtod(cp, &cp);
1887+
double frac;
1888+
1889+
frac = strtod(cp, &cp);
18861890
if (*cp != '\0')
18871891
return -1;
1892+
#ifdef HAVE_INT64_TIMESTAMP
1893+
*fsec = rint(frac * 1000000);
1894+
#else
1895+
*fsec = frac;
1896+
#endif
18881897
}
18891898
break;
18901899

@@ -1910,9 +1919,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
19101919

19111920
tmask |= DTK_TIME_M;
19121921
#ifdef HAVE_INT64_TIMESTAMP
1913-
dt2time((time * 86400000000), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1922+
dt2time((time * 86400000000),
1923+
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
19141924
#else
1915-
dt2time((time * 86400), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
1925+
dt2time((time * 86400),
1926+
&tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
19161927
#endif
19171928
}
19181929
break;
@@ -2336,24 +2347,17 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
23362347
*fsec = 0;
23372348
else if (*cp == '.')
23382349
{
2339-
#ifdef HAVE_INT64_TIMESTAMP
2340-
char fstr[MAXDATELEN + 1];
2350+
double frac;
23412351

2342-
/*
2343-
* OK, we have at most six digits to work with. Let's
2344-
* construct a string and then do the conversion to an
2345-
* integer.
2346-
*/
2347-
strncpy(fstr, (cp + 1), 7);
2348-
strcpy((fstr + strlen(fstr)), "000000");
2349-
*(fstr + 6) = '\0';
2350-
*fsec = strtol(fstr, &cp, 10);
2351-
#else
23522352
str = cp;
2353-
*fsec = strtod(str, &cp);
2354-
#endif
2353+
frac = strtod(str, &cp);
23552354
if (*cp != '\0')
23562355
return -1;
2356+
#ifdef HAVE_INT64_TIMESTAMP
2357+
*fsec = rint(frac * 1000000);
2358+
#else
2359+
*fsec = frac;
2360+
#endif
23572361
}
23582362
else
23592363
return -1;
@@ -2396,6 +2400,8 @@ DecodeNumber(int flen, char *str, int fmask,
23962400

23972401
if (*cp == '.')
23982402
{
2403+
double frac;
2404+
23992405
/*
24002406
* More than two digits before decimal point? Then could be a date
24012407
* or a run-together time: 2001.360 20011225 040506.789
@@ -2404,9 +2410,14 @@ DecodeNumber(int flen, char *str, int fmask,
24042410
return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
24052411
tmask, tm, fsec, is2digits);
24062412

2407-
*fsec = strtod(cp, &cp);
2413+
frac = strtod(cp, &cp);
24082414
if (*cp != '\0')
24092415
return -1;
2416+
#ifdef HAVE_INT64_TIMESTAMP
2417+
*fsec = rint(frac * 1000000);
2418+
#else
2419+
*fsec = frac;
2420+
#endif
24102421
}
24112422
else if (*cp != '\0')
24122423
return -1;
@@ -2514,19 +2525,13 @@ DecodeNumberField(int len, char *str, int fmask,
25142525
*/
25152526
if ((cp = strchr(str, '.')) != NULL)
25162527
{
2517-
#ifdef HAVE_INT64_TIMESTAMP
2518-
char fstr[MAXDATELEN + 1];
2528+
double frac;
25192529

2520-
/*
2521-
* OK, we have at most six digits to care about. Let's construct a
2522-
* string and then do the conversion to an integer.
2523-
*/
2524-
strcpy(fstr, (cp + 1));
2525-
strcpy((fstr + strlen(fstr)), "000000");
2526-
*(fstr + 6) = '\0';
2527-
*fsec = strtol(fstr, NULL, 10);
2530+
frac = strtod(cp, NULL);
2531+
#ifdef HAVE_INT64_TIMESTAMP
2532+
*fsec = rint(frac * 1000000);
25282533
#else
2529-
*fsec = strtod(cp, NULL);
2534+
*fsec = frac;
25302535
#endif
25312536
*cp = '\0';
25322537
len = strlen(str);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy