Closed
Bug 742427
Opened 13 years ago
Closed 8 years ago
Date/setHours/getHours (in javascript interpreter) has an important bug in hour manipulation
Categories
(Core :: JavaScript Engine, defect)
Core
JavaScript Engine
Tracking
()
RESOLVED
FIXED
People
(Reporter: lextr, Unassigned)
Details
User Agent: Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20100101 Firefox/11.0
Build ID: 20120312181643
Steps to reproduce:
First of all it's very hard to track because it depends on your timezone. So for demonstration purposes I will suppose you are in the timezone GMT+1 (Brussels, Copenhagen, Madrid, Paris). For testing you have to switch to this timezone, otherwise the problem won't be visible. Here is the code that reveals the bug :
<script type="text/javascript">
//BUG
var d = new Date("Mar 29 2009 01:00:00");
alert("Old date : " + d);
d.setHours(d.getHours() + 1);
alert("New date : " + d); //stays same
//OTHER DATES WORKING, eg
var d = new Date("Mar 29 2010 01:00:00");
alert("Old date : " + d);
d.setHours(d.getHours() + 1);
alert("New date : " + d); //displays +1 h
</script>
Actual results:
The problem is that the hours are not added correctly :
1 - the date is not changing (no hours added) and staying at 01:00:00
2 - timezone is switched
Expected results:
The result should be 1 hour added to the date showing : 02:00:00, instead of staying at same 01:00:00
It can be reproduced with any timezone, but a different date should be used. For instance for the timezone UTC-5 (Indiana East) or GMT-4, the date which would be concerned is :
var d = new Date("Mar 08 2009 01:00:00");
P.S:
I'm marking this question as security related as well, because I have encountered possibility to exploit similar bugs.
Assignee: nobody → general
Component: Untriaged → JavaScript Engine
Product: Firefox → Core
QA Contact: untriaged → general
![]() |
||
Comment 1•13 years ago
|
||
You're advancing the date by an hour from 1am on the morning when daylight savings time starts.
The first "Old date" alert is already wrong for me. It shows the timezone as "GMT-0500 (EDT)". The right thing is either "GMT-0400 (EDT)" or "GMT-0500 (EST)".
Advancing from the 1am in the latter should put you at 1am in the former, I would think.
Interestingly, Chrome and Safari and Opera all have the same behavior we do (except they always list EST, not EDT), so I wonder what the spec actually calls for here...
I also noticed this in other browsers as well, so this is actually a general javascript behavior. The thing is that this kind of bug can be very hard to track as they are generally left unnoticed, but are important when the timing should be precise. Is this the general definition of GMT/UTC system which causes this? or a particular implementation of these functions?
Here is the code to make the problem visible on any timezone :
<script type="text/javascript">
var d = new Date("Jan 01 2008 01:00:00");
var d_c = 0, d_prev = 0, ci = 0;
while (true) {
ci++;
d_prev = d_c;
d_c = d.setHours(d.getHours() + 1);
if (d_c == d_prev) alert("For your timezone the bug is at :\r\n" + d + "\r\nMs : " + d.getTime() + "\r\nLoops : " + ci);
}
</script>
Also this shows that some timezones are affected while others are not, example :
no bug : GMT+0400 (Russian Standard Time) / UTC+4 Moscow, St.Petersburg, Volgograd
no bug : GMT+1000 (Yakutsk Standard Time) / UTC + 10 Yakutsk
no bug : GMT+0000 (Coordinated Universal Time) / UTC
yes, bug present : GMT+0200 / UTC+1 Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
yes, bug present : GMT-0600 (Mountain Daylight Time) / UTC-7 Mountain Time (US & Canada)
![]() |
||
Comment 5•13 years ago
|
||
The "not affected" timezones are simply the ones that don't have daylight savings time, no?
Yes and no, for example, Russia used DST before February 8, 2011 (which should still make it an unaffected & affected timezone), and they have also planned on reintroducing it, so for RST and Yakutsk or other Russia's regions it shouldn't actually affect these calculations while it does
The other thing is that the 2 "affected" dates in ms or timestamp will be converted/shown as a wrong dates/times. So even without setHours/getHours (or that writing format when initializing) there will still be a bug in "Date" because the timestamp is shift by 1h. Eg:
in GMT-0400 (US Eastern Daylight Time) / UTC-5 Indiana (East) timezone :
new Date(1205038800000)
new Date(1205042400000)
are incorrectly shown as :
Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
Sun Mar 09 2008 00:00:00 GMT-0500 (US Eastern Standard Time)
while a closer timestamp is shown correctly :
new Date(1205049600000)
Sun Mar 09 2008 04:00:00 GMT-0400 (US Eastern Daylight Time)
Summary: setHours/getHours (in javascript interpreter) has an important bug in hour manipulation → Date/setHours/getHours (in javascript interpreter) has an important bug in hour manipulation
This also means that : 1205038800000 < 1205042400000, while 01:00 < 00:00 is not true, so while the timestamps are actually successive the timing is not (00:00 < 01:00), like it should be.
in GMT+1 the previous dates are :
Sun Mar 09 2008 06:00:00 GMT+0100
Sun Mar 09 2008 07:00:00 GMT+0100
which satisfies the relation t1 < t2, but is not true in the concerned timezones for particular timestamps.
This means there is a problem counting actual time :
MS
1 206 831 600 000
1 206 835 200 000
1 206 838 800 000
MS (H)
0
3 600 000
3 600 000
----------
7 200 000
This means 2 hours.
Now in timing system for same dates in GMT+1 :
Sun Mar 30 2008 00:00:00 GMT+0100
Sun Mar 30 2008 01:00:00 GMT+0100 1h
Sun Mar 30 2008 03:00:00 GMT+0200 2h
3 hours.
There is 1 hour "missing" which is 02:00, while it should be there. We are dealing with an unefficiency in the GMT/UTC system.
Reporter | ||
Comment 10•13 years ago
|
||
Also it's better visible on the GMT+01:00 (Brussels, Copenhagen, Madrid, Paris) timezone:
alert(new Date(1206828000000));
alert(new Date(1206831600000));
alert(new Date(1206835200000));
alert(new Date(1206838800000));
alert(new Date(1206842400000));
Sat Mar 29 2008 23:00:00 GMT+0100
Sun Mar 30 2008 00:00:00 GMT+0100
Sun Mar 30 2008 01:00:00 GMT+0100
Sun Mar 30 2008 03:00:00 GMT+0200 <--- ???
Sun Mar 30 2008 04:00:00 GMT+0200 <--- ???
while doesn't seem to be such thing for GMT-5 Indiana
![]() |
||
Comment 11•13 years ago
|
||
Indiana does not have daylight savings time.
Reporter | ||
Comment 12•13 years ago
|
||
According to Windows 7 clock Indiana East UTC-05:00 has DST (there are probably some regions which don't).
But if it doesn't then the problem encompasses timezones without DST :
Here is the problem for Indiana :
alert(new Date(1205035200000));
alert(new Date(1205038800000));
alert(new Date(1205042400000));
alert(new Date(1205046000000));
alert(new Date(1205049600000));
Sat Mar 08 2008 23:00:00 GMT-0500 (US Eastern Standard Time)
Sun Mar 09 2008 00:00:00 GMT-0500 (US Eastern Standard Time)
Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
Sun Mar 09 2008 03:00:00 GMT-0400 (US Eastern Daylight Time) <--- ?
Sun Mar 09 2008 04:00:00 GMT-0400 (US Eastern Daylight Time) <--- ?
Reporter | ||
Comment 13•13 years ago
|
||
The step in the timestamps above is 3600000 (1H)
![]() |
||
Comment 14•13 years ago
|
||
Oh, hmm. Looks like Indiana switched to observing DST in 2006, actually. Then I'm not sure what was going on in comment 10.
Reporter | ||
Comment 15•13 years ago
|
||
This also means there is a problem calculating hours for these particular days in timestamps and also that some dates have many timestamp presentations (not unique)
Reporter | ||
Comment 16•13 years ago
|
||
Here is an example to illustrate it (Indiana) :
//Problem of unicity :
alert("X1.a");
t = "Mar 09 2008 02:00:00";
x = new Date(t);
alert(t + "\r\n" + x + "\r\n" + x.getTime());
/*
Result :
Mar 09 2008 02:00:00
Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
1205042400000
*/
alert("X1.b");
t = "Mar 09 2008 02:30:00";
x = new Date(t);
alert(t + "\r\n" + x + "\r\n" + x.getTime());
/*
Result :
Mar 09 2008 02:30:00
Sun Mar 09 2008 01:30:00 GMT-0500 (US Eastern Standard Time)
1205044200000
*/
/*
From this observation we see that timestamps are equal :
1205042400000 Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
1205044200000 Sun Mar 09 2008 01:30:00 GMT-0500 (US Eastern Standard Time)
But 01:00 is not equal to 01:30
There are 2 different timestamps which after some internal conversion result in equal timestamps for
two different dates
So there is either a problem of unicity or a collision
*/
Reporter | ||
Comment 17•13 years ago
|
||
Ok, it's not same, just got confused with the 24,42 from looking too long, but the other problems are still there
Reporter | ||
Comment 18•13 years ago
|
||
This example for uniqueness is better :
//Problem of unicity :
alert("X1.a");
t = "Mar 09 2008 02:00:00";
x = new Date(t);
alert(t + "\r\n" + x + "\r\n" + x.getTime());
/*
Mar 09 2008 02:00:00
Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
1205042400000
*/
alert("X1.b");
t = "Mar 09 2008 01:00:00";
x = new Date(t);
alert(t + "\r\n" + x + "\r\n" + x.getTime());
/*
Mar 09 2008 01:00:00
Sun Mar 09 2008 01:00:00 GMT-0500 (US Eastern Standard Time)
1205042400000
*/
Comment 19•13 years ago
|
||
daylight savings is hard, but this can't be used to hack Firefox itself so it doesn't need to be hidden. Site authors need to take care.
Group: core-security
Reporter | ||
Comment 20•13 years ago
|
||
It were marked as security related to limit potential possibility of buffer overflow exploitation (and other) since it affects all js interpreters and there were no information on how and why it were provoked within the js interpreter core.
So feel free to remove the security level of that bug if you think such exploitations cannot be done, since it requires a deeper analysis and a POC.
Assignee | ||
Updated•11 years ago
|
Assignee: general → nobody
Comment 21•8 years ago
|
||
Fixed in https://hg.mozilla.org/mozilla-central/rev/b7ef07909cc4
Before (Win10):
new Date("Mar 29 2009 01:00:00").toString()
"Sun Mar 29 2009 01:00:00 GMT+0100 (Romance Daylight Time)"
d = new Date("Mar 29 2009 01:00:00"); d.setHours(d.getHours() + 1); d.toString()
"Sun Mar 29 2009 03:00:00 GMT+0200 (Romance Standard Time)"
new Date(1205038800000).toString()
"Sun Mar 09 2008 00:00:00 GMT-0500 (Eastern Daylight Time)"
After (Win10):
new Date("Mar 29 2009 01:00:00").toString()
"Sun Mar 29 2009 01:00:00 GMT+0100 (Romance Standard Time)"
d = new Date("Mar 29 2009 01:00:00"); d.setHours(d.getHours() + 1); d.toString()
"Sun Mar 29 2009 03:00:00 GMT+0200 (Romance Daylight Time)"
new Date(1205038800000).toString()
"Sun Mar 09 2008 00:00:00 GMT-0500 (Eastern Standard Time)"
Status: UNCONFIRMED → RESOLVED
Closed: 8 years ago
Resolution: --- → FIXED
You need to log in
before you can comment on or make changes to this bug.
Description
•