From grant@osf.org Tue Oct 19 17:47:42 1993 Return-Path: <grant@osf.org> ... Message-Id: <9310192147.AA24813@postman.osf.org> To: ado@elsie.nci.nih.gov Cc: grant@osf.org Subject: problems with zoneinfo package passing VSX4 Date: Tue, 19 Oct 1993 21:47:37 +0000 From: Grant Sullivan <grant@osf.org> ...
I am a contract software engineer currently working for the Open Software Foundation, Cambridge, MA. I last sent mail to you in August of this year regarding my project to upgrade the next OSF/1 release to include the zoneinfo package.
I ended up using a sort of cut & paste approach to the project, using the BSD 4.4 version of ctime.c, based on your earlier work, as my code base for the libc changes, and "zic" additions. I compared those sources with your June '93 kit, and merged in what appeared to be fixes. I also included your entire June '93 zoneinfo source files. I had to make a few other changes here and there to integrate everything into OSF/1.
As a final functional check of libc, I was asked to run the VSX4 test suite, before I would be allowed to formally submit the entire package into the OSF/1 source pool.
The VSX4 test suite found some problems with ctime(), localtime(), mktime(), strftime() and tzset(). Most of these problems turned out to have a single cause. For example, correcting the failure in ctime() fixed the problems with localtime(), strftime(), tzset(), and some of the mktime() problems. I thought you might be interested in knowing what changes I had to make to pass VSX4. I am also stuck with one problem in mktime(), which you should be aware of, and for which I am having trouble developing a solution.
The VSX4 failure in ctime() involved a test case where TZ was set to TZ=(255 A's)0(255 B's) The number "255" corresponds to the POSIX.1 value for TZNAME_MAX. The VSX4 ANSI.os/time/ctime/T.ctime test Assertion 11 failed when the test checked the contents of tzname[] to see if it contained long A and B strings. ctime() failed because tzset() return an error when it found that the value of stdlen+1+dstlen+1 was greater than sizeof sp->chars. The sizeof sp->chars was TZ_MAX_CHARS, set to "50" in tzfile.h. I reset TZ_MAX_CHARS to 2*(TZNAME_MAX+1), in order to fix the VSX4 failure. Additionally in tzparse(), I changed the size checks for "stdlen" and "dstlen" to include upper limit checks against TZNAME_MAX, as follows: . . } else { name = getzname(name); stdlen = name - stdname; if ( stdlen < _POSIX_TZNAME_MAX || stdlen > TZNAME_MAX ) return -1; . . dstlen = name - dstname; /* length of DST zone name */ if ( dstlen < _POSIX_TZNAME_MAX_POSIX_TZNAME_MAX || dstlen > TZNAME_MAX ) return -1; . . I also replaced "3" with _POSIX_TZNAME_MAX aboce. The additional limit checks also make sure that the sum of the "std" and "dst" fields will not exceed 2*(TZNAME_MAX+1) even if TZ_MAX_CHARS should be set to something smaller.
The changes to tzfile.h and tzparse() resulted in eliminating the VSX4 failures of ctime(), localtime(), strftime(), tzset(), and some of the mktime() failures.
I have some temporary fixes for the mktime() failures, but I have not been able to successfully fix the VSX4 failure of ANSI.os/time/mktime/T.mktime assertion 10. Attempts I've made to fix it have tended to cause other mktime() assertions to fail, and vice versa. I suspect a flaw in the loop logic, or loop termination logic in time2(), but it could also be a flaw in time1() or in localsub().
The VSX4 test of mktime fails when: TZ=GMT0BST-2,J81,J300 and mktime() is called with the following tm structure: expected.tm_sec = 21; expected.tm_min = 0; expected.tm_hour = 2; expected.tm_mday = 27; expected.tm_mon = 9; expected.tm_year = 88; expected.tm_wday = -1; expected.tm_yday = -1; expected.tm_isdst = 1; VSX4 is expecting mktime() to return a value in the range 593913621 - 593913631 (allowing for the possibility that mktime() may include up to 10 additional leap seconds. mktime() returned -1, instead.
I believe the expected value is correct. VSX4 validates the mktime() returned value by calling localtime() with the expected number and comparing the expected and localtime()-generated tm structures.
I believe that VSX4 is expecting mktime() to behave in accordance to XPG4 with regards to how tm_isdst = 1 is handled on input to mktime(). XPG4, "System Interfaces and Headers", page 275, says: A positive or zero value for tm_isdst causes the mktime() function to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. ... mktime() seems to be having trouble when tm_isdst = 1, but the time/day the tm data specified is just past the end of the daylight savings time period. In the case above, the time is 21 seconds past the transition back to standard time.
I have tried things like resetting tm_isdst = 0 and recalculating, but that works for some cases exercised by VSX4, but not for this particular case.
Have you heard of this VSX4 case?
One area that is suspect is the extended loop in time2() which is based on the "bits" counter. The comments above the "normalize" function appear to pertain to this loop in time2():
/* ** Adapted from code provided by Robert Elz, who writes: ** The "best" way to do mktime I think is based on an idea of Bob ** Kridle's (so its said...) from a long time ago. (mtxinu!kridle now). ** It does a binary search of the time_t space. Since time_t's are ** just 32 bits, its a max of 32 iterations (even at 64 bits it ** would still be very reasonable). */
I've added debugging statements to time2() to better understand what the "bits" logic is about, and found that "bits" counter would often get down to as low as "5" before jumping down to the next "for" loop. For the case tested by VSX4, timecnt = 136, so if this were truly "a binary search of the time_t space", I would not expect "bits" to drop below 21. For the VXS4 test case, however, bits = 5 by the time the loop has found a value of "t" that is in range (t=593920800). The calculates to a linear search, rather than a binary search, since the matching t = (sp->ats[37] + tt_gmtoff), and (37/2) is approx. (88-70) is approx. (initial bits - final bits ) (31 - 5). I've tried setting the tm_year = 92, however, and found the loop went through the same number of cycles, so it I guess the search isn't really linear, but it seems to me it could be faster.
I also noticed that your June '93 kit's version of timesub() contains additional code vs. the BSD 4.4 version. I am wondering if this additional code is a bug fix?
Thanks for your assistance, Grant W. Sullivan, OSF/1 Commands & Libraries Group Open Software Foundation 11 Cambridge Center Cambridge, MA 02142 grant@osf.org 617) 621-7249