Title: [88503] trunk
Revision
88503
Author
[email protected]
Date
2011-06-09 16:46:54 -0700 (Thu, 09 Jun 2011)

Log Message

Bug 62405 - Fix integer overflow in Array.prototype.push

Reviewed by Oliver Hunt.

There are three integer overflows here, leading to safe (not a security risk)
but incorrect (non-spec-compliant) behaviour.

Two overflows occur when calculating the new length after pushing (one in the
fast version of push in JSArray, one in the generic version in ArrayPrototype).
The other occurs calculating indices to write to when multiple items are pushed.

These errors result in three test-262 failures.

Source/_javascript_Core: 

* runtime/ArrayPrototype.cpp:
(JSC::arrayProtoFuncPush):
* runtime/JSArray.cpp:
(JSC::JSArray::put):
(JSC::JSArray::push):

LayoutTests: 

* sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A3-expected.txt:
* sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T2-expected.txt:
* sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T3-expected.txt:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (88502 => 88503)


--- trunk/LayoutTests/ChangeLog	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/LayoutTests/ChangeLog	2011-06-09 23:46:54 UTC (rev 88503)
@@ -1,3 +1,22 @@
+2011-06-09  Gavin Barraclough  <[email protected]>
+
+        Reviewed by Oliver Hunt.
+
+        Bug 62405 - Fix integer overflow in Array.prototype.push
+
+        There are three integer overflows here, leading to safe (not a security risk)
+        but incorrect (non-spec-compliant) behaviour.
+
+        Two overflows occur when calculating the new length after pushing (one in the
+        fast version of push in JSArray, one in the generic version in ArrayPrototype).
+        The other occurs calculating indices to write to when multiple items are pushed.
+
+        These errors result in three test-262 failures.
+
+        * sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A3-expected.txt:
+        * sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T2-expected.txt:
+        * sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T3-expected.txt:
+
 2011-06-09  Martin Robinson  <[email protected]>
 
         Reviewed by Eric Seidel.

Modified: trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A3-expected.txt (88502 => 88503)


--- trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A3-expected.txt	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A3-expected.txt	2011-06-09 23:46:54 UTC (rev 88503)
@@ -1,6 +1,6 @@
 S15.4.4.7_A3
 
-FAIL SputnikError: #2.2: x = []; x.length = 4294967295; x.push("x") throw RangeError. Actual: SputnikError: #2.1: x = []; x.length = 4294967295; x.push("x") throw RangeError. Actual: 4294967295
+PASS 
 
 TEST COMPLETE
 

Modified: trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T2-expected.txt (88502 => 88503)


--- trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T2-expected.txt	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T2-expected.txt	2011-06-09 23:46:54 UTC (rev 88503)
@@ -1,6 +1,6 @@
 S15.4.4.7_A4_T2
 
-FAIL SputnikError: #1: var obj = {}; obj.push = Array.prototype.push; obj.length = 4294967295; obj.push("x", "y", "z") === 4294967298. Actual: 2
+PASS 
 
 TEST COMPLETE
 

Modified: trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T3-expected.txt (88502 => 88503)


--- trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T3-expected.txt	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/LayoutTests/sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/15.4.4.7_Array_prototype_push/S15.4.4.7_A4_T3-expected.txt	2011-06-09 23:46:54 UTC (rev 88503)
@@ -1,6 +1,6 @@
 S15.4.4.7_A4_T3
 
-FAIL SputnikError: #1: var obj = {}; obj.push = Array.prototype.push; obj.length = -1; obj.push("x", "y", "z") === 4294967298. Actual: 2
+PASS 
 
 TEST COMPLETE
 

Modified: trunk/Source/_javascript_Core/ChangeLog (88502 => 88503)


--- trunk/Source/_javascript_Core/ChangeLog	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-06-09 23:46:54 UTC (rev 88503)
@@ -1,3 +1,24 @@
+2011-06-09  Gavin Barraclough  <[email protected]>
+
+        Reviewed by Oliver Hunt.
+
+        Bug 62405 - Fix integer overflow in Array.prototype.push
+
+        There are three integer overflows here, leading to safe (not a security risk)
+        but incorrect (non-spec-compliant) behaviour.
+
+        Two overflows occur when calculating the new length after pushing (one in the
+        fast version of push in JSArray, one in the generic version in ArrayPrototype).
+        The other occurs calculating indices to write to when multiple items are pushed.
+
+        These errors result in three test-262 failures.
+
+        * runtime/ArrayPrototype.cpp:
+        (JSC::arrayProtoFuncPush):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::put):
+        (JSC::JSArray::push):
+
 2011-06-09  Dan Bernstein  <[email protected]>
 
         Reviewed by Anders Carlsson.

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (88502 => 88503)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2011-06-09 23:46:54 UTC (rev 88503)
@@ -401,11 +401,19 @@
     if (exec->hadException())
         return JSValue::encode(jsUndefined());
 
-    for (unsigned n = 0; n < exec->argumentCount(); n++)
-        thisObj->put(exec, length + n, exec->argument(n));
-    length += exec->argumentCount();
-    putProperty(exec, thisObj, exec->propertyNames().length, jsNumber(length));
-    return JSValue::encode(jsNumber(length));
+    for (unsigned n = 0; n < exec->argumentCount(); n++) {
+        // Check for integer overflow; where safe we can do a fast put by index.
+        if (length + n >= length)
+            thisObj->put(exec, length + n, exec->argument(n));
+        else {
+            PutPropertySlot slot;
+            Identifier propertyName(exec, JSValue((int64_t)length + (int64_t)n).toString(exec));
+            thisObj->put(exec, propertyName, exec->argument(n), slot);
+        }
+    }
+    JSValue newLength = jsNumber((int64_t)length + (int64_t)exec->argumentCount());
+    putProperty(exec, thisObj, exec->propertyNames().length, newLength);
+    return JSValue::encode(newLength);
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)

Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (88502 => 88503)


--- trunk/Source/_javascript_Core/runtime/JSArray.cpp	2011-06-09 23:37:45 UTC (rev 88502)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp	2011-06-09 23:46:54 UTC (rev 88503)
@@ -330,7 +330,7 @@
     if (propertyName == exec->propertyNames().length) {
         unsigned newLength = value.toUInt32(exec);
         if (value.toNumber(exec) != static_cast<double>(newLength)) {
-            throwError(exec, createRangeError(exec, "Invalid array length."));
+            throwError(exec, createRangeError(exec, "Invalid array length"));
             return;
         }
         setLength(newLength);
@@ -736,6 +736,12 @@
     
     ArrayStorage* storage = m_storage;
 
+    if (UNLIKELY(storage->m_length == 0xFFFFFFFFu)) {
+        put(exec, storage->m_length, value);
+        throwError(exec, createRangeError(exec, "Invalid array length"));
+        return;
+    }
+
     if (storage->m_length < m_vectorLength) {
         storage->m_vector[storage->m_length].set(exec->globalData(), this, value);
         ++storage->m_numValuesInVector;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to