Changeset 166876 in webkit


Ignore:
Timestamp:
Apr 7, 2014 11:24:31 AM (10 years ago)
Author:
mark.lam@apple.com
Message:

Date object needs to check for ES5 15.9.1.14 TimeClip limit.
<https://webkit.org/b/131248>

Reviewed by Mark Hahnenberg.

Source/JavaScriptCore:

The current Date object code does not adequately check for the ES5
15.9.1.14 TimeClip limit. As a result, some calculations can underflow
/ overflow and produce unexpected results.

For example, we were getting an assertion failure in
WTF::equivalentYearForDST() due int underflows in this function, which
in turn were due to an int overflow in WTF::msToYear().

This patch adds the needed checks, and adds some assertions to ensure
that the used values are sane.

The changes have no noticeable impact on benchmark results.

  • runtime/DateConstructor.cpp:

(JSC::callDate):

  • runtime/JSDateMath.cpp:

(JSC::localTimeOffset):
(JSC::gregorianDateTimeToMS):
(JSC::msToGregorianDateTime):
(JSC::parseDateFromNullTerminatedCharacters):
(JSC::parseDate):

  • runtime/JSDateMath.h:
  • parseDateFromNullTerminatedCharacters() does not need to be public. Made it a static function.
  • runtime/VM.cpp:

(JSC::VM::resetDateCache):

  • Changed cachedDateStringValue to use std::numeric_limits<double>::quiet_NaN() to be consistent with other Date code.

Source/WTF:

  • wtf/DateMath.cpp:
  • Moved the definition of maxECMAScriptTime to the .h file so that we can use it in other files as well.

(WTF::msToYear):

  • Removed a stale comment for parseDateFromNullTerminatedCharacters().
  • wtf/DateMath.h:

LayoutTests:

  • js/regress-131248-expected.txt: Added.
  • js/regress-131248.html: Added.
  • js/script-tests/regress-131248.js: Added.

(testDateFromSetDateAdjustement):
(testDateFromSetTimeWithMilliseconds):
(testDateFromString):

