Re: Postgresql 7.3.3 crashing on query

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: Postgresql 7.3.3 crashing on query
Дата
Msg-id 9846.1060105308@sss.pgh.pa.us
обсуждение исходный текст
Ответ на Re: Postgresql 7.3.3 crashing on query  (Philipp Reisner <philipp.reisner@linbit.com>)
Список pgsql-bugs
Philipp Reisner <philipp.reisner@linbit.com> writes:
>                         strncpy(fstr, (cp + 1), 7);
> +                       fstr[7]=0;
>                         strcpy((fstr + strlen(fstr)), "000000");

After some looking around, it turns out there was another similar error,
plus several related places where the code was not quite right.
Attached is the full patch I applied against 7.3.4.  Many thanks for
pointing out this mistake!

            regards, tom lane

Index: datetime.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/adt/datetime.c,v
retrieving revision 1.96.2.5
diff -c -r1.96.2.5 datetime.c
*** datetime.c    4 May 2003 04:30:35 -0000    1.96.2.5
--- datetime.c    5 Aug 2003 17:34:48 -0000
***************
*** 1128,1134 ****
                                  if (*cp != '\0')
                                      return -1;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 *fsec = frac * 1000000;
  #else
                                  *fsec = frac;
  #endif
--- 1128,1134 ----
                                  if (*cp != '\0')
                                      return -1;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 *fsec = rint(frac * 1000000);
  #else
                                  *fsec = frac;
  #endif
***************
*** 1158,1166 ****

                                  tmask |= DTK_TIME_M;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 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);
  #endif
                              }
                              break;
--- 1158,1168 ----

                                  tmask |= DTK_TIME_M;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 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);
  #endif
                              }
                              break;
***************
*** 1835,1843 ****
                              tmask = DTK_M(SECOND);
                              if (*cp == '.')
                              {
!                                 *fsec = strtod(cp, &cp);
                                  if (*cp != '\0')
                                      return -1;
                              }
                              break;

--- 1837,1852 ----
                              tmask = DTK_M(SECOND);
                              if (*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;

***************
*** 1863,1871 ****

                                  tmask |= DTK_TIME_M;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 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);
  #endif
                              }
                              break;
--- 1872,1882 ----

                                  tmask |= DTK_TIME_M;
  #ifdef HAVE_INT64_TIMESTAMP
!                                 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);
  #endif
                              }
                              break;
***************
*** 2268,2291 ****
              *fsec = 0;
          else if (*cp == '.')
          {
! #ifdef HAVE_INT64_TIMESTAMP
!             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;
!             *fsec = strtod(str, &cp);
! #endif
              if (*cp != '\0')
                  return -1;
          }
          else
              return -1;
--- 2279,2295 ----
              *fsec = 0;
          else if (*cp == '.')
          {
!             double        frac;

              str = cp;
!             frac = strtod(str, &cp);
              if (*cp != '\0')
                  return -1;
+ #ifdef HAVE_INT64_TIMESTAMP
+             *fsec = rint(frac * 1000000);
+ #else
+             *fsec = frac;
+ #endif
          }
          else
              return -1;
***************
*** 2328,2333 ****
--- 2332,2339 ----

      if (*cp == '.')
      {
+         double    frac;
+
          /*
           * More than two digits? Then could be a date or a run-together
           * time: 2001.360 20011225 040506.789
***************
*** 2336,2344 ****
              return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
                                       tmask, tm, fsec, is2digits);

!         *fsec = strtod(cp, &cp);
          if (*cp != '\0')
              return -1;
      }
      else if (*cp != '\0')
          return -1;
--- 2342,2355 ----
              return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
                                       tmask, tm, fsec, is2digits);

!         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;
***************
*** 2441,2459 ****
       */
      if ((cp = strchr(str, '.')) != NULL)
      {
! #ifdef HAVE_INT64_TIMESTAMP
!         char        fstr[MAXDATELEN + 1];

!         /*
!          * 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);
  #else
!         *fsec = strtod(cp, NULL);
  #endif
          *cp = '\0';
          len = strlen(str);
--- 2452,2464 ----
       */
      if ((cp = strchr(str, '.')) != NULL)
      {
!         double        frac;

!         frac = strtod(cp, NULL);
! #ifdef HAVE_INT64_TIMESTAMP
!         *fsec = rint(frac * 1000000);
  #else
!         *fsec = frac;
  #endif
          *cp = '\0';
          len = strlen(str);

В списке pgsql-bugs по дате отправления:

Предыдущее
От: Tom Lane
Дата:
Сообщение: Re: Postgresql 7.3.3 crashing on query
Следующее
От: Joseph Shraibman
Дата:
Сообщение: pg 7.4beta1 doc bug: vacuum not updated