Changeset 24394 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Jul 17, 2007, 7:25:38 PM (18 years ago)
Author:
darin
Message:

JavaScriptCore:

Reviewed by Darin, Maciej, and Adam.

Fixes <http://bugs.webkit.org/show_bug.cgi?id=9697>,

the failure of ecma/GlobalObject/15.1.2.2-2.js,
the failure of ecma/LexicalConventions/7.7.3-1.js,
and most of the failures of tests in ecma/TypeConversion/9.3.1-3.js.

Bug 9697: parseInt results may be inaccurate for numbers greater than 253

This patch also fixes similar issues in the lexer and UString::toDouble().

  • kjs/function.cpp: (KJS::parseIntOverflow): (KJS::parseInt):
  • kjs/function.h:
  • kjs/lexer.cpp: (KJS::Lexer::lex):
  • kjs/ustring.cpp: (KJS::UString::toDouble):
  • tests/mozilla/expected.html:

LayoutTests:

Reviewed by Darin.

Added tests for:
http://bugs.webkit.org/show_bug.cgi?id=9697

Bug 9697: parseInt results may be inaccurate for numbers greater than 253

  • fast/js/numeric-conversion-expected.txt: Added.
  • fast/js/numeric-conversion.html: Added.
  • fast/js/resources/numeric-conversion.js: Added.
Location:
trunk/JavaScriptCore/kjs
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/function.cpp

    r24244 r24394  
    55 *  Copyright (C) 2001 Peter Kelly ([email protected])
    66 *  Copyright (C) 2003 Apple Computer, Inc.
     7 *  Copyright (C) 2007 Cameron Zwarich ([email protected])
    78 *
    89 *  This library is free software; you can redistribute it and/or
     
    2627#include "function.h"
    2728
     29#include "dtoa.h"
    2830#include "internal.h"
    2931#include "function_object.h"
     
    670672}
    671673
     674double parseIntOverflow(const char* s, int length, int radix)
     675{
     676    double number = 0.0;
     677    double radixMultiplier = 1.0;
     678
     679    for (const char* p = s + length - 1; p >= s; p--) {
     680        if (radixMultiplier == Inf) {
     681            if (*p != '0') {
     682                number = Inf;
     683                break;
     684            }
     685        } else {
     686            int digit = parseDigit(*p, radix);
     687            number += digit * radixMultiplier;
     688        }
     689
     690        radixMultiplier *= radix;
     691    }
     692
     693    return number;
     694}
     695
    672696static double parseInt(const UString& s, int radix)
    673697{
     
    702726        return NaN;
    703727
     728    int firstDigitPosition = p;
    704729    bool sawDigit = false;
    705730    double number = 0;
     
    712737        number += digit;
    713738        ++p;
     739    }
     740
     741    if (number >= mantissaOverflowLowerBound) {
     742        if (radix == 10)
     743            number = kjs_strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0);
     744        else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
     745            number = parseIntOverflow(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), p - firstDigitPosition, radix);
    714746    }
    715747
  • trunk/JavaScriptCore/kjs/function.h

    r21889 r24394  
    233233  };
    234234
     235  static const double mantissaOverflowLowerBound = 9007199254740992.0;
     236  double parseIntOverflow(const char* s, int length, int radix);
     237
    235238UString escapeStringForPrettyPrinting(const UString& s);
    236239
  • trunk/JavaScriptCore/kjs/lexer.cpp

    r20304 r24394  
    44 *  Copyright (C) 1999-2000 Harri Porten ([email protected])
    55 *  Copyright (C) 2006 Apple Computer, Inc.
     6 *  Copyright (C) 2007 Cameron Zwarich ([email protected])
    67 *
    78 *  This library is free software; you can redistribute it and/or
     
    2829#include <string.h>
    2930
     31#include "function.h"
    3032#include "interpreter.h"
    3133#include "nodes.h"
     
    473475      dval += convertHex(c);
    474476    }
     477
     478    if (dval >= mantissaOverflowLowerBound)
     479      dval = parseIntOverflow(buffer8 + 2, p - (buffer8 + 3), 16);
     480
    475481    state = Number;
    476482  } else if (state == Octal) {   // scan octal number
     
    480486      dval += c - '0';
    481487    }
     488
     489    if (dval >= mantissaOverflowLowerBound)
     490      dval = parseIntOverflow(buffer8 + 1, p - (buffer8 + 2), 8);
     491
    482492    state = Number;
    483493  }
  • trunk/JavaScriptCore/kjs/ustring.cpp

    r20004 r24394  
    44 *  Copyright (C) 1999-2000 Harri Porten ([email protected])
    55 *  Copyright (C) 2004 Apple Computer, Inc.
     6 *  Copyright (C) 2007 Cameron Zwarich ([email protected])
    67 *
    78 *  This library is free software; you can redistribute it and/or
     
    2728#include "JSLock.h"
    2829#include "dtoa.h"
     30#include "function.h"
    2931#include "identifier.h"
    3032#include "operations.h"
     
    889891  // hex number ?
    890892  if (*c == '0' && (*(c+1) == 'x' || *(c+1) == 'X')) {
     893    const char* firstDigitPosition = c + 2;
    891894    c++;
    892895    d = 0.0;
     
    899902        break;
    900903    }
     904
     905    if (d >= mantissaOverflowLowerBound)
     906        d = parseIntOverflow(firstDigitPosition, c - firstDigitPosition, 16);
    901907  } else {
    902908    // regular number ?
    903909    char *end;
    904910    d = kjs_strtod(c, &end);
    905     if ((d != 0.0 || end != c) && d != HUGE_VAL && d != -HUGE_VAL) {
     911    if ((d != 0.0 || end != c) && d != Inf && d != -Inf) {
    906912      c = end;
    907913    } else {
    908       // infinity ?
    909       d = 1.0;
     914      double sign = 1.0;
     915
    910916      if (*c == '+')
    911917        c++;
    912918      else if (*c == '-') {
    913         d = -1.0;
     919        sign = -1.0;
    914920        c++;
    915921      }
    916       if (strncmp(c, "Infinity", 8) != 0)
     922
     923      // We used strtod() to do the conversion. However, strtod() handles
     924      // infinite values slightly differently than JavaScript in that it
     925      // converts the string "inf" with any capitalization to infinity,
     926      // whereas the ECMA spec requires that it be converted to NaN.
     927
     928      if (strncmp(c, "Infinity", 8) == 0) {
     929        d = sign * Inf;
     930        c += 8;
     931      } else if ((d == Inf || d == -Inf) && *c != 'I' && *c != 'i')
     932        c = end;
     933      else
    917934        return NaN;
    918       d = d * Inf;
    919       c += 8;
    920935    }
    921936  }
Note: See TracChangeset for help on using the changeset viewer.