Location:
trunk
Files:
3 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r166875 r166876  
     12014-04-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Date object needs to check for ES5 15.9.1.14 TimeClip limit.
     4        <https://webkit.org/b/131248>
     5
     6        Reviewed by Mark Hahnenberg.
     7
     8        * js/regress-131248-expected.txt: Added.
     9        * js/regress-131248.html: Added.
     10        * js/script-tests/regress-131248.js: Added.
     11        (testDateFromSetDateAdjustement):
     12        (testDateFromSetTimeWithMilliseconds):
     13        (testDateFromString):
     14
    1152014-04-07  Sergio Villar Senin  <svillar@igalia.com>
    216
  • trunk/Source/JavaScriptCore/ChangeLog

    r166857 r166876  
     12014-04-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Date object needs to check for ES5 15.9.1.14 TimeClip limit.
     4        <https://webkit.org/b/131248>
     5
     6        Reviewed by Mark Hahnenberg.
     7
     8        The current Date object code does not adequately check for the ES5
     9        15.9.1.14 TimeClip limit.  As a result, some calculations can underflow
     10        / overflow and produce unexpected results.
     11
     12        For example, we were getting an assertion failure in
     13        WTF::equivalentYearForDST() due int underflows in this function, which
     14        in turn were due to an int overflow in WTF::msToYear().
     15
     16        This patch adds the needed checks, and adds some assertions to ensure
     17        that the used values are sane.
     18
     19        The changes have no noticeable impact on benchmark results.
     20
     21        * runtime/DateConstructor.cpp:
     22        (JSC::callDate):
     23        * runtime/JSDateMath.cpp:
     24        (JSC::localTimeOffset):
     25        (JSC::gregorianDateTimeToMS):
     26        (JSC::msToGregorianDateTime):
     27        (JSC::parseDateFromNullTerminatedCharacters):
     28        (JSC::parseDate):
     29        * runtime/JSDateMath.h:
     30        - parseDateFromNullTerminatedCharacters() does not need to be public.
     31          Made it a static function.
     32        * runtime/VM.cpp:
     33        (JSC::VM::resetDateCache):
     34        - Changed cachedDateStringValue to use std::numeric_limits<double>::quiet_NaN()
     35          to be consistent with other Date code.
     36
    1372014-04-06  Csaba Osztrogonác  <ossy@webkit.org>
    238
  • trunk/Source/JavaScriptCore/runtime/DateConstructor.cpp

    r165703 r166876  
    11/*
    22 *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
     3 *  Copyright (C) 2004-2008, 2011, 2014 Apple Inc. All rights reserved.
    44 *
    55 *  This library is free software; you can redistribute it and/or
     
    191191    VM& vm = exec->vm();
    192192    GregorianDateTime ts;
    193     msToGregorianDateTime(vm, currentTimeMS(), false, ts);
     193
     194    double currentTime = timeClip(currentTimeMS());
     195    if (std::isnan(currentTime))
     196        return JSValue::encode(jsNaN());
     197   
     198    msToGregorianDateTime(vm, currentTime, false, ts);
    194199    return JSValue::encode(jsNontrivialString(&vm, formatDateTime(ts, DateTimeFormatDateAndTime, false)));
    195200}
  • trunk/Source/JavaScriptCore/runtime/JSDateMath.cpp

    r163844 r166876  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006, 2007, 2012 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2007, 2012, 2014 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2007-2009 Torch Mobile, Inc.
     
    139139    double end = cache.end;
    140140
     141    ASSERT(fabs(ms) <= WTF::maxECMAScriptTime);
    141142    if (start <= ms) {
    142143        // If the time fits in the cached interval, return the cached offset.
     
    146147        double newEnd = end + cache.increment;
    147148
    148         if (ms <= newEnd) {
     149        if (ms <= newEnd && newEnd <= WTF::maxECMAScriptTime) {
    149150            LocalTimeOffset endOffset = calculateLocalTimeOffset(newEnd);
    150151            if (cache.offset == endOffset) {
     
    195196    double result = (day * WTF::msPerDay) + ms;
    196197
     198    if (fabs(result) > WTF::maxECMAScriptTime)
     199        return std::numeric_limits<double>::quiet_NaN();
     200
    197201    if (!inputIsUTC)
    198202        result -= localTimeOffset(vm, result).offset;
    199203
    200     return result;
     204    return timeClip(result);
    201205}
    202206
     
    204208void msToGregorianDateTime(VM& vm, double ms, bool outputIsUTC, GregorianDateTime& tm)
    205209{
     210    ASSERT(fabs(ms) <= WTF::maxECMAScriptTime);
    206211    LocalTimeOffset localTime;
    207212    if (!outputIsUTC) {
     
    223228}
    224229
    225 double parseDateFromNullTerminatedCharacters(VM& vm, const char* dateString)
     230static double parseDateFromNullTerminatedCharacters(VM& vm, const char* dateString)
    226231{
    227232    bool haveTZ;
    228233    int offset;
    229234    double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset);
    230     if (std::isnan(ms))
    231         return QNaN;
     235    if (std::isnan(ms) || fabs(ms) > WTF::maxECMAScriptTime)
     236        return std::numeric_limits<double>::quiet_NaN();
    232237
    233238    // fall back to local timezone
     
    245250    if (std::isnan(value))
    246251        value = parseDateFromNullTerminatedCharacters(vm, date.utf8().data());
     252    value = timeClip(value);
    247253    vm.cachedDateString = date;
    248254    vm.cachedDateStringValue = value;
  • trunk/Source/JavaScriptCore/runtime/JSDateMath.h

    r156540 r166876  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2007, 2014 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
     
    5454double gregorianDateTimeToMS(VM&, const GregorianDateTime&, double, bool inputIsUTC);
    5555double getUTCOffset(VM&);
    56 double parseDateFromNullTerminatedCharacters(VM&, const char* dateString);
    5756double parseDate(VM&, const WTF::String&);
    5857
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r166121 r166876  
    502502    localTimeOffsetCache.reset();
    503503    cachedDateString = String();
    504     cachedDateStringValue = QNaN;
     504    cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
    505505    dateInstanceCache.reset();
    506506}
  • trunk/Source/WTF/ChangeLog

    r166837 r166876  
     12014-04-04  Mark Lam  <mark.lam@apple.com>
     2
     3        Date object needs to check for ES5 15.9.1.14 TimeClip limit.
     4        <https://webkit.org/b/131248>
     5
     6        Reviewed by Mark Hahnenberg.
     7
     8        * wtf/DateMath.cpp:
     9        - Moved the definition of maxECMAScriptTime to the .h file so that we
     10          can use it in other files as well.
     11        (WTF::msToYear):
     12        - Removed a stale comment for parseDateFromNullTerminatedCharacters().
     13        * wtf/DateMath.h:
     14
    1152014-04-04  Mark Hahnenberg  <mhahnenberg@apple.com>
    216
  • trunk/Source/WTF/wtf/DateMath.cpp

    r165667 r166876  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2007, 2014 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2007-2009 Torch Mobile, Inc.
     
    110110
    111111static const double maxUnixTime = 2145859200.0; // 12/31/2037
    112 // ECMAScript asks not to support for a date of which total
    113 // millisecond value is larger than the following value.
    114 // See 15.9.1.14 of ECMA-262 5th edition.
    115 static const double maxECMAScriptTime = 8.64E15;
    116112
    117113// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1.
     
    185181int msToYear(double ms)
    186182{
     183    ASSERT(fabs(ms) <= maxECMAScriptTime);
    187184    int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970);
    188185    double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear);
     
    331328
    332329/*
    333  * Find an equivalent year for the one given, where equivalence is deterined by
     330 * Find an equivalent year for the one given, where equivalence is determined by
    334331 * the two years having the same leapness and the first day of the year, falling
    335332 * on the same day of the week.
     
    797794}
    798795
    799 // Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore.
    800796double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset)
    801797{
  • trunk/Source/WTF/wtf/DateMath.h

    r156154 r166876  
    11/*
    22 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
    3  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
     3 * Copyright (C) 2006-2007, 2014 Apple Inc. All rights reserved.
    44 * Copyright (C) 2009 Google Inc. All rights reserved.
    55 * Copyright (C) 2010 Research In Motion Limited. All rights reserved.
     
    5353
    5454namespace WTF {
     55
     56// ECMAScript asks not to support for a date of which total
     57// millisecond value is larger than the following value.
     58// See 15.9.1.14 of ECMA-262 5th edition.
     59static const double maxECMAScriptTime = 8.64E15;
    5560
    5661struct LocalTimeOffset {
Note: See TracChangeset for help on using the changeset viewer.