Skip to content

Commit e77c9f8

Browse files
committed
Fixes GH-20967: DateTime[Immutable]::createFromTimestamp(float) misses support for 64bit integers or 32bit environments
1 parent 19b3003 commit e77c9f8

5 files changed

Lines changed: 63 additions & 141 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ PHP NEWS
1717

1818
- Date:
1919
. Update timelib to 2022.16. (Derick)
20+
. Fixed bug GH-20967 (DateTime[Immutable]::createFromTimestamp(float) misses
21+
support for 64bit integers or 32bit environments). (marc-mabe)
2022

2123
- MbString:
2224
. Fixed bug GH-20833 (mb_str_pad() divide by zero if padding string is

ext/date/php_date.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,35 +2519,40 @@ PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, siz
25192519
return 1;
25202520
} /* }}} */
25212521

2522-
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec) /* {{{ */
2522+
PHPAPI void php_date_initialize_from_ts_sll(php_date_obj *dateobj, timelib_sll sec, int usec) /* {{{ */
25232523
{
25242524
dateobj->time = timelib_time_ctor();
25252525
dateobj->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
25262526

2527-
timelib_unixtime2gmt(dateobj->time, (timelib_sll)sec);
2527+
timelib_unixtime2gmt(dateobj->time, sec);
25282528
timelib_update_ts(dateobj->time, NULL);
25292529
php_date_set_time_fraction(dateobj->time, usec);
25302530
} /* }}} */
25312531

2532+
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec) /* {{{ */
2533+
{
2534+
php_date_initialize_from_ts_sll(dateobj, (timelib_sll)sec, usec);
2535+
} /* }}} */
2536+
25322537
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts) /* {{{ */
25332538
{
25342539
double sec_dval = trunc(ts);
2535-
zend_long sec;
2540+
timelib_sll sec;
25362541
int usec;
25372542

2538-
if (UNEXPECTED(isnan(sec_dval) || !PHP_DATE_DOUBLE_FITS_LONG(sec_dval))) {
2543+
if (UNEXPECTED(isnan(sec_dval) || !PHP_DATE_DOUBLE_FITS_SLL(sec_dval))) {
25392544
zend_argument_error(
25402545
date_ce_date_range_error,
25412546
1,
2542-
"must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2543-
TIMELIB_LONG_MIN,
2544-
TIMELIB_LONG_MAX,
2547+
"must be a finite number between " PHP_DATE_SLL_FMT " and " PHP_DATE_SLL_FMT ".999999, %g given",
2548+
INT64_MIN,
2549+
INT64_MAX,
25452550
ts
25462551
);
25472552
return false;
25482553
}
25492554

2550-
sec = (zend_long)sec_dval;
2555+
sec = (timelib_sll)sec_dval;
25512556
usec = (int) round(fmod(ts, 1) * 1000000);
25522557

25532558
if (UNEXPECTED(abs(usec) == 1000000)) {
@@ -2556,13 +2561,13 @@ PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts)
25562561
}
25572562

25582563
if (UNEXPECTED(usec < 0)) {
2559-
if (UNEXPECTED(sec == TIMELIB_LONG_MIN)) {
2564+
if (UNEXPECTED(sec == INT64_MAX)) {
25602565
zend_argument_error(
25612566
date_ce_date_range_error,
25622567
1,
2563-
"must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2564-
TIMELIB_LONG_MIN,
2565-
TIMELIB_LONG_MAX,
2568+
"must be a finite number between " PHP_DATE_SLL_FMT " and " PHP_DATE_SLL_FMT ".999999, %g given",
2569+
INT64_MIN,
2570+
INT64_MAX,
25662571
ts
25672572
);
25682573
return false;
@@ -2572,7 +2577,7 @@ PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts)
25722577
usec = 1000000 + usec;
25732578
}
25742579

2575-
php_date_initialize_from_ts_long(dateobj, sec, usec);
2580+
php_date_initialize_from_ts_sll(dateobj, sec, usec);
25762581

25772582
return true;
25782583
} /* }}} */

ext/date/php_date.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@
3737
# define PHP_DATE_DOUBLE_FITS_LONG(d) (!((d) >= (double)TIMELIB_LONG_MAX || (d) < (double)TIMELIB_LONG_MIN))
3838
#endif
3939

40+
/* Same as PHP_DATE_SIZEOF_LONG but for timelib_sll (int64_t) */
41+
#define PHP_DATE_DOUBLE_FITS_SLL(d) (!((d) >= (double)INT64_MAX || (d) < (double)INT64_MIN))
42+
43+
/* Same as TIMELIB_LONG_FMT but for timelib_sll (int64_t) */
44+
#define PHP_DATE_SLL_FMT "%" PRId64
45+
4046
#include "php_version.h"
4147
#define PHP_DATE_VERSION PHP_VERSION
4248

@@ -160,6 +166,7 @@ PHPAPI zend_class_entry *php_date_get_period_ce(void);
160166

161167
PHPAPI zval *php_date_instantiate(zend_class_entry *pce, zval *object);
162168
PHPAPI bool php_date_initialize(php_date_obj *dateobj, const char *time_str, size_t time_str_len, const char *format, zval *timezone_object, int flags);
169+
PHPAPI void php_date_initialize_from_ts_sll(php_date_obj *dateobj, timelib_sll sec, int usec);
163170
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec);
164171
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts);
165172

