Skip to content

Commit d9e3738

Browse files
committed
Support range of INT64_MIN/MAX on 32bit for DateTime[Immutable]::createFromTimestamp
1 parent 2e2494f commit d9e3738

File tree

4 files changed

+61
-141
lines changed

4 files changed

+61
-141
lines changed

ext/date/php_date.c

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

2484-
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec) /* {{{ */
2484+
PHPAPI void php_date_initialize_from_ts_sll(php_date_obj *dateobj, timelib_sll sec, int usec) /* {{{ */
24852485
{
24862486
dateobj->time = timelib_time_ctor();
24872487
dateobj->time->zone_type = TIMELIB_ZONETYPE_OFFSET;
24882488

2489-
timelib_unixtime2gmt(dateobj->time, (timelib_sll)sec);
2489+
timelib_unixtime2gmt(dateobj->time, sec);
24902490
timelib_update_ts(dateobj->time, NULL);
24912491
php_date_set_time_fraction(dateobj->time, usec);
24922492
} /* }}} */
24932493

2494+
PHPAPI void php_date_initialize_from_ts_long(php_date_obj *dateobj, zend_long sec, int usec) /* {{{ */
2495+
{
2496+
php_date_initialize_from_ts_sll(dateobj, (timelib_sll)sec, usec);
2497+
} /* }}} */
2498+
24942499
PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts) /* {{{ */
24952500
{
24962501
double sec_dval = trunc(ts);
2497-
zend_long sec;
2502+
timelib_sll sec;
24982503
int usec;
24992504

2500-
if (UNEXPECTED(isnan(sec_dval) || !PHP_DATE_DOUBLE_FITS_LONG(sec_dval))) {
2505+
if (UNEXPECTED(isnan(sec_dval) || !PHP_DATE_DOUBLE_FITS_SLL(sec_dval))) {
25012506
zend_argument_error(
25022507
date_ce_date_range_error,
25032508
1,
2504-
"must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2505-
TIMELIB_LONG_MIN,
2506-
TIMELIB_LONG_MAX,
2509+
"must be a finite number between " PHP_DATE_SLL_FMT " and " PHP_DATE_SLL_FMT ".999999, %g given",
2510+
INT64_MIN,
2511+
INT64_MAX,
25072512
ts
25082513
);
25092514
return false;
25102515
}
25112516

2512-
sec = (zend_long)sec_dval;
2517+
sec = (timelib_sll)sec_dval;
25132518
usec = (int) round(fmod(ts, 1) * 1000000);
25142519

25152520
if (UNEXPECTED(abs(usec) == 1000000)) {
@@ -2518,13 +2523,13 @@ PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts)
25182523
}
25192524

25202525
if (UNEXPECTED(usec < 0)) {
2521-
if (UNEXPECTED(sec == TIMELIB_LONG_MIN)) {
2526+
if (UNEXPECTED(sec == INT64_MAX)) {
25222527
zend_argument_error(
25232528
date_ce_date_range_error,
25242529
1,
2525-
"must be a finite number between " TIMELIB_LONG_FMT " and " TIMELIB_LONG_FMT ".999999, %g given",
2526-
TIMELIB_LONG_MIN,
2527-
TIMELIB_LONG_MAX,
2530+
"must be a finite number between " PHP_DATE_SLL_FMT " and " PHP_DATE_SLL_FMT ".999999, %g given",
2531+
INT64_MIN,
2532+
INT64_MAX,
25282533
ts
25292534
);
25302535
return false;
@@ -2534,7 +2539,7 @@ PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts)
25342539
usec = 1000000 + usec;
25352540
}
25362541

2537-
php_date_initialize_from_ts_long(dateobj, sec, usec);
2542+
php_date_initialize_from_ts_sll(dateobj, sec, usec);
25382543

25392544
return true;
25402545
} /* }}} */

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)