]> granicus.if.org Git - postgresql/commitdiff
Fix several places where fractional-second inputs were misprocessed
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Aug 2003 17:39:19 +0000 (17:39 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Aug 2003 17:39:19 +0000 (17:39 +0000)
in HAVE_INT64_TIMESTAMP cases, including two potential stack smashes
when more than six fractional digits were supplied.  Per bug report
from Philipp Reisner.

src/backend/utils/adt/datetime.c

index 8ae6d2f2ea9723f9f17ed933fe451feeeb6d7bd2..7baa751895cef43387b3b4c8a28362c975c421ff 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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')
                                                                        return -1;
 #ifdef HAVE_INT64_TIMESTAMP
-                                                               *fsec = frac * 1000000;
+                                                               *fsec = rint(frac * 1000000);
 #else
                                                                *fsec = frac;
 #endif
@@ -1177,9 +1177,11 @@ DecodeDateTime(char **field, int *ftype, int nf,
 
                                                                tmask |= DTK_TIME_M;
 #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
-                                                               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
                                                        }
                                                        break;
@@ -1882,9 +1884,16 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
                                                        tmask = DTK_M(SECOND);
                                                        if (*cp == '.')
                                                        {
-                                                               *fsec = strtod(cp, &cp);
+                                                               double          frac;
+
+                                                               frac = strtod(cp, &cp);
                                                                if (*cp != '\0')
                                                                        return -1;
+#ifdef HAVE_INT64_TIMESTAMP
+                                                               *fsec = rint(frac * 1000000);
+#else
+                                                               *fsec = frac;
+#endif
                                                        }
                                                        break;
 
@@ -1910,9 +1919,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
 
                                                                tmask |= DTK_TIME_M;
 #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
-                                                               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
                                                        }
                                                        break;
@@ -2336,24 +2347,17 @@ DecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec)
                        *fsec = 0;
                else if (*cp == '.')
                {
-#ifdef HAVE_INT64_TIMESTAMP
-                       char            fstr[MAXDATELEN + 1];
+                       double          frac;
 
-                       /*
-                        * 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;
-                       *fsec = strtod(str, &cp);
-#endif
+                       frac = strtod(str, &cp);
                        if (*cp != '\0')
                                return -1;
+#ifdef HAVE_INT64_TIMESTAMP
+                       *fsec = rint(frac * 1000000);
+#else
+                       *fsec = frac;
+#endif
                }
                else
                        return -1;
@@ -2396,6 +2400,8 @@ DecodeNumber(int flen, char *str, int fmask,
 
        if (*cp == '.')
        {
+               double  frac;
+
                /*
                 * More than two digits before decimal point? Then could be a date
                 * 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),
                                                                         tmask, tm, fsec, is2digits);
 
-               *fsec = strtod(cp, &cp);
+               frac = strtod(cp, &cp);
                if (*cp != '\0')
                        return -1;
+#ifdef HAVE_INT64_TIMESTAMP
+               *fsec = rint(frac * 1000000);
+#else
+               *fsec = frac;
+#endif
        }
        else if (*cp != '\0')
                return -1;
@@ -2514,19 +2525,13 @@ DecodeNumberField(int len, char *str, int fmask,
         */
        if ((cp = strchr(str, '.')) != NULL)
        {
-#ifdef HAVE_INT64_TIMESTAMP
-               char            fstr[MAXDATELEN + 1];
+               double          frac;
 
-               /*
-                * OK, we have at most six digits to care about. Let's construct a
-                * string and then do the conversion to an integer.
-                */
-               strcpy(fstr, (cp + 1));
-               strcpy((fstr + strlen(fstr)), "000000");
-               *(fstr + 6) = '\0';
-               *fsec = strtol(fstr, NULL, 10);
+               frac = strtod(cp, NULL);
+#ifdef HAVE_INT64_TIMESTAMP
+               *fsec = rint(frac * 1000000);
 #else
-               *fsec = strtod(cp, NULL);
+               *fsec = frac;
 #endif
                *cp = '\0';
                len = strlen(str);