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]

Reply via email to