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;