Reviewed by Maciej.

        - fixed <rdar://problem/3519285>: integer operations on large negative numbers yield bad results (discovered with "HTMLCrypt")
        - fixed other related overflow issues

        * kjs/value.h: Changed return types of toInteger, toInt32, toUInt32, and toUInt16.
        * kjs/value.cpp:
        (ValueImp::toInteger): Change to return a double, since this operation, from the ECMA specification,
        must not restrict values to the range of a particular integer type.
        (ValueImp::toInt32): Used a sized integer type for the result of this function, and also added
        proper handling for negative results from fmod.
        (ValueImp::toUInt32): Ditto.
        (ValueImp::toUInt16): Ditto.
        (ValueImp::dispatchToUInt32): Changed result type from unsigned to uint32_t.

        * kjs/array_object.cpp: (ArrayProtoFuncImp::call): Use a double instead of an int to handle
        out-of-integer-range values better in the slice function.
        * kjs/internal.cpp: (KJS::roundValue): Streamline the function, handling NAN and infinity properly.
        * kjs/number_object.cpp: (NumberProtoFuncImp::call): Use a double instead of an int to handle
        out-of-integer-range values better in the toString function.
        * kjs/string_object.cpp: (StringProtoFuncImp::call): Use a double instead of an int to handle
        out-of-integer-range values better in the charAt, charCodeAt, indexOf, lastIndexOf, slice,
        and substr functions.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6025 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/string_object.cpp b/JavaScriptCore/kjs/string_object.cpp
index df2acc2..877e9e6 100644
--- a/JavaScriptCore/kjs/string_object.cpp
+++ b/JavaScriptCore/kjs/string_object.cpp
@@ -186,9 +186,9 @@
     return String(thisObj.internalValue().toString(exec));
   }
 
-  int n, m;
   UString u, u2, u3;
   int pos, p0, i;
+  double dpos;
   double d = 0.0;
 
   UString s = thisObj.toString(exec);
@@ -203,19 +203,19 @@
     // handled above
     break;
   case CharAt:
-    pos = a0.toInteger(exec);
-    if (pos < 0 || pos >= len)
+    dpos = a0.toInteger(exec);
+    if (dpos < 0 || dpos >= len)
       u = "";
     else
-      u = s.substr(pos, 1);
+      u = s.substr(static_cast<int>(dpos), 1);
     result = String(u);
     break;
   case CharCodeAt:
-    pos = a0.toInteger(exec);
-    if (pos < 0 || pos >= len)
+    dpos = a0.toInteger(exec);
+    if (dpos < 0 || dpos >= len)
       d = NaN;
     else {
-      UChar c = s[pos];
+      UChar c = s[static_cast<int>(dpos)];
       d = (c.high() << 8) + c.low();
     }
     result = Number(d);
@@ -231,22 +231,30 @@
   case IndexOf:
     u2 = a0.toString(exec);
     if (a1.type() == UndefinedType)
-      pos = 0;
-    else
-      pos = a1.toInteger(exec);
-    d = s.find(u2, pos);
+      dpos = 0;
+    else {
+      dpos = a1.toInteger(exec);
+      if (dpos < 0)
+        dpos = 0;
+      else if (dpos > len)
+        dpos = len;
+    }
+    d = s.find(u2, static_cast<int>(dpos));
     result = Number(d);
     break;
   case LastIndexOf:
     u2 = a0.toString(exec);
     d = a1.toNumber(exec);
-    if (a1.type() == UndefinedType || KJS::isNaN(d) || KJS::isPosInf(d))
-      pos = len;
-    else
-      pos = a1.toInteger(exec);
-    if (pos < 0)
-      pos = 0;
-    d = s.rfind(u2, pos);
+    if (a1.type() == UndefinedType || KJS::isNaN(d))
+      dpos = len;
+    else {
+      dpos = a1.toInteger(exec);
+      if (dpos < 0)
+        dpos = 0;
+      else if (dpos > len)
+        dpos = len;
+    }
+    d = s.rfind(u2, static_cast<int>(dpos));
     result = Number(d);
     break;
   case Match:
@@ -377,21 +385,29 @@
   case Slice: // http://developer.netscape.com/docs/manuals/js/client/jsref/string.htm#1194366
     {
         // The arg processing is very much like ArrayProtoFunc::Slice
-        int begin = args[0].toUInt32(exec);
-        if (begin < 0)
-          begin = maxInt(begin + len, 0);
-        else
-          begin = minInt(begin, len);
-        int end = len;
+        double begin = args[0].toInteger(exec);
+        if (begin < 0) {
+          begin += len;
+          if (begin < 0)
+            begin = 0;
+        } else {
+          if (begin > len)
+            begin = len;
+        }
+        double end = len;
         if (args[1].type() != UndefinedType) {
           end = args[1].toInteger(exec);
-          if (end < 0)
-            end = maxInt(len + end, 0);
-          else
-            end = minInt(end, len);
+          if (end < 0) {
+            end += len;
+            if (end < 0)
+              end = 0;
+          } else {
+            if (end > len)
+              end = len;
+          }
         }
         //printf( "Slicing from %d to %d \n", begin, end );
-        result = String(s.substr(begin, end-begin));
+        result = String(s.substr(static_cast<int>(begin), static_cast<int>(end-begin)));
         break;
     }
     case Split: {
@@ -451,18 +467,22 @@
     }
     break;
   case Substr: {
-    n = a0.toInteger(exec);
-    m = a1.toInteger(exec);
-    int d, d2;
-    if (n >= 0)
-      d = n;
-    else
-      d = maxInt(len + n, 0);
+    double d = a0.toInteger(exec);
+    double d2 = a1.toInteger(exec);
+    if (d < 0) {
+      d += len;
+      if (d < 0)
+        d = 0;
+    }
     if (a1.type() == UndefinedType)
       d2 = len - d;
-    else
-      d2 = minInt(maxInt(m, 0), len - d);
-    result = String(s.substr(d, d2));
+    else {
+      if (d2 < 0)
+        d2 = 0;
+      if (d2 > len - d)
+        d2 = len - d;
+    }
+    result = String(s.substr(static_cast<int>(d), static_cast<int>(d2)));
     break;
   }
   case Substring: {