今天遇到一个bug,获取有效期值错误,在定位跟踪后发现有效期有值,如下:
$expireDate = 2133999048; //2037-08-16 09:30:48
但是在该时间戳的基础上加上1 year后, $expireDate的值为false,而不是正确的时间戳。
<?php $expireDate = strtotime("+1 year", $expireDate); echo($expireDate);//31536000 转换时间格式为1971-01-01 08:00:00
网上搜索一下,说是32位的unix时间戳漏洞,称为Y2K38 漏洞。64位的系统不受此影响.
Y2K38 漏洞
Y2K38,又称 Unix Millennium Bug,此漏洞将会影响到所有 32 位系统下用 UNIX 时间戳整数来记录时间的 PHP,及其它编程语言。 一个整型的变量所能保存的最大时间为 2038 年01月19 日 03:14:07。超过这个时间后,整型数值将会溢出。 从 1970 年 01 月 01 日开始,到世界标准时 2038 年 01 月 19 日星期二凌晨 03:14:07 超过 2^31 – 1。2^31 – 1 就是0x7FFFFFFF,相信很多编程员都看过,
在 32 位系统里,这表示最大的有符号整数。如果用它来表示秒数,大概相当于 68.1 年,从 1970 年到 2038 年刚好是这个数。
在php中一个有效的时间是从 1970-01-01 07:00:00 – 2038-01-19 03:14:07. 这个的 关于php中unix时间戳的产生
<?php echo strtotime('2038-01-19 03:14:07').PHP_EOL; // 2147483647 echo strtotime('1970-01-01 07:00:00'); // 0"Y-m-d", $expireDate);//25200
那么那如何判断定一个时间戳能顺利返回正确的时间通常有两种方法
逆向思维方法
function is_timestamp($timestamp) { if(strtotime(date('m-d-Y H:i:s', $timestamp)) === $timestamp) { return $timestamp; } else { return false; } }
普通的整数范围判断
$is_unixtime = ctype_digit($str) && $str <= 2147483647;
这种方法比较简单粗暴。