From bfc988552f6b0f2e950b2221046e7fdc5e2d595a Mon Sep 17 00:00:00 2001 From: Saki Takamachi <34942839+SakiTakamachi@users.noreply.github.com> Date: Tue, 11 Jun 2024 19:02:43 +0900 Subject: [PATCH] Fixed GH-14383: Fixed usec was carry up (#14463) If round to the fractional part of a timestamp, a carry will occur in cases such as 999 999 9. In that case, set usec to 0 and add/sub 1 to sec. --- ext/date/php_date.c | 5 +++ ext/date/tests/gh14383.phpt | 61 +++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 ext/date/tests/gh14383.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index e2050227120..0702f635230 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2537,6 +2537,11 @@ PHPAPI bool php_date_initialize_from_ts_double(php_date_obj *dateobj, double ts) sec = (zend_long)sec_dval; usec = (int) round(fmod(ts, 1) * 1000000); + if (UNEXPECTED(abs(usec) == 1000000)) { + sec += usec > 0 ? 1 : -1; + usec = 0; + } + if (UNEXPECTED(usec < 0)) { if (UNEXPECTED(sec == TIMELIB_LONG_MIN)) { zend_argument_error( diff --git a/ext/date/tests/gh14383.phpt b/ext/date/tests/gh14383.phpt new file mode 100644 index 00000000000..dd145da9a24 --- /dev/null +++ b/ext/date/tests/gh14383.phpt @@ -0,0 +1,61 @@ +--TEST-- +Bug GH-14383 (DateTime::createFromTimestamp overflowed microseconds value) +--INI-- +date.timezone=UTC +--FILE-- +format('s.u'), "\n"; +} + +echo "\nminus:\n"; +foreach ($cases as [$usec, $label]) { + echo "-{$label}: "; + echo DateTime::createFromTimestamp(-$usec)->format('s.u'), "\n"; +} +?> +--EXPECT-- +plus: +0.999_999_0: 00.999999 +0.999_999_1: 00.999999 +0.999_999_8: 01.000000 +0.999_999_9: 01.000000 +1.000_000_0: 01.000000 +1.000_000_1: 01.000000 +1.000_000_8: 01.000001 +1.000_000_9: 01.000001 +1.000_001_0: 01.000001 +1.000_001_1: 01.000001 +1.000_001_8: 01.000002 +1.000_001_9: 01.000002 + +minus: +-0.999_999_0: 59.000001 +-0.999_999_1: 59.000001 +-0.999_999_8: 59.000000 +-0.999_999_9: 59.000000 +-1.000_000_0: 59.000000 +-1.000_000_1: 59.000000 +-1.000_000_8: 58.999999 +-1.000_000_9: 58.999999 +-1.000_001_0: 58.999999 +-1.000_001_1: 58.999999 +-1.000_001_8: 58.999998 +-1.000_001_9: 58.999998