Re: Postgresql 7.3.3 crashing on query

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Philipp Reisner <philipp(dot)reisner(at)linbit(dot)com>
Cc: pgsql-bugs(at)postgresql(dot)org
Subject: Re: Postgresql 7.3.3 crashing on query
Date: 2003-08-05 17:41:48
Message-ID: 9846.1060105308@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Philipp Reisner <philipp(dot)reisner(at)linbit(dot)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);

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Joseph Shraibman 2003-08-06 00:51:05 pg 7.4beta1 doc bug: vacuum not updated
Previous Message Tom Lane 2003-08-05 16:35:53 Re: Postgresql 7.3.3 crashing on query