1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
--- /dev/null
+++ b/ext/calendar/tests/bug53574.phpt
@@ -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) ""
+}
+
--- a/ext/calendar/julian.c
+++ b/ext/calendar/julian.c
@@ -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 @@ 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(
|