problem with tzcode96l

Hi, we're trying to get OpenBSD to pass the NIST POSIX test suite and it tries to do a mktime() with TZ=dst0std,J057,J059 with a time of Tue Feb 26 01:59:59 1991 (which should return 667533600). mktime() from tzcode96l (and earlier versions) returns -1 with that TZ setting. There seems to be a problem with the end of daylight savings time specification. If you comment out the getrule() on line 751 it at least keeps mktime from returning -1 :-) I really don't understand the code in question. Any clues would be greatly appreciated. thanks, todd --- Todd C. Miller Sysadmin--University of Colorado Todd.Miller@cs.colorado.edu

Date: Tue, 29 Oct 1996 11:35:14 -0700 From: "Todd C. Miller" <Todd.Miller@cs.colorado.edu> we're trying to get OpenBSD to pass the NIST POSIX test suite and it tries to do a mktime() with TZ=dst0std,J057,J059 with a time of Tue Feb 26 01:59:59 1991 (which should return 667533600). This makes it sound like the NIST Posix test suite is incorrect. With those arguments, mktime should return 667533599 if tm_isdst is negative or 0, and an implementation-defined value (typically either 667533599 or 667529999) if tm_isdst is positive. mktime() from tzcode96l (and earlier versions) returns -1 with that TZ setting. If mktime returns -1 then that is a bug, but I can't reproduce the bug when building tzcode96l on Solaris 2.5.1. I used make cc=gcc CFLAGS='-DHAVE_GETTEXT=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_SETTIMEOFDAY=3 -DHAVE_STRERROR=1 -DHAVE_UTMPX_H=1' to build tzcode96l. mktime had the behavior described above (it returned 667529999 for the positive tm_isdst case).

In message <199610291921.LAA16622@shade.twinsun.com> so spake Paul Eggert (eggert):
If mktime returns -1 then that is a bug, but I can't reproduce the bug when building tzcode96l on Solaris 2.5.1. I used
make cc=gcc CFLAGS='-DHAVE_GETTEXT=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_SETTIM EOFDAY=3 -DHAVE_STRERROR=1 -DHAVE_UTMPX_H=1'
to build tzcode96l. mktime had the behavior described above (it returned 667529999 for the positive tm_isdst case).
Hmm, that is interesting. The problem may lie elsewhere then. I'll let you know what I find out. - todd

In message <199610291921.LAA16622@shade.twinsun.com> so spake Paul Eggert (eggert):
If mktime returns -1 then that is a bug, but I can't reproduce the bug when building tzcode96l on Solaris 2.5.1. I used
make cc=gcc CFLAGS='-DHAVE_GETTEXT=1 -DHAVE_LONG_DOUBLE=1 -DHAVE_SETTIM EOFDAY=3 -DHAVE_STRERROR=1 -DHAVE_UTMPX_H=1'
to build tzcode96l. mktime had the behavior described above (it returned 667529999 for the positive tm_isdst case).
Hmm, under hpux 10.10 with : make cc=gcc CFLAGS='-DHAVE_LONG_DOUBLE=1 -DHAVE_SETTIMEOFDAY=3 -DHAVE_UTMPX_H=1 -DHAVE_STRERROR=1 and TZ=dst0std,J057,J059 I also get a return value of -1. Under solaris 2.5 with the exact parameters you have above I also get a return value of -1 with TZ=dst0std,J057,J059. I'm using the following simple test linked with $(LIBOBJS) (localtime.o asctime.o difftime.o). - todd #include <stdio.h> #include <stdlib.h> #include <time.h> main() { struct tm tm; time_t t; (void) memset(&tm, 0, sizeof(tm)); tm.tm_hour = 2; tm.tm_mday = 26; tm.tm_mon = 1; tm.tm_year = 91; tm.tm_wday = 2; (void) putenv("TZ=dst0std,J057,J059"); t = mktime(&tm); printf("Time is %ld\n", t); exit(0); }

Here is the exact test the POSIX test suite is using that fails. int main() { struct tm tm; time_t t; tm.tm_isdst = -1; tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 2; tm.tm_mday = 26; tm.tm_mon = 1; tm.tm_year = 91; tm.tm_wday = 2; tm.tm_yday = -1; putenv("TZ=dst0std,J057,J059"); tzset(); t = mktime(&tm); printf("Expected: 667530000\n"); printf("or: 667533600\n"); printf("Actual: %ld\n", (long)t); return 0; }

