Skip to content

Commit 9d41073

Browse files
committedAug 5, 2003
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

+38-33
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)