[SCM] WebKit Debian packaging branch, webkit-1.2, updated. 1.2.5-1500-gb65db3c

Huzaifa Sidhpurwala huzaifas at redhat.com
Tue Jan 11 11:41:53 UTC 2011


The following commit has been merged in the webkit-1.2 branch:
commit f236c158708a2116a799174bd2722fd721e663c4
Author: Huzaifa Sidhpurwala <huzaifas at redhat.com>
Date:   Thu Dec 2 12:25:51 2010 +0530

    Backport crash fix by Huzaifa Sidhpurwala <huzaifas at redhat.com>
    
    Original authors: oliver at apple.com
                      mrowe at apple.com
                      darin at apple.com
    
            https://bugs.webkit.org/show_bug.cgi?id=41351
    
            Clamp the number of arguments supported by function.apply
    
            JavaScriptCore:
            Add clamping logic to function.apply similar to that enforced by firefox.
            We have a smaller clamp than firefox as our calling convention means that stack
            usage is proportional to argument count -- the firefox limit is larger
            than you could actually call.
    
            Make Arguments::MaxArguments clamping work for numbers >= 0x80000000 in
            the interpreter as well as the JIT.
    
            * interpreter/Interpreter.cpp:
            (JSC::Interpreter::privateExecute):
            * jit/JITStubs.cpp:
            (JSC::DEFINE_STUB_FUNCTION):
            * runtime/Arguments.h:
            (JSC::Arguments::):
            * interpreter/Interpreter.cpp:
            (JSC::Interpreter::privateExecute): Be slightly more consistent in using uint32_t to prevent
            warnings about comparisons between signed and unsigned types, and attempts to call an overload
            of std::min that doesn't exist.
            * interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute):
            Fix signed integer overflow problem in op_load_varargs handling. 0xFFFFFFFF was read as -1.
    
            LayoutTests:
            * fast/js/function-apply-many-args-expected.txt: Added.
            * fast/js/function-apply-many-args.html: Added.
            * fast/js/script-tests/function-apply-many-args.js: Added.
            * fast/js/function-apply-expected.txt: Updated to expect success.
            * fast/js/script-tests/function-apply.js: Added test cases.
    
            Backported from the following development branch commits:
            http://trac.webkit.org/changeset/62432
            http://trac.webkit.org/changeset/62433
            http://trac.webkit.org/changeset/62464
            http://trac.webkit.org/changeset/62456

diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp
index b6e9161..2fcdae3 100644
--- a/JavaScriptCore/interpreter/Interpreter.cpp
+++ b/JavaScriptCore/interpreter/Interpreter.cpp
@@ -3454,9 +3454,10 @@ skip_id_custom_self:
         int argsOffset = vPC[2].u.operand;
         
         JSValue arguments = callFrame->r(argsOffset).jsValue();
-        int32_t argCount = 0;
+        uint32_t argCount = 0;
         if (!arguments) {
-            argCount = (uint32_t)(callFrame->argumentCount()) - 1;
+            argCount = (uint32_t)(callFrame->argumentCount());
+            argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
             Register* newEnd = callFrame->registers() + sizeDelta;
             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -3464,9 +3465,9 @@ skip_id_custom_self:
                 goto vm_throw;
             }
             ASSERT(!callFrame->callee()->isHostFunction());
-            int32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
-            int32_t inplaceArgs = min(argCount, expectedParams);
-            int32_t i = 0;
+            uint32_t expectedParams = callFrame->callee()->jsExecutable()->parameterCount();
+            uint32_t inplaceArgs = min(argCount, expectedParams);
+            uint32_t i = 0;
             Register* argStore = callFrame->registers() + argsOffset;
 
             // First step is to copy the "expected" parameters from their normal location relative to the callframe
@@ -3483,6 +3484,7 @@ skip_id_custom_self:
             if (asObject(arguments)->classInfo() == &Arguments::info) {
                 Arguments* args = asArguments(arguments);
                 argCount = args->numProvidedArguments(callFrame);
+                argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
                 Register* newEnd = callFrame->registers() + sizeDelta;
                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -3493,6 +3495,7 @@ skip_id_custom_self:
             } else if (isJSArray(&callFrame->globalData(), arguments)) {
                 JSArray* array = asArray(arguments);
                 argCount = array->length();
+                argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
                 Register* newEnd = callFrame->registers() + sizeDelta;
                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -3503,6 +3506,7 @@ skip_id_custom_self:
             } else if (asObject(arguments)->inherits(&JSArray::info)) {
                 JSObject* argObject = asObject(arguments);
                 argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+                argCount = min<uint32_t>(argCount, Arguments::MaxArguments);
                 int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
                 Register* newEnd = callFrame->registers() + sizeDelta;
                 if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -3510,7 +3514,7 @@ skip_id_custom_self:
                     goto vm_throw;
                 }
                 Register* argsBuffer = callFrame->registers() + argsOffset;
