Skip to content

Commit 09ca095

Browse files
committed
Fix GH-18422: int overflow in php_date_llabs
php_date_llabs negated its argument with -i, which is UB when i is LLONG_MIN. Cast to uint64_t before negating and use stdint types throughout. Updated Y/x/X format call sites to PRIu64. Fixes GH-18422 Closes GH-21638
1 parent 3a8307d commit 09ca095

4 files changed

Lines changed: 32 additions & 10 deletions

File tree

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.4.22
44

5+
- Date:
6+
. Fixed bug GH-18422 (int overflow in php_date_llabs). (iliaal)
7+
58
- Intl:
69
. Fix incorrect argument positions in out-of-bounds errors for
710
IntlCalendar::set(), IntlCalendar::setDate(), IntlCalendar::setDateTime(),

ext/date/config0.m4

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ AX_CHECK_COMPILE_FLAG([-Wno-implicit-fallthrough],
99
[-Werror])
1010

1111
PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -I@ext_builddir@/lib -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1 -DHAVE_TIMELIB_CONFIG_H=1"
12+
13+
AX_CHECK_COMPILE_FLAG([-fwrapv],
14+
[PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -fwrapv"])
15+
1216
timelib_sources="lib/astro.c lib/dow.c lib/parse_date.c lib/parse_tz.c lib/parse_posix.c
1317
lib/timelib.c lib/tm2unixtime.c lib/unixtime2tm.c lib/parse_iso_intervals.c lib/interval.c"
1418

ext/date/php_date.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,7 @@
3131
#include "win32/time.h"
3232
#endif
3333

34-
#ifdef PHP_WIN32
35-
static __inline __int64 php_date_llabs( __int64 i ) { return i >= 0? i: -i; }
36-
#elif defined(__GNUC__) && __GNUC__ < 3
37-
static __inline __int64_t php_date_llabs( __int64_t i ) { return i >= 0 ? i : -i; }
38-
#else
39-
static inline long long php_date_llabs( long long i ) { return i >= 0 ? i : -i; }
40-
#endif
34+
static inline uint64_t php_date_llabs(int64_t i) { return i >= 0 ? (uint64_t)i : -(uint64_t)i; }
4135

4236
#ifdef PHP_WIN32
4337
#define DATE_I64_BUF_LEN 65
@@ -742,9 +736,9 @@ static zend_string *date_format(const char *format, size_t format_len, timelib_t
742736
/* year */
743737
case 'L': length = slprintf(buffer, sizeof(buffer), "%d", timelib_is_leap((int) t->y)); break;
744738
case 'y': length = slprintf(buffer, sizeof(buffer), "%02d", (int) (t->y % 100)); break;
745-
case 'Y': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break;
746-
case 'x': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : (t->y >= 10000 ? "+" : ""), php_date_llabs((timelib_sll) t->y)); break;
747-
case 'X': length = slprintf(buffer, sizeof(buffer), "%s%04lld", t->y < 0 ? "-" : "+", php_date_llabs((timelib_sll) t->y)); break;
739+
case 'Y': length = slprintf(buffer, sizeof(buffer), "%s%04" PRIu64, t->y < 0 ? "-" : "", php_date_llabs((timelib_sll) t->y)); break;
740+
case 'x': length = slprintf(buffer, sizeof(buffer), "%s%04" PRIu64, t->y < 0 ? "-" : (t->y >= 10000 ? "+" : ""), php_date_llabs((timelib_sll) t->y)); break;
741+
case 'X': length = slprintf(buffer, sizeof(buffer), "%s%04" PRIu64, t->y < 0 ? "-" : "+", php_date_llabs((timelib_sll) t->y)); break;
748742

749743
/* time */
750744
case 'a': length = slprintf(buffer, sizeof(buffer), "%s", t->h >= 12 ? "pm" : "am"); break;

ext/date/tests/gh18422.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-18422 (int overflow in Date extension)
3+
--FILE--
4+
<?php
5+
date_default_timezone_set('UTC');
6+
7+
$dto = date_create("2006-12-12");
8+
date_isodate_set($dto, PHP_INT_MIN, 1, 1);
9+
echo $dto->format("Y"), "\n";
10+
echo $dto->format("x"), "\n";
11+
echo $dto->format("X"), "\n";
12+
13+
echo date_create("2024-06-15")->format("Y"), "\n";
14+
echo date_create("-0042-01-01")->format("Y"), "\n";
15+
?>
16+
--EXPECTF--
17+
-%d
18+
-%d
19+
-%d
20+
2024
21+
-0042

0 commit comments

Comments
 (0)