Title: [102709] trunk
Revision
102709
Author
[email protected]
Date
2011-12-13 15:17:43 -0800 (Tue, 13 Dec 2011)

Log Message

Arguments object doesn't handle mutation of length property correctly
https://bugs.webkit.org/show_bug.cgi?id=74454

Reviewed by Gavin Barraclough.

Source/_javascript_Core:

Correct handling of arguments objects with overridden length property

* interpreter/Interpreter.cpp:
(JSC::loadVarargs):
* runtime/Arguments.cpp:
(JSC::Arguments::copyToArguments):
(JSC::Arguments::fillArgList):

LayoutTests:

Add tests of mutated arguments.length

* fast/js/arguments-expected.txt:
* fast/js/script-tests/arguments.js:
(argumentLengthIs5):
(duplicateArgumentAndReturnLast_call):
(duplicateArgumentAndReturnFirst_call):
(duplicateArgumentAndReturnLast_apply):
(duplicateArgumentAndReturnFirst_apply):

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (102708 => 102709)


--- trunk/LayoutTests/ChangeLog	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/LayoutTests/ChangeLog	2011-12-13 23:17:43 UTC (rev 102709)
@@ -1,3 +1,20 @@
+2011-12-13  Oliver Hunt  <[email protected]>
+
+        Arguments object doesn't handle mutation of length property correctly
+        https://bugs.webkit.org/show_bug.cgi?id=74454
+
+        Reviewed by Gavin Barraclough.
+
+        Add tests of mutated arguments.length
+
+        * fast/js/arguments-expected.txt:
+        * fast/js/script-tests/arguments.js:
+        (argumentLengthIs5):
+        (duplicateArgumentAndReturnLast_call):
+        (duplicateArgumentAndReturnFirst_call):
+        (duplicateArgumentAndReturnLast_apply):
+        (duplicateArgumentAndReturnFirst_apply):
+
 2011-12-13  Vsevolod Vlasov  <[email protected]>
 
         Web Inspector: Network item view does not correctly decode "+" in request parameters.

Modified: trunk/LayoutTests/fast/js/arguments-expected.txt (102708 => 102709)


--- trunk/LayoutTests/fast/js/arguments-expected.txt	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/LayoutTests/fast/js/arguments-expected.txt	2011-12-13 23:17:43 UTC (rev 102709)
@@ -18,6 +18,13 @@
 PASS access_3(1, 2, 3, 4, 5) is 3
 PASS access_4(1, 2, 3, 4, 5) is 4
 PASS access_5(1, 2, 3, 4, 5) is 5
+PASS argumentLengthIs5() is 5
+PASS argumentLengthIs5(1,2,3,4,5) is 5
+PASS argumentLengthIs5(1,2,3,4,5,6,7,8,9,10) is 5
+PASS duplicateArgumentAndReturnLast_call(1) is 1
+PASS duplicateArgumentAndReturnFirst_call(1) is 1
+PASS duplicateArgumentAndReturnLast_apply(1) is 1
+PASS duplicateArgumentAndReturnFirst_apply(1) is 1
 PASS tear_off_equal_access_1(1, 2, 3) is 1
 PASS tear_off_equal_access_2(1, 2, 3) is 2
 PASS tear_off_equal_access_3(1, 2, 3) is 3

Modified: trunk/LayoutTests/fast/js/script-tests/arguments.js (102708 => 102709)


--- trunk/LayoutTests/fast/js/script-tests/arguments.js	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/LayoutTests/fast/js/script-tests/arguments.js	2011-12-13 23:17:43 UTC (rev 102709)
@@ -27,6 +27,31 @@
     return arguments[4];
 }
 
+function argumentLengthIs5() {
+    arguments.length = 5;
+    return arguments.length;
+}
+
+function duplicateArgumentAndReturnLast_call(a) {
+    Array.prototype.push.call(arguments, a);
+    return arguments[1];
+}
+
+function duplicateArgumentAndReturnFirst_call(a) {
+    Array.prototype.push.call(arguments, a);
+    return arguments[0];
+}
+
+function duplicateArgumentAndReturnLast_apply(a) {
+    Array.prototype.push.apply(arguments, arguments);
+    return arguments[1];
+}
+
+function duplicateArgumentAndReturnFirst_apply(a) {
+    Array.prototype.push.apply(arguments, arguments);
+    return arguments[0];
+}
+
 shouldBe("access_1(1, 2, 3)", "1");
 shouldBe("access_2(1, 2, 3)", "2");
 shouldBe("access_3(1, 2, 3)", "3");