ext/date/tests/createFromTimestamp.phpt

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ $timestamps = array(
1818
0,
1919
0.0,
2020
-0.0,
21-
PHP_INT_MAX + 1024.0,
22-
PHP_INT_MIN - 1025.0,
21+
9223372036854775808.0, // INT64_MAX + 1
22+
-9223372036854777856.0, // INT64_MIN - 2048
2323
NAN,
2424
+INF,
2525
-INF,
2626
1599828571.235628,
2727
-1599828571.235628,
28+
2147483648.0, // INT32_MAX + 1
29+
-2147483649.0, // INT32_MIN - 1
2830
);
2931

3032
foreach ($timestamps as $ts) {
@@ -245,6 +247,38 @@ DateTimeImmutable::createFromTimestamp(-1599828571.235628): object(DateTimeImmut
245247
["timezone"]=>
246248
string(6) "+00:00"
247249
}
250+
DateTime::createFromTimestamp(2147483648.0): object(DateTime)#%d (3) {
251+
["date"]=>
252+
string(26) "2038-01-19 03:14:08.000000"
253+
["timezone_type"]=>
254+
int(1)
255+
["timezone"]=>
256+
string(6) "+00:00"
257+
}
258+
DateTimeImmutable::createFromTimestamp(2147483648.0): object(DateTimeImmutable)#%d (3) {
259+
["date"]=>
260+
string(26) "2038-01-19 03:14:08.000000"
261+
["timezone_type"]=>
262+
int(1)
263+
["timezone"]=>
264+
string(6) "+00:00"
265+
}
266+
DateTime::createFromTimestamp(-2147483649.0): object(DateTime)#%d (3) {
267+
["date"]=>
268+
string(26) "1901-12-13 20:45:51.000000"
269+
["timezone_type"]=>
270+
int(1)
271+
["timezone"]=>
272+
string(6) "+00:00"
273+
}
274+
DateTimeImmutable::createFromTimestamp(-2147483649.0): object(DateTimeImmutable)#%d (3) {
275+
["date"]=>
276+
string(26) "1901-12-13 20:45:51.000000"
277+
["timezone_type"]=>
278+
int(1)
279+
["timezone"]=>
280+
string(6) "+00:00"
281+
}
248282
MyDateTime::createFromTimestamp(0): object(MyDateTime)#%d (3) {
249283
["date"]=>
250284
string(26) "1970-01-01 00:00:00.000000"

ext/date/tests/createFromTimestamp_32bit.phpt

Lines changed: 0 additions & 126 deletions
This file was deleted.

0 commit comments

Comments
 (0)