Skip to content

Commit a3f3404

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-19371: integer overflow in calendar.c
2 parents 4342059 + 11e6655 commit a3f3404

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

ext/calendar/calendar.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,16 @@ PHP_FUNCTION(cal_days_in_month)
197197
RETURN_THROWS();
198198
}
199199

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

202212
sdn_start = calendar->to_jd(year, month, 1);
@@ -242,6 +252,21 @@ PHP_FUNCTION(cal_to_jd)
242252
RETURN_THROWS();
243253
}
244254

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

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

0 commit comments

Comments
 (0)