Skip Menu |

This queue is for tickets about the Time-y2038 CPAN distribution.

Report information
The Basics
Id: 40764
Status: open
Priority: 0/
Queue: Time-y2038

People
Owner: Nobody in particular
Requestors: VOVKASM [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 20081106
Fixed in: (no value)



Subject: check_max infinity loop on freebsd
In function check_date_min for gmtime: when after some iteration gmtime called with time = -67768038400720896, it never returns to program. Tested on freebsd-6.2 (amd64) and freebsd-7.0 (amd64). Of cource, it's actually freebsd bug, but can we workaround this? Can be showed with attached program (it is check_max.c with debugging printf's ;-)
Subject: check_max_d.c
/* A little program to test the limits of your system's time functions */ #include <time.h> #include <stdio.h> #include <math.h> time_t Time_Zero = 0; /* Visual C++ 2008's difftime() can't do negative times */ double my_difftime(time_t left, time_t right) { double diff = (double)left - (double)right; return diff; } void check_date_max( struct tm * (*date_func)(const time_t *), char *func_name ) { struct tm *date; time_t time = 0; time_t last_time = 0; time_t time_change; int i; for (i = 0; i <= 63; i++) { date = (*date_func)(&time); /* date_func() broke or tm_year overflowed */ if(date == NULL || date->tm_year < 69) break; last_time = time; time += time + 1; /* time_t overflowed */ if( time < last_time ) break; } /* Binary search for the exact failure point */ time = last_time; time_change = last_time / 2; do { time += time_change; date = (*date_func)(&time); /* date_func() broke or tm_year overflowed or time_t overflowed */ if(date == NULL || date->tm_year < 69 || time < last_time) { time = last_time; time_change = time_change / 2; } else { last_time = time; } } while(time_change > 0); printf("%s_max %.0f\n", func_name, my_difftime(last_time, Time_Zero)); } void check_date_min( struct tm * (*date_func)(const time_t *), char *func_name ) { struct tm *date; time_t time = -1; time_t last_time = 0; time_t time_change; int i; for (i = 1; i <= 63; i++) { date = (*date_func)(&time); /* date_func() broke or tm_year underflowed */ if(date == NULL || date->tm_year > 70) { printf("%d) break;\n",i); break; } last_time = time; time += time; printf("%d) time: %ld\tlast: %ld\n",i,time,last_time); /* time_t underflowed */ if( time > last_time ) { printf("%d) time > last_time: %ld > %ld\n",i,time,last_time); break; } } /* Binary search for the exact failure point */ time = last_time; time_change = last_time / 2; printf("now time: %ld, time_change: %ld\n",time,time_change); do { time += time_change; printf("enter date_func(%ld)\n",time); date = (*date_func)(&time); /* gmtime() broke or tm_year overflowed or time_t overflowed */ if(date == NULL || date->tm_year > 70 || time > last_time) { time = last_time; time_change = time_change / 2; } else { last_time = time; } printf("time_change: %ld\n",time_change); } while(time_change < 0); printf("exit check_date_min\n"); printf("%s_min %.0f\n", func_name, my_difftime(last_time, Time_Zero)); } int main(void) { check_date_max(gmtime, "gmtime"); check_date_max(localtime, "localtime"); check_date_min(gmtime, "gmtime"); check_date_min(localtime, "localtime"); return 0; }
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Sat, 08 Nov 2008 15:46:23 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
Vladimir Timofeev via RT wrote: Show quoted text
> In function check_date_min for gmtime: > when after some iteration gmtime called with time = -67768038400720896, > it never returns to program. > Tested on freebsd-6.2 (amd64) and freebsd-7.0 (amd64). > Of cource, it's actually freebsd bug, but can we workaround this?
Congratulations! You've discovered a y2**31 bug! Sorry. More than likely tm.tm_year is still stored as a signed 32 bit integer. Why you'd do such a thing on a 64 bit platform I'm not sure. Yes, it's a FreeBSD bug and it sounds like they handle it badly. It should return NULL and set errno to EOVERFLOW. Could please inform them of the problem? I've rewritten check_max to limit the test based on the size of time_t and tm.tm_year. Could you try... http://y2038.googlecode.com/svn/trunk/bin/check_max.c -- 91. I am not authorized to initiate Jihad. -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army http://skippyslist.com/list/
Суб. Ноя. 08 18:47:19 2008, schwern@pobox.com писал: Show quoted text
> More than likely tm.tm_year is still stored as a signed 32 bit > integer. Why > you'd do such a thing on a 64 bit platform I'm not sure. Yes, it's a > FreeBSD > bug and it sounds like they handle it badly. It should return NULL > and set > errno to EOVERFLOW. Could please inform them of the problem?
Yes tm_year is 32bit, bug report to freebsd submitted... Show quoted text
> > I've rewritten check_max to limit the test based on the size of time_t > and > tm.tm_year. Could you try... > http://y2038.googlecode.com/svn/trunk/bin/check_max.c
Still loops infinity... Seems that gmtime "freezes" with -33884019326476801 and any lower values. But in check_date_min: time = -1, time_change = Time_Min (-67768038400720895) ... time += time_change (now -67768038400720896) then call gmtime and oops... I try set Time_Min to -33884019326476799, and take this iterations: time: -33884019326476800, last_time: 0 call gmtime date->tm_year: -1073741758 time: -67768038652953599, last_time: -33884019326476800 call gmtime date->tm_year: -2147483586 time: -101652057979430398, last_time: -67768038652953599 call gmtime date->tm_year: 1073741882 time: -84710048316191998, last_time: -67768038652953599 call gmtime date->tm_year: 1610612796 time: -76239043484572798, last_time: -67768038652953599 call gmtime date->tm_year: 1879048253 time: -72003541068763198, last_time: -67768038652953599 call gmtime date->tm_year: 2013265981 time: -69885789860858398, last_time: -67768038652953599 call gmtime date->tm_year: 2080374845 time: -68826914256905998, last_time: -67768038652953599 call gmtime date->tm_year: 2113929277 time: -68297476454929798, last_time: -67768038652953599 call gmtime date->tm_year: 2130706493 time: -68032757553941698, last_time: -67768038652953599 call gmtime date->tm_year: 2139095101 time: -67900398103447648, last_time: -67768038652953599 call gmtime date->tm_year: 2143289405 time: -67834218378200623, last_time: -67768038652953599 call gmtime date->tm_year: 2145386557 time: -67801128515577111, last_time: -67768038652953599 call gmtime forever :-/ PS. sorry for bad english...
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Sat, 08 Nov 2008 21:32:57 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
Vladimir Timofeev via RT wrote: Show quoted text
> Суб. Ноя. 08 18:47:19 2008, schwern@pobox.com писал:
>> More than likely tm.tm_year is still stored as a signed 32 bit >> integer. Why >> you'd do such a thing on a 64 bit platform I'm not sure. Yes, it's a >> FreeBSD >> bug and it sounds like they handle it badly. It should return NULL >> and set >> errno to EOVERFLOW. Could please inform them of the problem?
> Yes tm_year is 32bit, bug report to freebsd submitted...
Thanks. Show quoted text
>> I've rewritten check_max to limit the test based on the size of time_t >> and >> tm.tm_year. Could you try... >> http://y2038.googlecode.com/svn/trunk/bin/check_max.c
> Still loops infinity... > Seems that gmtime "freezes" with -33884019326476801 and any lower values.
I've changed check_max again so that it will not go past the max/min guessed at by using sizeof(). Please pull down a new copy and see if that clears things up. Show quoted text
> But in check_date_min: > time = -1, time_change = Time_Min (-67768038400720895) > ... > time += time_change (now -67768038400720896) > then call gmtime and oops... > I try set Time_Min to -33884019326476799, and take this iterations: > > time: -33884019326476800, last_time: 0 > call gmtime > date->tm_year: -1073741758 > time: -67768038652953599, last_time: -33884019326476800 > call gmtime > date->tm_year: -2147483586 > time: -101652057979430398, last_time: -67768038652953599 > call gmtime > date->tm_year: 1073741882 > time: -84710048316191998, last_time: -67768038652953599 > call gmtime > date->tm_year: 1610612796 > time: -76239043484572798, last_time: -67768038652953599 > call gmtime > date->tm_year: 1879048253 > time: -72003541068763198, last_time: -67768038652953599 > call gmtime > date->tm_year: 2013265981 > time: -69885789860858398, last_time: -67768038652953599 > call gmtime > date->tm_year: 2080374845 > time: -68826914256905998, last_time: -67768038652953599 > call gmtime > date->tm_year: 2113929277 > time: -68297476454929798, last_time: -67768038652953599 > call gmtime > date->tm_year: 2130706493 > time: -68032757553941698, last_time: -67768038652953599 > call gmtime > date->tm_year: 2139095101 > time: -67900398103447648, last_time: -67768038652953599 > call gmtime > date->tm_year: 2143289405 > time: -67834218378200623, last_time: -67768038652953599 > call gmtime > date->tm_year: 2145386557 > time: -67801128515577111, last_time: -67768038652953599 > call gmtime forever :-/
That's interesting that it only goes wild on times very close to -2**31 but if you go way further it's fine. -- 94. Crucifixes do not ward off officers, and I should not test that. -- The 213 Things Skippy Is No Longer Allowed To Do In The U.S. Army http://skippyslist.com/list/
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Sat, 08 Nov 2008 21:45:46 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
PS If you're willing to give me a login on your machine that would help. Then I can do my own debugging, I don't have any 64bit machines to test with.
Вск. Ноя. 09 00:34:09 2008, schwern@pobox.com писал: Show quoted text
> I've changed check_max again so that it will not go past the max/min > guessed > at by using sizeof(). Please pull down a new copy and see if that > clears > things up.
Yes, things up ;-) check_max returns: gmtime_max: 67768036175919296 gmtime_min: -67768036191676800 localtime_max: 67768036175919296 localtime_min: -67768036191676800 but tests fail with: t/everywhere....ok t/time..........ok t/timegm........3/? # Failed test 'timelocal(localtime(-4503599627370496))' # at t/timegm.t line 20. # got: -4503599627456896 # expected: -4503599627370496 # Looks like you failed 1 test of 17. t/timegm........ Dubious, test returned 1 (wstat 256, 0x100) Failed 1/17 subtests (less 4 skipped subtests: 12 okay)
Вск. Ноя. 09 00:47:14 2008, schwern@pobox.com писал: Show quoted text
> PS If you're willing to give me a login on your machine that would > help. > Then I can do my own debugging, I don't have any 64bit machines to > test with.
I'll try tomorrow (should consult with our company security team).
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Sun, 09 Nov 2008 20:51:01 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
Vladimir Timofeev via RT wrote: Show quoted text
>> I've changed check_max again so that it will not go past the max/min >> guessed >> at by using sizeof(). Please pull down a new copy and see if that >> clears >> things up.
> Yes, things up ;-) > check_max returns: > gmtime_max: 67768036175919296 > gmtime_min: -67768036191676800 > localtime_max: 67768036175919296 > localtime_min: -67768036191676800
Great! Show quoted text
> but tests fail with: > > t/everywhere....ok > t/time..........ok > t/timegm........3/? > # Failed test 'timelocal(localtime(-4503599627370496))' > # at t/timegm.t line 20. > # got: -4503599627456896 > # expected: -4503599627370496 > # Looks like you failed 1 test of 17. > t/timegm........ Dubious, test returned 1 (wstat 256, 0x100) > Failed 1/17 subtests > (less 4 skipped subtests: 12 okay)
This is probably due to that I don't check the range of mktime() (aka timelocal()) so I have to use the time zone / DST information from 1971-2037. Usually it's off by an hour but that looks off by a whole day. Can you try this C program? Also, what time zone are you in? #include <stdio.h> #include <time.h> #include <stdlib.h> int main(void) { time_t have = -123; time_t from_mktime; time_t Time_Zero = 0; struct tm *date; date = localtime(&have); from_mktime = mktime(date); printf("localtime said: %s", asctime(date)); printf("mktime said: %0.f, %s", difftime(from_mktime, Time_Zero), ctime(&from_mktime)); return 0; } -- I have a date with some giant cartoon robots and booze.
On Sun Nov 09 23:51:56 2008, schwern@pobox.com wrote: Show quoted text
> #include <stdio.h> > #include <time.h> > #include <stdlib.h> > > int main(void) { > time_t have = -123;
Sorry, that's... time_t have = -4503599627370496LL
Вск. Ноя. 09 23:51:56 2008, schwern@pobox.com писал: Show quoted text
> > but tests fail with: > > > > t/everywhere....ok > > t/time..........ok > > t/timegm........3/? > > # Failed test 'timelocal(localtime(-4503599627370496))' > > # at t/timegm.t line 20. > > # got: -4503599627456896 > > # expected: -4503599627370496 > > # Looks like you failed 1 test of 17. > > t/timegm........ Dubious, test returned 1 (wstat 256, 0x100) > > Failed 1/17 subtests > > (less 4 skipped subtests: 12 okay)
> > This is probably due to that I don't check the range of mktime() (aka > timelocal()) so I have to use the time zone / DST information from > 1971-2037. > Usually it's off by an hour but that looks off by a whole day. > > Can you try this C program? Also, what time zone are you in?
With have = -4503599627370496LL, this returns: localtime said: Mon Jan 24 22:41:44 -142711421 mktime said: -1, Thu Jan 1 02:59:59 1970 Timezone is MSK (Europe/Moscow, GMT+3) PS. Sorry, i can't make access to our freebsd servers... :-( But can install freebsd (amd64) at home, and make login to you (but it will take some time, because I need install system and setup dyndns - my isp use dynamic IPs). Needed?
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Tue, 11 Nov 2008 15:54:28 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
Vladimir Timofeev via RT wrote: Show quoted text
>>> t/everywhere....ok >>> t/time..........ok >>> t/timegm........3/? >>> # Failed test 'timelocal(localtime(-4503599627370496))' >>> # at t/timegm.t line 20. >>> # got: -4503599627456896 >>> # expected: -4503599627370496 >>> # Looks like you failed 1 test of 17. >>> t/timegm........ Dubious, test returned 1 (wstat 256, 0x100) >>> Failed 1/17 subtests >>> (less 4 skipped subtests: 12 okay)
>> This is probably due to that I don't check the range of mktime() (aka >> timelocal()) so I have to use the time zone / DST information from >> 1971-2037. >> Usually it's off by an hour but that looks off by a whole day. >> >> Can you try this C program? Also, what time zone are you in?
> With have = -4503599627370496LL, this returns: > localtime said: Mon Jan 24 22:41:44 -142711421 > mktime said: -1, Thu Jan 1 02:59:59 1970 > Timezone is MSK (Europe/Moscow, GMT+3)
Ouch, they both should have reported the same date and time. Your system's mktime() is not 64 bit clean. One more bug to report to the FreeBSD folks. But that test doesn't use mktime() that far back so something else is going on. It's very peculiar for it to be off by a whole day. I wonder if it's something historically odd about Russian leap years. Or maybe FreeBSD's localtime is just a little off. Show quoted text
> PS. Sorry, i can't make access to our freebsd servers... :-( > But can install freebsd (amd64) at home, and make login to you (but it > will take some time, because I need install system and setup dyndns - my > isp use dynamic IPs). Needed?
Yes, that would be very helpful. Thank you! -- Whip me, beat me, make my code compatible with VMS!
The test failure should be cleared up by the latest alphas. Time::y2038 now detects the limits of the system's mktime() so localtime/timelocal should round trip better. Please reopen if that's not the case.
From: vovkasm [...] gmail.com
Втр Фев 16 20:46:17 2010, MSCHWERN писал: Show quoted text
> The test failure should be cleared up by the latest alphas.
Time::y2038 Show quoted text
> now detects the limits of the system's mktime() so localtime/timelocal > should round trip better.
No, check_max.c still loops infinity. (freebsd-7.1 amd64) Show quoted text
> > Please reopen if that's not the case.
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Fri, 19 Feb 2010 12:46:55 +0300
To: bug-Time-y2038 [...] rt.cpan.org
From: Vladimir Timofeev <vovkasm [...] gmail.com>
On Fri, Feb 19, 2010 at 12:43, vovkasm@gmail.com via RT <bug-Time-y2038@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=40764 > > > Втр Фев 16 20:46:17 2010, MSCHWERN писал:
>> The test failure should be cleared up by the latest alphas.
> Time::y2038
>> now detects the limits of the system's mktime() so localtime/timelocal >> should round trip better.
> > No, check_max.c still loops infinity. (freebsd-7.1 amd64)
Tested with Time-y2038-20100218 Show quoted text
> >
>> >> Please reopen if that's not the case.
> > >
-- -- vovkasm
Subject: Re: [rt.cpan.org #40764] check_max infinity loop on freebsd
Date: Fri, 19 Feb 2010 04:18:32 -0800
To: bug-Time-y2038 [...] rt.cpan.org
From: Michael G Schwern <schwern [...] pobox.com>
vovkasm@gmail.com via RT wrote: Show quoted text
> Queue: Time-y2038 > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=40764 > > > On Fri, Feb 19, 2010 at 12:43, vovkasm@gmail.com via RT > <bug-Time-y2038@rt.cpan.org> wrote:
>> <URL: https://rt.cpan.org/Ticket/Display.html?id=40764 > >> >> Втр Фев 16 20:46:17 2010, MSCHWERN писал:
>>> The test failure should be cleared up by the latest alphas.
>> Time::y2038
>>> now detects the limits of the system's mktime() so localtime/timelocal >>> should round trip better.
>> No, check_max.c still loops infinity. (freebsd-7.1 amd64)
> > Tested with Time-y2038-20100218
Going to have to hard code it then. As I don't have access to a failing machine, you're going to have to do the leg work. You'll have to find the point where it goes bad and the necessary C defines to look for to identify the bad version. Then I can add them to check_max and prevent it from tickling the problem. Also, when you say "loops to infinity" do you mean its locking up inside gmtime() or inside check_max? -- "Clutter and overload are not an attribute of information, they are failures of design" -- Edward Tufte
From: vovkasm [...] gmail.com
Птн Фев 19 07:19:31 2010, schwern@pobox.com писал: Show quoted text
> vovkasm@gmail.com via RT wrote:
> > Queue: Time-y2038 > > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=40764 > > > > > On Fri, Feb 19, 2010 at 12:43, vovkasm@gmail.com via RT > > <bug-Time-y2038@rt.cpan.org> wrote:
> >> <URL: https://rt.cpan.org/Ticket/Display.html?id=40764 > > >> > >> Втр Фев 16 20:46:17 2010, MSCHWERN писал:
> >>> The test failure should be cleared up by the latest alphas.
> >> Time::y2038
> >>> now detects the limits of the system's mktime() so localtime/timelocal > >>> should round trip better.
> >> No, check_max.c still loops infinity. (freebsd-7.1 amd64)
> > > > Tested with Time-y2038-20100218
> > Going to have to hard code it then. As I don't have access to a failing > machine, you're going to have to do the leg work. You'll have to find the > point where it goes bad and the necessary C defines to look for to identify > the bad version. Then I can add them to check_max and prevent it from > tickling the problem.
Thanks, I'll try to look at it with gdb... Show quoted text
> > Also, when you say "loops to infinity" do you mean its locking up inside > gmtime() or inside check_max?
Inside gmtime() of course Show quoted text
> >
I assume I am also hitting this: Building a program to test the range of your system time functions... cc -Iy2038 -I/usr/local/lib/perl5/5.10.1/darwin-2level/CORE -c -fno-common -DPERL_DARWIN -no-cpp-precomp -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -I/opt/local/include -O3 -o check_max.o check_max.c cc -fstack-protector -L/usr/local/lib -L/opt/local/lib -o check_max check_max.o and running it... and then it never terminates. This is with v20100225. Let me know (via whatever channel) if there is something I can do to help. Darwin walrus.local 10.2.0 Darwin Kernel Version 10.2.0: Tue Nov 3 10:37:10 PST 2009; root:xnu-1486.2.11~1/RELEASE_I386 i386 -- rjbs
I got the OS X information about this from miyagawa. It seems timegm() is hanging around time_t -4136232677716. The general problem of time.h functions hanging is going to require a rewrite of check_max.c to mostly be in Perl so it can take advantage of alarm().
As a cheap hack, because reworking the whole limit check system is proving time consuming, I've wrapped the check in an alarm. It will use some very conservative defaults in that case.