NetBSD Problem Report #11545
Received: (qmail 27818 invoked from network); 22 Nov 2000 02:03:27 -0000
Message-Id: <200011132208.eADM84O21018@kaakeli.ssh.fi>
Date: Tue, 14 Nov 2000 00:08:04 +0200 (EET)
From: Tero Kivinen <kivinen@ssh.fi>
To: gnats-bugs@gnats.netbsd.org
Subject: gmtime does not work after 2038
X-Send-Pr-Version: 3.95
>Number: 11545
>Category: y2k
>Synopsis: gmtime returns year 1901 if trying to use time > 0x80000000
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: y2k-manager
>State: closed
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Nov 22 02:04:01 +0000 2000
>Closed-Date: Sun Oct 27 20:17:24 +0000 2002
>Last-Modified: Sun Oct 27 20:17:24 +0000 2002
>Originator: Tero Kivinen
>Release: NetBSD 1.5_ALPHA 2
>Organization:
SSH Communications Security
>Environment:
System: NetBSD kaakeli.ssh.fi 1.5_ALPHA2 NetBSD 1.5_ALPHA2 (KAAKELI) #39: Fri Oct 13 03:12:52 EEST 2000 kivinen@kaakeli.ssh.fi:/usr/src/sys/arch/i386/compile/KAAKELI i386
>Description:
If gmtime is given a time_t that is negative (i.e unix time
after 2038), then it returns year as 1901. This breaks for
example the perl HTTP::Cookie library, as for example the
www.google.com sets cookie like this:
Set-Cookie: PREF=ID=15d4258c1f04851e:TM=973465320:LM=973465320;
domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT
And when HTTP::Cookie tries to convert that 17-Jan-2038
19:14:07 to unix time it will fail and print out error
message.
Also most of the commercial y2k statements define programs to
be y2k safe only if they work up to year 2100. This means that
netbsd programs are NOT y2k safe in that sense, if they use
any gmtime etc functions.
>How-To-Repeat:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char **argv)
{
struct tm *t;
time_t c;
c = 0x80000000;
t = gmtime(&c);
printf("%d-%02d-%02d %02d:%02d:%02d\n",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
return 0;
}
>Fix:
Proper fix would be to define new time_t type (ltime_t?) that
would be 64-bits and start using that. Another easier fix
would be change the time_t to be unsigned instead of signed,
but this might break some programs. Easiest fix would be to
modify the lib/libc/time/localtime.c:timesub() so that it will
interpret the time_t as unsigned internally and return years
bigger than 2038 instead of years smaller than 1970 if
negative time_t values are used.
>Release-Note:
>Audit-Trail:
From: Robert Elz <kre@munnari.OZ.AU>
To: Tero Kivinen <kivinen@ssh.fi>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: y2k/11545: gmtime does not work after 2038
Date: Wed, 22 Nov 2000 15:39:16 +0700
Date: Tue, 14 Nov 2000 00:08:04 +0200 (EET)
From: Tero Kivinen <kivinen@ssh.fi>
Message-ID: <200011132208.eADM84O21018@kaakeli.ssh.fi>
| Proper fix would be to define new time_t type (ltime_t?) that
| would be 64-bits and start using that.
Yes, at some time that might be needed. It is a big change though,
and exactly what the format would be is not clear - certainly we don't
need a 64 bit offset of seconds from 1970 (not even 63 bit if it is
signed), the universe will have ended before then...
So, almost all suggestions for 64 bit time_t replacements also store
sub-seconds (perhaps down to pico-seconds). (ie: use scaled ints).
| Another easier fix
| would be change the time_t to be unsigned instead of signed,
I did that in 4.2BSD before it was released. The change didn't
last long - it broke so much, as to be unsupportable. The breakage
wasn't mostly in applications expecting signed time_t (there may have
been some of that, but it was minor) - the breakage was in ctime()
(localtime()) which couldn't cope with time_t t = 0; when that was
done (if you're in a timezone anywhere west of Greenwich - so it
had never bothered me....). That is, for time_t 0 people were used
to seeing some time in Dec 31, 1969, and were real upset when 2106
(or whatever it is) turned up instead.
That could be fixed in localtime() but at the time it seemed safer
to simply make time_t back to being signed.
And in any case (this was all pre POSIX of course, and ANSI C as well)
it was never clear that being able to represent times before 1970
shouldn't be possible ... ie: time_t t = - 100 * 86400 ought be 100
days before the start of 1970, perhaps. Or maybe not...
| but this might break some programs. Easiest fix would be to
| modify the lib/libc/time/localtime.c:timesub() so that it will
| interpret the time_t as unsigned internally and return years
| bigger than 2038 instead of years smaller than 1970 if
| negative time_t values are used.
A safer fix, that would probably bother less people, would be to
set the range of a time_t to be from (say) 1964 .. 2100, so there
are about 6 years of negative values, and 130 years of positive
values.
Most likely that would bother almost no-one. But it would be worth
asking about this on the tz list, where the people who really care
about time representations, and conversions, hang out. tz@elsie.nci.nih.gov
kre
From: Tero Kivinen <kivinen@ssh.fi>
To: Robert Elz <kre@munnari.OZ.AU>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: y2k/11545: gmtime does not work after 2038
Date: Wed, 22 Nov 2000 15:37:38 +0200 (EET)
Robert Elz writes:
> | Proper fix would be to define new time_t type (ltime_t?) that
> | would be 64-bits and start using that.
> Yes, at some time that might be needed. It is a big change though,
> and exactly what the format would be is not clear - certainly we don't
> need a 64 bit offset of seconds from 1970 (not even 63 bit if it is
> signed), the universe will have ended before then...
True.
> So, almost all suggestions for 64 bit time_t replacements also store
> sub-seconds (perhaps down to pico-seconds). (ie: use scaled ints).
Pico (1E-12) is too short... That would give us only 0.58 years... I
think nano (1E-9) is ok, it will give us 584 years. Of course it would
be better to define it starting from some other value than 1970 if we
are going to change the format anyways, i.e change the resolution to
micro (1E-6) and start it 2000 years before year 2000 (i.e year -1,
because somebody claims that year 0 does not exist :-) That would give
use time that is ok up to year 584942, i.e then we only need to take
care of the Y10K and Y100K problems, but not Y1M problem...
Microsecond resolution is propably going to be enough when we are
talking about the absolute real time, and timeval is already using
that resolution anyways.
Another possibility is to start using structure like timespec/timeval,
and make it to be signed 64-bit second counter from year 1970, and
32-bit nanosecond counter inside that second.
> A safer fix, that would probably bother less people, would be to
> set the range of a time_t to be from (say) 1964 .. 2100, so there
> are about 6 years of negative values, and 130 years of positive
> values.
I think that would be safest and best kludge to fix the problem now
before making the real fix (changing to use 64 bit time).
> Most likely that would bother almost no-one. But it would be worth
> asking about this on the tz list, where the people who really care
> about time representations, and conversions, hang out. tz@elsie.nci.nih.gov
Ok.
--
kivinen@ssh.fi Work : +358 303 9870
SSH Communications Security http://www.ssh.fi/
SSH IPSEC Toolkit http://www.ssh.fi/ipsec/
From: Robert Elz <kre@munnari.OZ.AU>
To: Tero Kivinen <kivinen@ssh.fi>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: y2k/11545: gmtime does not work after 2038
Date: Wed, 22 Nov 2000 22:02:15 +0700
Date: Wed, 22 Nov 2000 15:37:38 +0200 (EET)
From: Tero Kivinen <kivinen@ssh.fi>
Message-ID: <200011221337.PAA21749@torni.hel.fi.ssh.com>
| Pico (1E-12) is too short...
Hmm - yes, so it is...
| Microsecond resolution is propably going to be enough
Probably, though an issue that matters, is that to avoid growing
inodes, the entire time thing needs to fit in 64 bits, to be able
to record access/modify/change time on files. Microseconds are
already getting to be pretty long, in the forseeable future it
might actually be possible to make useful changes to files in less
than a microsecond, then that resolution wouldn't really be enough.
Maybe 1E-8 (though not a unit with a name) might be good - 5800
years should be plenty (+/- 2900 perhaps).
| Another possibility is to start using structure like timespec/timeval,
| and make it to be signed 64-bit second counter from year 1970, and
| 32-bit nanosecond counter inside that second.
Then it won't fit in the space available in inodes.
kre
From: Andrew Brown <atatat@atatdot.net>
To: Tero Kivinen <kivinen@ssh.fi>
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: y2k/11545: gmtime does not work after 2038
Date: Wed, 22 Nov 2000 12:06:49 -0500
> If gmtime is given a time_t that is negative (i.e unix time
> after 2038), then it returns year as 1901. This breaks for
> example the perl HTTP::Cookie library, as for example the
> www.google.com sets cookie like this:
that's because time is stored as a signed value, so once the high bit
goes on, it falls back to the beginning: Fri, 13-Dec-1901 20:45:52 GMT.
> Set-Cookie: PREF=ID=15d4258c1f04851e:TM=973465320:LM=973465320;
> domain=.google.com; path=/; expires=Sun, 17-Jan-2038 19:14:07 GMT
>
> And when HTTP::Cookie tries to convert that 17-Jan-2038
> 19:14:07 to unix time it will fail and print out error
> message.
then that module is in error.
% date -u -r 2147368447 +"%a, %d-%b-%Y %T %Z"
Sun, 17-Jan-2038 19:14:07 GMT
> Also most of the commercial y2k statements define programs to
> be y2k safe only if they work up to year 2100. This means that
> netbsd programs are NOT y2k safe in that sense, if they use
> any gmtime etc functions.
funny...and all this time i thought that y2k safe meant it would
survive the crossover into the year 2000.
--
|-----< "CODE WARRIOR" >-----|
codewarrior@daemon.org * "ah! i see you have the internet
twofsonet@graffiti.com (Andrew Brown) that goes *ping*!"
andrew@crossbar.com * "information is power -- share the wealth."
State-Changed-From-To: open->closed
State-Changed-By: chs
State-Changed-When: Sun Oct 27 12:12:34 PST 2002
State-Changed-Why:
since time_t has historically been signed, if one uses a negative value,
one should expect that to be before the epoch. I'll also note that
the time in the example is actually 0x7ffe3dff, which isn't even negative.
further, solaris, hpux and aix all return a date in 1901 for the given
test program, so we're conforming to industry practice. in short,
the existing code is fine.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.