Date: Tue, 29 Oct 1996 14:36:25 -0700 From: "Todd C. Miller" <Todd.Miller@cs.colorado.edu> Here is the exact test the POSIX test suite is using that fails. int main() { struct tm tm; time_t t; tm.tm_isdst = -1; tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 2; tm.tm_mday = 26; tm.tm_mon = 1; tm.tm_year = 91; tm.tm_wday = 2; tm.tm_yday = -1; putenv("TZ=dst0std,J057,J059"); tzset(); t = mktime(&tm); printf("Expected: 667530000\n"); printf("or: 667533600\n"); printf("Actual: %ld\n", (long)t); return 0; } That test (which appears to be taken from NIST-PCTS/STD/LS/src/mktime/8.1.58_09.c) is attempting to apply `mktime' to 1991-02-26 02:00:00 with isdst set to -1. When TZ='dst0std,J057,J059', the requested local time never exists (the clock jumps from 01:59:59 to 03:00:00), so the C Standard allows mktime to return -1 in this case. The POSIX test suite is therefore erroneous here. I'll CC: this message to 151-2@sst.ncsl.nist.gov, as I understand it's the right address to report bugs in the POSIX test suite. (If tzcode were modified to work around the bug in the Posix test suite, it'd still conform to Posix; this might take less time than fixing the bug in the test suite. This would be reminiscent of the optional PCTS-bug workaround that's already in tzcode.) I asked the C Standard committee about a very similar test case a while ago, and they gave an official response that a -1 return is OK. The rest of this message contains a copy of the request and response, taken from the official record of C Standard interpretations at <URL:ftp://ftp.dmk.com/DMK/sc22wg14/rr/defec130.txt.gz>. Posix just copies the C Standard in this area, so a -1 return conforms to Posix too. ------- Defect Report #136 *Submission Date*: 31 Mar 94 *Submittor*: Project Editor (P.J. Plauger) *Source*: Paul Eggert Question Suppose I run the following program in a US environment, where the clocks will jump forward from 01:59:59 to 03:00:00 on April 3, 1994. This program attempts to invoke `mktime' on a `struct tm' that represents 02:30:00 on that date. Does the C Standard let `mktime' return -1 in this case? #include <stdio.h> #include <time.h> int main() { struct tm t; time_t r; /* 1994-04-03 02:30:00 */ t.tm_year = 1994 - 1900; t.tm_mon = 3; t.tm_mday = 3; t.tm_hour = 2; t.tm_min = 30; t.tm_sec = 0; t.tm_isdst = -1; /* i.e. unknown */ r = mktime(&t); if (r == -1) printf("mktime failed\n"); else printf("%s", ctime(&r)); return 0; } The ANSI C Rationale (corresponding to subclause 7.12.2.3) clearly lets `mktime' yield -1 in the ``fall-backward fold'' that will occur when the clock is turned back from 01:59:59 to 01:00:00 on October 30, 1994. The question is whether `mktime' is also allowed to yield -1 in the ``spring-forward gap'' when the clock is advanced from 01:59:59 to 03:00:00. This question arose when Arthur David Olson's popular ``tz'' time zone software was tested using NIST-PCTS:151-2, Version 1.4, (1993-12-03) a test suite put out by the National Institute of Standards and Technology that attempts to test C and Posix conformance. The PCTS package insists that in the above case, `mktime' must yield a `time_t' corresponding to either 01:30:00 or 03:30:00; i.e. PCTS rejects Olson's `mktime', which yields -1. This test case differs in an important way from the common practical use of `mktime' to ``add 1'' to the output of `localtime' or `gmtime', since those functions normally set `tm_isdst' to a nonnegative value, whereas `tm_isdst' is -1 in the case under question. I suggest that the Committee issue a clarification which makes it clear that `mktime' can yield -1 in the spring-forward gap when `tm_isdst' is -1. *Response* The Standard does not specify the behavior precisely enough to preclude `mktime' from returning a value of `(time_t)-1' and leaving the `tm_isdst' member set to -1 in such situations.

Aha, thanks for looking into this. We've run afoul of bugs in the PCTS before... - todd

The following patch fixes things for PCTS, courtesy of Thorsten Lockert <tholo@sigmasoft.com>. - todd Index: localtime.c =================================================================== RCS file: /cvs/src/lib/libc/time/localtime.c,v retrieving revision 1.6 diff -u -r1.6 localtime.c --- localtime.c 1996/09/05 12:28:23 1.6 +++ localtime.c 1996/10/30 00:14:32 @@ -1366,7 +1366,14 @@ dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (bits-- < 0) +#ifdef PCTS + { + t += 2; + break; + } +#else return WRONG; +#endif if (bits < 0) --t; /* may be needed if new t is minimal */ else if (dir > 0)
participants (2)
-
Paul Eggert
-
Todd C. Miller