develooper Front page | perl.perl5.porters | Postings from January 2010

gmtime/localtime are busted around 2**48

Thread Next
From:
Michael G Schwern
Date:
January 30, 2010 01:45
Subject:
gmtime/localtime are busted around 2**48
Message ID:
4B63FFB3.4000607@pobox.com
--------------050906040205040606090909
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

I was working on y2038 today and noticed this.

$ perl5.11.4 -wle 'print scalar gmtime 2**48'
Tue Jun 23 10:44:16 -5877641

That ain't right (though it still leaves us in better shape than before).

The problem is this:

commit d95a2ea538e6c332f36c34ca45b78d6ad93c3a1f
Author: Craig A. Berry <craigberry@mac.com>
Date:   Sat Apr 25 17:51:38 2009 -0500

     Make time64 use NV for time_t, I32 for year, not Quad_t.

     This means it should run on anything that does not have a 64-bit
     integer type available but does have a double.  Presumably this
     includes platforms that define PERL_MICRO, so we now use the
     same extended time implementation for everything that runs Perl.

Something is overflowing.  It does so somewhere between 2**47 and 2**48.  I 
haven't investigated what.  I'm not so hot with the idea of storing time in an 
NV, though I understand why it was done and I realize storing it as a quad is 
already a lost cause because of the lack of a Quad SV.  But a year definitely 
cannot be stored in a 32 bit int, it will overflow around 2**56.

I'd recommend reversing that patch and also adding in the attached tests which 
do some basic sanity checks on distant dates to catch this sort of error.

Craig, want to give it another shot?


-- 
E: "Would you want to maintain a 5000 line Perl program?"
d: "Why would you write a 5000 line program?"


--------------050906040205040606090909
Content-Type: text/x-patch;
 name="0001-Add-sanity-checks-for-far-far-distant-dates.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename*0="0001-Add-sanity-checks-for-far-far-distant-dates.patch"

From ead93b9db0fcb1ce96c8a4f66c750ecde066bcbb Mon Sep 17 00:00:00 2001
From: Michael G. Schwern <schwern@pobox.com>
Date: Sat, 30 Jan 2010 01:41:59 -0800
Subject: [PATCH] Add sanity checks for far, far distant dates.

---
 t/op/time.t |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/t/op/time.t b/t/op/time.t
index 0f2dd66..8db6866 100644
--- a/t/op/time.t
+++ b/t/op/time.t
@@ -6,7 +6,7 @@ BEGIN {
     require './test.pl';
 }
 
-plan tests => 44;
+plan tests => 60;
 
 ($beguser,$begsys) = times;
 
@@ -145,3 +145,28 @@ ok(gmtime() =~ /^(Sun|Mon|Tue|Wed|Thu|Fri|Sat)[ ]
     };
     is($@, '', 'Ignore fractional time');
 }
+
+
+# Some sanity tests for the far, far future and far, far past
+{
+    my %time2year = (
+        -2**62  => -146138510344,
+        -2**52  => -142711421,
+        -2**48  => -8917617,
+        -2**46  => -2227927,
+         2**46  => 2231866,
+         2**48  => 8921556,
+         2**52  => 142715360,
+         2**62  => 146138514283
+    );
+
+    for my $time (sort keys %time2year) {
+        my $want = $time2year{$time};
+
+        my $have = (gmtime($time))[5] + 1900;
+        is $have, $want, "year check, gmtime($time)";
+
+        $have = (localtime($time))[5] + 1900;
+        is $have, $want, "year check, localtime($time)";
+    }
+}
-- 
1.6.6.1


--------------050906040205040606090909--

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About