PHP :: Bug #75851 :: Year component overflow with date formats "c", "o", "r" and "y"
php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75851 Year component overflow with date formats "c", "o", "r" and "y"
Submitted: 2018-01-20 09:38 UTC Modified: 2018-01-20 09:46 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:1 (50.0%)
From: juju2143 at gmail dot com Assigned:
Status: Open Package: Date/time related
PHP Version: 7.1.13 OS: macOS 10.12
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2018-01-20 09:38 UTC] juju2143 at gmail dot com
Description:
------------
I'm not sure whether PHP or even the human species will still be around when someone would want to process dates past the year 2147483647, but it seems that the format characters c, o, r, y (actually, probably everything that calculates the year except Y, L is untested) as defined in the date() manual page will compute the year component in a 32-bit integer. For consistency with Y, it might be desirable to upgrade those to 64-bit on 64-bit systems as well.

Test script:
---------------
echo date(DATE_ATOM."\n".DATE_RFC2822."\nc\nr\no\ny\nY\nU\n\n", PHP_INT_MIN);
echo date(DATE_ATOM."\n".DATE_RFC2822."\nc\nr\no\ny\nY\nU\n\n", 67767976233532799);
echo date(DATE_ATOM."\n".DATE_RFC2822."\nc\nr\no\ny\nY\nU\n\n", 67767976233532800);
echo date(DATE_ATOM."\n".DATE_RFC2822."\nc\nr\no\ny\nY\nU\n\n", PHP_INT_MAX);


Expected result:
----------------
-292277022657-01-27T08:29:52+00:00
Fri, 27 Jan -292277022657 08:29:52 +0000
-292277022657-01-27T08:29:52+00:00
Fri, 27 Jan -292277022657 08:29:52 +0000
-292277022657
57 (or -57?)
-292277022657
-9223372036854775808

2147483647-12-31T23:59:59+00:00
Tue, 31 Dec 2147483647 23:59:59 +0000
2147483647-12-31T23:59:59+00:00
Tue, 31 Dec 2147483647 23:59:59 +0000
2147483648
47
2147483647
67767976233532799

2147483648-01-01T00:00:00+00:00
Wed, 01 Jan 2147483648 00:00:00 +0000
2147483648-01-01T00:00:00+00:00
Wed, 01 Jan 2147483648 00:00:00 +0000
2147483648
48
2147483648
67767976233532800

292277026596-12-04T15:30:07+00:00
Sun, 04 Dec 292277026596 15:30:07 +0000
292277026596-12-04T15:30:07+00:00
Sun, 04 Dec 292277026596 15:30:07 +0000
292277026596
96
292277026596
9223372036854775807

Actual result:
--------------
-292277022657-01-27T08:29:52+00:00
Fri, 27 Jan -292277022657 08:29:52 +0000
-219246529-01-27T08:29:52+00:00
Fri, 27 Jan -219246529 08:29:52 +0000
-219246529
-29
-292277022657
-9223372036854775808

2147483647-12-31T23:59:59+00:00
Tue, 31 Dec 2147483647 23:59:59 +0000
2147483647-12-31T23:59:59+00:00
Tue, 31 Dec 2147483647 23:59:59 +0000
-2147483648
47
2147483647
67767976233532799

2147483648-01-01T00:00:00+00:00
Wed, 01 Jan 2147483648 00:00:00 +0000
-2147483648-01-01T00:00:00+00:00
Wed, 01 Jan -2147483648 00:00:00 +0000
-2147483648
-48
2147483648
67767976233532800

292277026596-12-04T15:30:07+00:00
Sun, 04 Dec 292277026596 15:30:07 +0000
219250468-12-04T15:30:07+00:00
Sun, 04 Dec 219250468 15:30:07 +0000
219250468
68
292277026596
9223372036854775807

Patches

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-01-20 09:46 UTC] juju2143 at gmail dot com
-Summary: Year component overflow with formats "c" and "r" +Summary: Year component overflow with date formats "c", "o", "r" and "y"
 [2018-01-20 09:46 UTC] juju2143 at gmail dot com
Changed the title.
 [2018-01-20 11:42 UTC] daverandom@php.net
I have worked up a PR for this but I'm not going to merge it without review.
 [2018-01-20 19:49 UTC] juju2143 at gmail dot com
Thanks! Also note that I also reproduced it on 7.0.27 on Linux and might also work on 7.2.
 [2018-01-20 23:21 UTC] daverandom@php.net
I would imagine this has been present for a long time, as year component is cast down to system int type for formatting. It's stored internally in timelib as a timelib_sll, which is a 64-bit signed integer, so it should be safe (afaict) to cast it to a zend_long instead and format it with %lld.

However, I'm not intimately familiar with PHP's internal printf augmentations, nor with timelib or ext/date, and I do not have a 32-bit system to test my changes against, which is why I would like it reviewed by someone who knows what they are doing before merging it :-)
 
PHP Copyright © 2001-2018 The PHP Group
All rights reserved.
Last updated: Mon Aug 20 22:01:26 2018 UTC