-                for (int32_t i = 0; i < argCount; ++i) {
+                for (uint32_t i = 0; i < argCount; ++i) {
                     argsBuffer[i] = asObject(arguments)->get(callFrame, i);
                     CHECK_FOR_EXCEPTION();
                 }
diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp
index 03b16b4..d9cd7b0 100644
--- a/JavaScriptCore/jit/JITStubs.cpp
+++ b/JavaScriptCore/jit/JITStubs.cpp
@@ -2134,6 +2134,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
     if (!arguments) {
         int providedParams = callFrame->registers()[RegisterFile::ArgumentCount].i() - 1;
         argCount = providedParams;
+        argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments)); 
         int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
         Register* newEnd = callFrame->registers() + sizeDelta;
         if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -2169,6 +2170,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
         if (asObject(arguments)->classInfo() == &Arguments::info) {
             Arguments* argsObject = asArguments(arguments);
             argCount = argsObject->numProvidedArguments(callFrame);
+            argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments)); 
             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
             Register* newEnd = callFrame->registers() + sizeDelta;
             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -2179,6 +2181,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
         } else if (isJSArray(&callFrame->globalData(), arguments)) {
             JSArray* array = asArray(arguments);
             argCount = array->length();
+            argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments)); 
             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
             Register* newEnd = callFrame->registers() + sizeDelta;
             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
