diff options
author | Michael G. Schwern <schwern@pobox.com> | 2010-01-31 03:22:08 -0800 |
---|---|---|
committer | Craig A. Berry <craigberry@mac.com> | 2010-02-05 12:49:05 -0600 |
commit | fc003d4b0d731bb670adb07e168c683339ec57e7 (patch) | |
tree | b9a1f4d99883196df80277597ec950669ec41240 /pp_sys.c | |
parent | 23d72198749db53785b1c67cd1a37697afb95fc0 (diff) | |
download | perl-fc003d4b0d731bb670adb07e168c683339ec57e7.tar.gz |
Don't try to calculate a time over the conservative failure boundary.
Otherwise gmtime(2**66) will cause a very, very, very long loop and
DOS Perl.
Add a test that very, very large times don't send gmtime and localtime into a loop
Had to fix some revealed mistakes in op/time.t when warnings were turned on.
Fix Time::gmtime and Time::localtime tests to match the new limits of gm/localtime.
Diffstat (limited to 'pp_sys.c')
-rw-r--r-- | pp_sys.c | 29 |
1 files changed, 25 insertions, 4 deletions
@@ -4485,6 +4485,15 @@ PP(pp_tms) #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; @@ -4513,10 +4522,22 @@ PP(pp_gmtime) } } - 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 */ |