Hey Steve, Adam, (This is in reference to bug 257255: sqsh crashes after trying to deal with date fields in a result set.)
This isn't an sqsh bug, it's a couple of freetds ones (libct3 in particular). First off, a couple of functions in src/tds/convert.c have a hardcoded maximum date string size of 30, which is fine for the LANG=C locale, but not for anywhere mildly more interesting (such as en_US.UTF-8). That's expanded out to 64 from 30, which is more than enough to include the extra timezone name. Second thing, the TDS layer seems to keep dates in its own format, and convert out of it at the last minute (no prob with that, given struct tm doesn't include timezone or millisecond information). However, the conversion isn't quite right. In particular, they don't handle Daylight Savings Time and their count of days since January 1 is off by one. For whatever godawful reason, glibc's entirely too fragile strftime() seems to care about those being right. mktime() handles cleaning up struct tm, so slap a call in there to adjust the trickier fields, and then correct the tm_hour field as it may have been moved by the mktime() call. After fixing those two things, `sqsh -C "select getdate()"` is no longer segfaulting on en_US.UTF-8. I'm guessing it's the same problem for any other interesting timezone, so this will probably close this bug report. Regardless, please apply. (Oh, and while I have your attention, thanks for doing the work you do for Debian. It makes my life a lot easier.) Ray diff -pruX /usr/src/dontdiff freetds-0.63/src/tds/convert.c freetds-0.63-fixed/src/tds/convert.c --- freetds-0.63/src/tds/convert.c 2005-11-11 13:42:19 -0800 +++ freetds-0.63-fixed/src/tds/convert.c 2005-11-15 00:24:16 -0800 @@ -1268,7 +1268,7 @@ tds_convert_datetime(TDSCONTEXT * tds_ct unsigned int dt_days, dt_time; - char whole_date_string[30]; + char whole_date_string[64]; TDSDATEREC when; switch (desttype) { @@ -1342,7 +1342,7 @@ tds_convert_datetime4(TDSCONTEXT * tds_c TDS_USMALLINT dt_days, dt_mins; - char whole_date_string[30]; + char whole_date_string[64]; TDSDATEREC when; switch (desttype) { @@ -2759,7 +2759,7 @@ tds_strftime(char *buf, size_t maxsize, tm.tm_sec = dr->second; tm.tm_min = dr->minute; - tm.tm_hour = dr->hour; + tm.tm_hour = 12; tm.tm_mday = dr->day; tm.tm_mon = dr->month; tm.tm_year = dr->year - 1900; @@ -2767,6 +2767,11 @@ tds_strftime(char *buf, size_t maxsize, tm.tm_yday = dr->dayofyear; tm.tm_isdst = 0; + /* correct the final three fields, which as a side effect could change tm_hour */ + mktime(&tm); + + tm.tm_hour = dr->hour; + /* NOTE 2 in intentional. one more character is required because we replace %z with 3 digits */ our_format = (char *) malloc(strlen(format) + 2); if (!our_format) -- Ray Lee <[EMAIL PROTECTED]> http://madrabbit.org/ -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]