@@ -2189,6 +2192,7 @@ DEFINE_STUB_FUNCTION(int, op_load_varargs)
         } else if (asObject(arguments)->inherits(&JSArray::info)) {
             JSObject* argObject = asObject(arguments);
             argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
+            argCount = min(argCount, static_cast<uint32_t>(Arguments::MaxArguments)); 
             int32_t sizeDelta = argsOffset + argCount + RegisterFile::CallFrameHeaderSize;
             Register* newEnd = callFrame->registers() + sizeDelta;
             if (!registerFile->grow(newEnd) || ((newEnd - callFrame->registers()) != sizeDelta)) {
diff --git a/JavaScriptCore/runtime/Arguments.h b/JavaScriptCore/runtime/Arguments.h
index 9797e08..704b13e 100644
--- a/JavaScriptCore/runtime/Arguments.h
+++ b/JavaScriptCore/runtime/Arguments.h
@@ -55,6 +55,10 @@ namespace JSC {
 
     class Arguments : public JSObject {
     public:
+        // Use an enum because otherwise gcc insists on doing a memory 
+        // read
+        enum { MaxArguments = 0x10000 };
+
         enum NoParametersType { NoParameters };
 
         Arguments(CallFrame*);
diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp
index d3ef44c..ae9e038 100644
--- a/JavaScriptCore/runtime/JSArray.cpp
+++ b/JavaScriptCore/runtime/JSArray.cpp
@@ -948,10 +948,10 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
 
 void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
 {
-    ASSERT(m_storage->m_length == maxSize);
+    ASSERT(m_storage->m_length >= maxSize);
     UNUSED_PARAM(maxSize);
     JSValue* vector = m_storage->m_vector;
-    unsigned vectorEnd = min(m_storage->m_length, m_vectorLength);
+    unsigned vectorEnd = min(maxSize, m_vectorLength);
     unsigned i = 0;
     for (; i < vectorEnd; ++i) {
         JSValue& v = vector[i];
@@ -960,7 +960,7 @@ void JSArray::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSiz
         buffer[i] = v;
     }
 
-    for (; i < m_storage->m_length; ++i)
+    for (; i < maxSize; ++i)
         buffer[i] = get(exec, i);
 }
 
diff --git a/LayoutTests/fast/js/function-apply-expected.txt b/LayoutTests/fast/js/function-apply-expected.txt
index 63ef8db..018163f 100644
--- a/LayoutTests/fast/js/function-apply-expected.txt
+++ b/LayoutTests/fast/js/function-apply-expected.txt
@@ -30,6 +30,12 @@ PASS arrayApplyChangeLength1() is 2
 PASS arrayApplyChangeLength2() is 2
 PASS arrayApplyChangeLength3() is 2
 PASS arrayApplyChangeLength4() is 0
+PASS var a = []; a.length = 0xFFFE; [].constructor.apply('', a).length is 0xFFFE 
+PASS var a = []; a.length = 0xFFFF; [].constructor.apply('', a).length is 0xFFFF 
+PASS var a = []; a.length = 0x10000; [].constructor.apply('', a).length is 0x10000 
+PASS var a = []; a.length = 0x10001; [].constructor.apply('', a).length is 0x10000 
+PASS var a = []; a.length = 0xFFFFFFFE; [].constructor.apply('', a).length is 0x10000 
+PASS var a = []; a.length = 0xFFFFFFFF; [].constructor.apply('', a).length is 0x10000 
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/fast/js/function-apply-many-args-expected.txt b/LayoutTests/fast/js/function-apply-many-args-expected.txt
new file mode 100644
index 0000000..a616b2a
--- /dev/null
+++ b/LayoutTests/fast/js/function-apply-many-args-expected.txt
@@ -0,0 +1,45 @@
+Tests that we truncate arguments beyond a certain threshold.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS f.apply(null) is 0
+PASS f.apply(null, []) is 0
+PASS f.apply(null, [1]) is 1
+PASS f.apply(null, new Array(10)) is 10
+PASS f.apply(null, new Array(1000)) is 1000
+PASS f.apply(null, new Array(65536)) is 65536
+PASS f.apply(null, new Array(65537)) is 65536
+PASS f.apply(null, new Array(65537)) is 65536
+PASS f.apply(null, bigArray) is 65536
+PASS g.apply(null) is 0
+PASS g.apply(null, []) is 0
+PASS g.apply(null, [1]) is 1
+PASS g.apply(null, new Array(10)) is 10
+PASS g.apply(null, new Array(1000)) is 1000
+PASS g.apply(null, new Array(65536)) is 65536
+PASS g.apply(null, new Array(65537)) is 65536
+PASS g.apply(null, new Array(65537)) is 65536
+PASS g.apply(null, bigArray) is 65536
+PASS h.apply(null) is 0
+PASS h.apply(null, []) is 0
+PASS h.apply(null, [1]) is 1
+PASS h.apply(null, new Array(10)) is 10
+PASS h.apply(null, new Array(1000)) is 1000
+PASS h.apply(null, new Array(65536)) is 65536
+PASS h.apply(null, new Array(65537)) is 65536
+PASS h.apply(null, new Array(65537)) is 65536
+PASS h.apply(null, bigArray) is 65536
+PASS i.apply(null) is 0
+PASS i.apply(null, []) is 0
+PASS i.apply(null, [1]) is 1
+PASS i.apply(null, new Array(10)) is 10
+PASS i.apply(null, new Array(1000)) is 1000
+PASS i.apply(null, new Array(65536)) is 65536
+PASS i.apply(null, new Array(65537)) is 65536
+PASS i.apply(null, new Array(65537)) is 65536
+PASS i.apply(null, bigArray) is 65536
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/function-apply-many-args.html b/LayoutTests/fast/js/function-apply-many-args.html
new file mode 100644
index 0000000..bd15769
--- /dev/null
+++ b/LayoutTests/fast/js/function-apply-many-args.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/function-apply-many-args.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/script-tests/function-apply-aliased.js b/LayoutTests/fast/js/script-tests/function-apply-aliased.js
index 0e09632..f011133 100644
--- a/LayoutTests/fast/js/script-tests/function-apply-aliased.js
+++ b/LayoutTests/fast/js/script-tests/function-apply-aliased.js
@@ -44,10 +44,17 @@ shouldBe("myFunctionWithApply.apply(myObject, arg1Array)", '[myFunctionWithApply
 shouldBe("forwarder(myFunctionWithApply, myObject, arg1Array)", '[myFunctionWithApply, "myFunctionWithApply.apply", myObject]');
 shouldBe("myFunctionWithApply.aliasedApply(myObject, arg1Array)", '[myObject, "myFunctionWithApply", "arg1"]');
 
-// Blow the stack with a sparse array
-shouldThrow("myFunction.apply(null, new Array(5000000))");
-// Blow the stack with a sparse array that is sufficiently large to cause int overflow
-shouldThrow("myFunction.apply(null, new Array(1 << 30))");
+function stackOverflowTest() { 
+    try {
+        var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z; 
+        stackOverflowTest(); 
+    } catch(e) { 
+        // Blow the stack with a sparse array 
+        shouldThrow("myFunction.apply(null, new Array(5000000))");
+        // Blow the stack with a sparse array that is sufficiently large to cause int overflow 
+        shouldThrow("myFunction.apply(null, new Array(1 << 30))");
+    }
+}
 // Blow the stack recursing with arguments
 shouldThrow("recurseArguments.apply(null, new Array(50000))");
 
diff --git a/LayoutTests/fast/js/script-tests/function-apply-many-args.js b/LayoutTests/fast/js/script-tests/function-apply-many-args.js
new file mode 100644
index 0000000..6c67bf2
--- /dev/null
+++ b/LayoutTests/fast/js/script-tests/function-apply-many-args.js
@@ -0,0 +1,48 @@
+description("Tests that we truncate arguments beyond a certain threshold.");
+
+function f() { return arguments.length; }
+function g() { return f.apply(null, arguments); }
+function h() { arguments; return f.apply(null, arguments); }
+function i() { arguments[arguments.length] = 0; return f.apply(null, arguments); }
+var bigArray = [];
+for (var j = 0; j < 100000; j++)
+    bigArray.push(null);
+
+shouldBe("f.apply(null)", "0");
+shouldBe("f.apply(null, [])", "0");
+shouldBe("f.apply(null, [1])", "1");
+shouldBe("f.apply(null, new Array(10))", "10");
+shouldBe("f.apply(null, new Array(1000))", "1000");
+shouldBe("f.apply(null, new Array(65536))", "65536");
+shouldBe("f.apply(null, new Array(65537))", "65536");
+shouldBe("f.apply(null, new Array(65537))", "65536");
+shouldBe("f.apply(null, bigArray)", "65536");
+shouldBe("g.apply(null)", "0");
+shouldBe("g.apply(null, [])", "0");
+shouldBe("g.apply(null, [1])", "1");
+shouldBe("g.apply(null, new Array(10))", "10");
+shouldBe("g.apply(null, new Array(1000))", "1000");
+shouldBe("g.apply(null, new Array(65536))", "65536");
+shouldBe("g.apply(null, new Array(65537))", "65536");
+shouldBe("g.apply(null, new Array(65537))", "65536");
+shouldBe("g.apply(null, bigArray)", "65536");
+shouldBe("h.apply(null)", "0");
+shouldBe("h.apply(null, [])", "0");
+shouldBe("h.apply(null, [1])", "1");
+shouldBe("h.apply(null, new Array(10))", "10");
+shouldBe("h.apply(null, new Array(1000))", "1000");
+shouldBe("h.apply(null, new Array(65536))", "65536");
+shouldBe("h.apply(null, new Array(65537))", "65536");
+shouldBe("h.apply(null, new Array(65537))", "65536");
+shouldBe("h.apply(null, bigArray)", "65536");
+shouldBe("i.apply(null)", "0");
+shouldBe("i.apply(null, [])", "0");
+shouldBe("i.apply(null, [1])", "1");
+shouldBe("i.apply(null, new Array(10))", "10");
+shouldBe("i.apply(null, new Array(1000))", "1000");
+shouldBe("i.apply(null, new Array(65536))", "65536");
+shouldBe("i.apply(null, new Array(65537))", "65536");
+shouldBe("i.apply(null, new Array(65537))", "65536");
+shouldBe("i.apply(null, bigArray)", "65536");
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/js/script-tests/function-apply.js b/LayoutTests/fast/js/script-tests/function-apply.js
index e58d909..57aaea1 100644
--- a/LayoutTests/fast/js/script-tests/function-apply.js
+++ b/LayoutTests/fast/js/script-tests/function-apply.js
@@ -284,4 +284,11 @@ shouldBe("arrayApplyChangeLength2()", "2");
 shouldBe("arrayApplyChangeLength3()", "2");
 shouldBe("arrayApplyChangeLength4()", "0");
 
+shouldBe("var a = []; a.length = 0xFFFE; [].constructor.apply('', a).length", "0xFFFE"); 
+shouldBe("var a = []; a.length = 0xFFFF; [].constructor.apply('', a).length", "0xFFFF"); 
+shouldBe("var a = []; a.length = 0x10000; [].constructor.apply('', a).length", "0x10000"); 
+shouldBe("var a = []; a.length = 0x10001; [].constructor.apply('', a).length", "0x10000"); 
+shouldBe("var a = []; a.length = 0xFFFFFFFE; [].constructor.apply('', a).length", "0x10000"); 
+shouldBe("var a = []; a.length = 0xFFFFFFFF; [].constructor.apply('', a).length", "0x10000"); 
+
 var successfullyParsed = true;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list