cataphract Sun, 19 Dec 2010 23:47:00 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=306475
Log: - Fixed bug #53574 (Integer overflow in SdnToJulian, sometimes leading to segfault). Bug: http://bugs.php.net/53574 (Assigned) Integer overflow in SdnToJulian Changed paths: U php/php-src/branches/PHP_5_3/NEWS U php/php-src/branches/PHP_5_3/ext/calendar/julian.c A php/php-src/branches/PHP_5_3/ext/calendar/tests/bug53574.phpt U php/php-src/trunk/ext/calendar/julian.c A php/php-src/trunk/ext/calendar/tests/bug53574.phpt Modified: php/php-src/branches/PHP_5_3/NEWS =================================================================== --- php/php-src/branches/PHP_5_3/NEWS 2010-12-19 23:46:27 UTC (rev 306474) +++ php/php-src/branches/PHP_5_3/NEWS 2010-12-19 23:47:00 UTC (rev 306475) @@ -12,6 +12,10 @@ (Ilia) . Fixed bug #48607 (fwrite() doesn't check reply from ftp server before exiting). (Ilia) + +- Calendar extension: + . Fixed bug #53574 (Integer overflow in SdnToJulian, sometimes leading to + segfault). (Gustavo) - DateTime extension: . Fixed a bug in DateTime->modify() where absolute date/time statements had Modified: php/php-src/branches/PHP_5_3/ext/calendar/julian.c =================================================================== --- php/php-src/branches/PHP_5_3/ext/calendar/julian.c 2010-12-19 23:46:27 UTC (rev 306474) +++ php/php-src/branches/PHP_5_3/ext/calendar/julian.c 2010-12-19 23:47:00 UTC (rev 306475) @@ -146,6 +146,7 @@ **************************************************************************/ #include "sdncal.h" +#include <limits.h> #define JULIAN_SDN_OFFSET 32083 #define DAYS_PER_5_MONTHS 153 @@ -164,15 +165,22 @@ int dayOfYear; if (sdn <= 0) { - *pYear = 0; - *pMonth = 0; - *pDay = 0; - return; + goto fail; } - temp = (sdn + JULIAN_SDN_OFFSET) * 4 - 1; + /* Check for overflow */ + if (sdn > (LONG_MAX - JULIAN_SDN_OFFSET * 4 + 1) / 4 || sdn < LONG_MIN / 4) { + goto fail; + } + temp = sdn * 4 + (JULIAN_SDN_OFFSET * 4 - 1); /* Calculate the year and day of year (1 <= dayOfYear <= 366). */ - year = temp / DAYS_PER_4_YEARS; + { + long yearl = temp / DAYS_PER_4_YEARS; + if (yearl > INT_MAX || yearl < INT_MIN) { + goto fail; + } + year = (int) yearl; + } dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1; /* Calculate the month and day of month. */ @@ -196,6 +204,12 @@ *pYear = year; *pMonth = month; *pDay = day; + return; + +fail: + *pYear = 0; + *pMonth = 0; + *pDay = 0; } long int JulianToSdn( Added: php/php-src/branches/PHP_5_3/ext/calendar/tests/bug53574.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/calendar/tests/bug53574.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/ext/calendar/tests/bug53574.phpt 2010-12-19 23:47:00 UTC (rev 306475) @@ -0,0 +1,35 @@ +--TEST-- +Bug #53574 (Integer overflow in SdnToJulian; leads to segfault) +--SKIPIF-- +<?php include 'skipif.inc'; ?> +--FILE-- +<?php +if (PHP_INT_MAX == 0x7FFFFFFF) { + $x = 882858043; +} else { + $x = 3315881921229094912; +} + +var_dump(cal_from_jd($x, CAL_JULIAN)); +--EXPECT-- +array(9) { + ["date"]=> + string(5) "0/0/0" + ["month"]=> + int(0) + ["day"]=> + int(0) + ["year"]=> + int(0) + ["dow"]=> + int(3) + ["abbrevdayname"]=> + string(3) "Wed" + ["dayname"]=> + string(9) "Wednesday" + ["abbrevmonth"]=> + string(0) "" + ["monthname"]=> + string(0) "" +} + Modified: php/php-src/trunk/ext/calendar/julian.c =================================================================== --- php/php-src/trunk/ext/calendar/julian.c 2010-12-19 23:46:27 UTC (rev 306474) +++ php/php-src/trunk/ext/calendar/julian.c 2010-12-19 23:47:00 UTC (rev 306475) @@ -146,6 +146,7 @@ **************************************************************************/ #include "sdncal.h" +#include <limits.h> #define JULIAN_SDN_OFFSET 32083 #define DAYS_PER_5_MONTHS 153 @@ -164,15 +165,22 @@ int dayOfYear; if (sdn <= 0) { - *pYear = 0; - *pMonth = 0; - *pDay = 0; - return; + goto fail; } - temp = (sdn + JULIAN_SDN_OFFSET) * 4 - 1; + /* Check for overflow */ + if (sdn > (LONG_MAX - JULIAN_SDN_OFFSET * 4 + 1) / 4 || sdn < LONG_MIN / 4) { + goto fail; + } + temp = sdn * 4 + (JULIAN_SDN_OFFSET * 4 - 1); /* Calculate the year and day of year (1 <= dayOfYear <= 366). */ - year = temp / DAYS_PER_4_YEARS; + { + long yearl = temp / DAYS_PER_4_YEARS; + if (yearl > INT_MAX || yearl < INT_MIN) { + goto fail; + } + year = (int) yearl; + } dayOfYear = (temp % DAYS_PER_4_YEARS) / 4 + 1; /* Calculate the month and day of month. */ @@ -196,6 +204,12 @@ *pYear = year; *pMonth = month; *pDay = day; + return; + +fail: + *pYear = 0; + *pMonth = 0; + *pDay = 0; } long int JulianToSdn( Added: php/php-src/trunk/ext/calendar/tests/bug53574.phpt =================================================================== --- php/php-src/trunk/ext/calendar/tests/bug53574.phpt (rev 0) +++ php/php-src/trunk/ext/calendar/tests/bug53574.phpt 2010-12-19 23:47:00 UTC (rev 306475) @@ -0,0 +1,35 @@ +--TEST-- +Bug #53574 (Integer overflow in SdnToJulian; leads to segfault) +--SKIPIF-- +<?php include 'skipif.inc'; ?> +--FILE-- +<?php +if (PHP_INT_MAX == 0x7FFFFFFF) { + $x = 882858043; +} else { + $x = 3315881921229094912; +} + +var_dump(cal_from_jd($x, CAL_JULIAN)); +--EXPECT-- +array(9) { + ["date"]=> + string(5) "0/0/0" + ["month"]=> + int(0) + ["day"]=> + int(0) + ["year"]=> + int(0) + ["dow"]=> + int(3) + ["abbrevdayname"]=> + string(3) "Wed" + ["dayname"]=> + string(9) "Wednesday" + ["abbrevmonth"]=> + string(0) "" + ["monthname"]=> + string(0) "" +} +
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php