]> granicus.if.org Git - php/commitdiff
- Fixed bug #53574 (Integer overflow in SdnToJulian, sometimes leading to
authorGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 19 Dec 2010 23:47:00 +0000 (23:47 +0000)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Sun, 19 Dec 2010 23:47:00 +0000 (23:47 +0000)
  segfault).

NEWS
ext/calendar/julian.c
ext/calendar/tests/bug53574.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 65d8c3b180d2e9d43f41240c68a2fb11a9eab0fb..aa55786525812fe905a7fb113d6e5739fb9586f0 100644 (file)
--- a/NEWS
+++ b/NEWS
     (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
index 39bcbc7e655d4a2d498db735b91daf443ce71850..17e7bcb5974ad7ace03f12d95f6880a483757b22 100644 (file)
  **************************************************************************/
 
 #include "sdncal.h"
+#include <limits.h>
 
 #define JULIAN_SDN_OFFSET         32083
 #define DAYS_PER_5_MONTHS  153
@@ -164,15 +165,22 @@ void SdnToJulian(
        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 @@ void SdnToJulian(
        *pYear = year;
        *pMonth = month;
        *pDay = day;
+       return;
+
+fail:
+       *pYear = 0;
+       *pMonth = 0;
+       *pDay = 0;
 }
 
 long int JulianToSdn(
diff --git a/ext/calendar/tests/bug53574.phpt b/ext/calendar/tests/bug53574.phpt
new file mode 100644 (file)
index 0000000..e426991
--- /dev/null
@@ -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) ""
+}
+