@@ -45,6 +70,14 @@
 shouldBe("access_4(1, 2, 3, 4, 5)", "4");
 shouldBe("access_5(1, 2, 3, 4, 5)", "5");
 
+shouldBe("argumentLengthIs5()", "5");
+shouldBe("argumentLengthIs5(1,2,3,4,5)", "5");
+shouldBe("argumentLengthIs5(1,2,3,4,5,6,7,8,9,10)", "5");
+shouldBe("duplicateArgumentAndReturnLast_call(1)", "1");
+shouldBe("duplicateArgumentAndReturnFirst_call(1)", "1");
+shouldBe("duplicateArgumentAndReturnLast_apply(1)", "1");
+shouldBe("duplicateArgumentAndReturnFirst_apply(1)", "1");
+
 function f(a, b, c)
 {
     return arguments;

Modified: trunk/Source/_javascript_Core/ChangeLog (102708 => 102709)


--- trunk/Source/_javascript_Core/ChangeLog	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/Source/_javascript_Core/ChangeLog	2011-12-13 23:17:43 UTC (rev 102709)
@@ -1,3 +1,18 @@
+2011-12-13  Oliver Hunt  <[email protected]>
+
+        Arguments object doesn't handle mutation of length property correctly
+        https://bugs.webkit.org/show_bug.cgi?id=74454
+
+        Reviewed by Gavin Barraclough.
+
+        Correct handling of arguments objects with overridden length property
+
+        * interpreter/Interpreter.cpp:
+        (JSC::loadVarargs):
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::copyToArguments):
+        (JSC::Arguments::fillArgList):
+
 2011-12-13  Filip Pizlo  <[email protected]>
 
         DFG GetByVal CSE rule should match PutByValAlias

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (102708 => 102709)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2011-12-13 23:17:43 UTC (rev 102709)
@@ -495,7 +495,7 @@
     if (asObject(arguments)->classInfo() == &Arguments::s_info) {
         Arguments* argsObject = asArguments(arguments);
         unsigned argCount = argsObject->length(callFrame);
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argCount + 1 + RegisterFile::CallFrameHeaderSize);
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
         if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
             callFrame->globalData().exception = createStackOverflowError(callFrame);
             return 0;
@@ -509,7 +509,7 @@
     if (isJSArray(&callFrame->globalData(), arguments)) {
         JSArray* array = asArray(arguments);
         unsigned argCount = array->length();
-        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argCount + 1 + RegisterFile::CallFrameHeaderSize);
+        CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
         if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
             callFrame->globalData().exception = createStackOverflowError(callFrame);
             return 0;
@@ -522,7 +522,7 @@
 
     JSObject* argObject = asObject(arguments);
     unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
-    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + argCount + 1 + RegisterFile::CallFrameHeaderSize);
+    CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + firstFreeRegister + CallFrame::offsetFor(argCount + 1));
     if (argCount > Arguments::MaxArguments || !registerFile->grow(newCallFrame->registers())) {
         callFrame->globalData().exception = createStackOverflowError(callFrame);
         return 0;

Modified: trunk/Source/_javascript_Core/runtime/Arguments.cpp (102708 => 102709)


--- trunk/Source/_javascript_Core/runtime/Arguments.cpp	2011-12-13 22:24:38 UTC (rev 102708)
+++ trunk/Source/_javascript_Core/runtime/Arguments.cpp	2011-12-13 23:17:43 UTC (rev 102709)
@@ -54,6 +54,12 @@
 
 void Arguments::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t length)
 {
+    if (UNLIKELY(d->overrodeLength)) {
+        length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length);
+        for (unsigned i = 0; i < length; i++)
+            callFrame->setArgument(i, get(exec, i));
+        return;
+    }
     ASSERT(length == this->length(exec));
     for (size_t i = 0; i < length; ++i) {
         if (!d->deletedArguments || !d->deletedArguments[i])
@@ -65,6 +71,12 @@
 
 void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
 {
+    if (UNLIKELY(d->overrodeLength)) {
+        unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec); 
+        for (unsigned i = 0; i < length; i++) 
+            args.append(get(exec, i)); 
+        return;
+    }
     uint32_t length = this->length(exec);
     for (size_t i = 0; i < length; ++i) {
         if (!d->deletedArguments || !d->deletedArguments[i])
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to