Skip to content

Commit d527647

Browse files
committed
Fix GH-19371: integer overflow in calendar.c
1 parent cdfd663 commit d527647

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

ext/calendar/calendar.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,16 @@ PHP_FUNCTION(cal_days_in_month)
194194
RETURN_THROWS();
195195
}
196196

197+
if (UNEXPECTED(month <= 0 || month > INT32_MAX - 1)) {
198+
zend_argument_value_error(2, "must be between 0 and %d", INT32_MAX - 1);
199+
RETURN_THROWS();
200+
}
201+
202+
if (UNEXPECTED(year > INT32_MAX - 1)) {
203+
zend_argument_value_error(3, "must be less than %d", INT32_MAX - 1);
204+
RETURN_THROWS();
205+
}
206+
197207
calendar = &cal_conversion_table[cal];
198208

199209
sdn_start = calendar->to_jd(year, month, 1);
@@ -239,6 +249,21 @@ PHP_FUNCTION(cal_to_jd)
239249
RETURN_THROWS();
240250
}
241251

252+
if (UNEXPECTED(month <= 0 || month > INT32_MAX - 1)) {
253+
zend_argument_value_error(2, "must be between 0 and %d", INT32_MAX - 1);
254+
RETURN_THROWS();
255+
}
256+
257+
if (UNEXPECTED(ZEND_LONG_EXCEEDS_INT(day))) {
258+
zend_argument_value_error(3, "must be between %d and %d", INT32_MIN, INT32_MAX);
259+
RETURN_THROWS();
260+
}
261+
262+
if (UNEXPECTED(year > INT32_MAX - 1)) {
263+
zend_argument_value_error(4, "must be less than %d", INT32_MAX - 1);
264+
RETURN_THROWS();
265+
}
266+
242267
RETURN_LONG(cal_conversion_table[cal].to_jd(year, month, day));
243268
}
244269
/* }}} */

ext/calendar/tests/cal_days_in_month_error1.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ try {
1212
echo "{$ex->getMessage()}\n";
1313
}
1414
try{
15-
cal_days_in_month(CAL_GREGORIAN,0, 2009);
15+
cal_days_in_month(CAL_GREGORIAN,20, 2009);
1616
} catch (ValueError $ex) {
1717
echo "{$ex->getMessage()}\n";
1818
}

ext/calendar/tests/gh19371.phpt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
GH-19371 (integer overflow in calendar.c)
3+
--EXTENSIONS--
4+
calendar
5+
--FILE--
6+
<?php
7+
8+
try {
9+
echo cal_days_in_month(CAL_GREGORIAN, 12, PHP_INT_MAX);
10+
} catch (ValueError $e) {
11+
echo $e->getMessage(), "\n";
12+
}
13+
try {
14+
echo cal_days_in_month(CAL_GREGORIAN, PHP_INT_MIN, 1);
15+
} catch (ValueError $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
try {
19+
echo cal_days_in_month(CAL_GREGORIAN, PHP_INT_MAX, 1);
20+
} catch (ValueError $e) {
21+
echo $e->getMessage(), "\n";
22+
}
23+
24+
try {
25+
echo cal_to_jd(CAL_GREGORIAN, PHP_INT_MIN, 1, 1);
26+
} catch (ValueError $e) {
27+
echo $e->getMessage(), "\n";
28+
}
29+
try {
30+
echo cal_to_jd(CAL_GREGORIAN, PHP_INT_MAX, 1, 1);
31+
} catch (ValueError $e) {
32+
echo $e->getMessage(), "\n";
33+
}
34+
try {
35+
echo cal_to_jd(CAL_GREGORIAN, 1, PHP_INT_MIN, 1);
36+
} catch (ValueError $e) {
37+
echo $e->getMessage(), "\n";
38+
}
39+
try {
40+
echo cal_to_jd(CAL_GREGORIAN, 1, PHP_INT_MAX, 1);
41+
} catch (ValueError $e) {
42+
echo $e->getMessage(), "\n";
43+
}
44+
try {
45+
echo cal_to_jd(CAL_GREGORIAN, 1, 1, PHP_INT_MAX);
46+
} catch (ValueError $e) {
47+
echo $e->getMessage(), "\n";
48+
}
49+
50+
?>
51+
--EXPECT--
52+
cal_days_in_month(): Argument #3 ($year) must be less than 2147483646
53+
cal_days_in_month(): Argument #2 ($month) must be between 0 and 2147483646
54+
cal_days_in_month(): Argument #2 ($month) must be between 0 and 2147483646
55+
cal_to_jd(): Argument #2 ($month) must be between 0 and 2147483646
56+
cal_to_jd(): Argument #2 ($month) must be between 0 and 2147483646
57+
cal_to_jd(): Argument #3 ($day) must be between -2147483648 and 2147483647
58+
cal_to_jd(): Argument #3 ($day) must be between -2147483648 and 2147483647
59+
cal_to_jd(): Argument #4 ($year) must be less than 2147483646

0 commit comments

Comments
 (0)