t/op/tiearray.t See if tie for arrays works
t/op/tiehandle.t See if tie for handles works
t/op/tie.t See if tie/untie functions work
+t/op/time_loop.t Test that very large values don't hang gmtime and localtime.
t/op/time.t See if time functions work
t/op/tr.t See if tr works
t/op/undef.t See if undef works
my(@times, @methods);
BEGIN {
- @times = (-2**62, -2**50, -2**33, -2**31-1, -1, 0, 1, 2**31-1, 2**33, 2**50, 2**62, time);
+ @times = (-2**55, -2**50, -2**33, -2**31-1, -1, 0, 1, 2**31-1, 2**33, 2**50, 2**55, time);
@methods = qw(sec min hour mday mon year wday yday isdst);
- plan tests => (@times * @methods) + 1;
+ plan tests => (@times * (@methods + 1)) + 1;
use_ok Time::gmtime;
}
my $gmtime = gmtime $time; # This is the OO gmtime.
my @gmtime = CORE::gmtime $time; # This is the gmtime function
+ is @gmtime, 9, "gmtime($time)";
for my $method (@methods) {
is $gmtime->$method, shift @gmtime, "gmtime($time)->$method";
}
my(@times, @methods);
BEGIN {
- @times = (-2**62, -2**50, -2**33, -2**31-1, -1, 0, 1, 2**31-1, 2**33, 2**50, 2**62, time);
+ @times = (-2**55, -2**50, -2**33, -2**31-1, -1, 0, 1, 2**31-1, 2**33, 2**50, 2**55, time);
@methods = qw(sec min hour mday mon year wday yday isdst);
- plan tests => (@times * @methods) + 1;
+ plan tests => (@times * (@methods + 1)) + 1;
use_ok Time::localtime;
}
my $localtime = localtime $time; # This is the OO localtime.
my @localtime = CORE::localtime $time; # This is the localtime function
+ is @localtime, 9, "localtime($time)";
for my $method (@methods) {
is $localtime->$method, shift @localtime, "localtime($time)->$method";
}
=item gmtime(%.0f) too large
-(W overflow) You called C<gmtime> with an number that was beyond the 64-bit
-range that it accepts, and some rounding resulted. This warning is also
-triggered with nan (the special not-a-number value).
+(W overflow) You called C<gmtime> with an number that was larger than
+it can reliably handle and C<gmtime> probably returned the wrong
+date. This warning is also triggered with nan (the special
+not-a-number value).
+
+=item gmtime(%.0f) too small
+
+(W overflow) You called C<gmtime> with an number that was smaller than
+it can reliably handle and C<gmtime> probably returned the wrong
+date. This warning is also triggered with nan (the special
+not-a-number value).
=item Got an error from DosAllocMem
=item localtime(%.0f) too large
-(W overflow) You called C<localtime> with an number that was beyond the
-64-bit range that it accepts, and some rounding resulted. This warning is also triggered with nan (the special not-a-number value).
+(W overflow) You called C<localtime> with an number that was larger
+than it can reliably handle and C<localtime> probably returned the
+wrong date. This warning is also triggered with nan (the special
+not-a-number value).
+
+=item localtime(%.0f) too small
+
+(W overflow) You called C<localtime> with an number that was smaller
+than it can reliably handle and C<localtime> probably returned the
+wrong date. This warning is also triggered with nan (the special
+not-a-number value).
=item Lookbehind longer than %d not implemented in regex m/%s/
#endif /* HAS_TIMES */
}
+/* The 32 bit int year limits the times we can represent to these
+ boundaries with a few days wiggle room to account for time zone
+ offsets
+*/
+/* Sat Jan 3 00:00:00 -2147481748 */
+#define TIME_LOWER_BOUND -67768100567755200.0
+/* Sun Dec 29 12:00:00 2147483647 */
+#define TIME_UPPER_BOUND 67767976233316800.0
+
PP(pp_gmtime)
{
dVAR;
}
}
- if (PL_op->op_type == OP_LOCALTIME)
- err = S_localtime64_r(&when, &tmbuf);
- else
- err = S_gmtime64_r(&when, &tmbuf);
+ if ( TIME_LOWER_BOUND > when ) {
+ Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
+ "%s(%.0f) too small", opname, when);
+ err = NULL;
+ }
+ else if( when > TIME_UPPER_BOUND ) {
+ Perl_ck_warner(aTHX_ packWARN(WARN_OVERFLOW),
+ "%s(%.0f) too large", opname, when);
+ err = NULL;
+ }
+ else {
+ if (PL_op->op_type == OP_LOCALTIME)
+ err = S_localtime64_r(&when, &tmbuf);
+ else
+ err = S_gmtime64_r(&when, &tmbuf);
+ }
if (err == NULL) {
/* XXX %lld broken for quads */
-#!./perl
+#!./perl -w
BEGIN {
chdir 't' if -d 't';
require './test.pl';
}
-plan tests => 56;
+plan tests => 62;
# These tests make sure, among other things, that we don't end up
# burning tons of CPU for dates far in the future.
($xsec,$foo) = localtime($now);
$localyday = $yday;
-isnt($sec, $xsec), 'localtime() list context';
-ok $mday, ' month day';
-ok $year, ' year';
+isnt($sec, $xsec, 'localtime() list context');
+ok $mday, ' month day';
+ok $year, ' year';
ok(localtime() =~ /^(Sun|Mon|Tue|Wed|Thu|Fri|Sat)[ ]
(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[ ]
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime($beg);
($xsec,$foo) = localtime($now);
-isnt($sec, $xsec), 'gmtime() list conext';
-ok $mday, ' month day';
-ok $year, ' year';
+isnt($sec, $xsec, 'gmtime() list conext');
+ok $mday, ' month day';
+ok $year, ' year';
my $day_diff = $localyday - $yday;
ok( grep({ $day_diff == $_ } (0, 1, -1, 364, 365, -364, -365)),
{
eval {
$SIG{__WARN__} = sub { die @_; };
- localtime(1.23);
+ is( (localtime(1296000.23))[5] + 1900, 1970 );
};
is($@, '', 'Ignore fractional time');
eval {
$SIG{__WARN__} = sub { die @_; };
- gmtime(1.23);
+ is( (gmtime(1.23))[5] + 1900, 1970 );
};
is($@, '', 'Ignore fractional time');
}
is $have, $want, "year check, localtime($time)";
}
}
+
+
+# Test that Perl warns properly when it can't handle a time.
+{
+ my $warning;
+ local $SIG{__WARN__} = sub { $warning .= join "\n", @_; };
+
+ my $big_time = 2**60;
+ my $small_time = -2**60;
+
+ $warning = '';
+ my $date = gmtime($big_time);
+ like $warning, qr/^gmtime(.*) too large/;
+
+ $warning = '';
+ $date = localtime($big_time);
+ like $warning, qr/^localtime(.*) too large/;
+
+ $warning = '';
+ $date = gmtime($small_time);
+ like $warning, qr/^gmtime(.*) too small/;
+
+ $warning = '';
+ $date = localtime($small_time);
+ like $warning, qr/^localtime(.*) too small/;
+}
--- /dev/null
+#!perl -w
+
+# d95a2ea538e6c332f36c34ca45b78d6ad93c3a1f allowed times greater than
+# 2**63 to be handed to gm/localtime() which caused an internal overflow
+# and an excessively long loop. Test this does not happen.
+
+use strict;
+
+BEGIN { require './test.pl'; }
+
+plan tests => 2;
+watchdog(2);
+
+local $SIG{__WARN__} = sub {};
+is gmtime(2**69), undef;
+is localtime(2**69), undef;