Title: [177460] trunk
Revision
177460
Author
msab...@apple.com
Date
2014-12-17 13:38:43 -0800 (Wed, 17 Dec 2014)

Log Message

Tests with infinite recursion frequently crash
https://bugs.webkit.org/show_bug.cgi?id=139548

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

While unwinding, if the call frame doesn't have a codeblock, then we
are in native code, handle appropriately.

* interpreter/Interpreter.cpp:
(JSC::unwindCallFrame):
(JSC::UnwindFunctor::operator()):
Added checks for null CodeBlock.

(JSC::Interpreter::unwind): Removed wrong ASSERT.

LayoutTests:

New test that exercises the various places that we do stack overflow checks.

* TestExpectations:
* js/regress-139548-expected.txt: Added.
* js/regress-139548.html: Added.
* js/script-tests/regress-139548.js: Added.
(ToStringObj):
(ToStringObj.prototype.toString):
(makeArgsArray):
(recurseNoDFG):
(recurse):
(probeAndRecurse):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (177459 => 177460)


--- trunk/LayoutTests/ChangeLog	2014-12-17 21:19:21 UTC (rev 177459)
+++ trunk/LayoutTests/ChangeLog	2014-12-17 21:38:43 UTC (rev 177460)
@@ -1,3 +1,23 @@
+2014-12-17  Michael Saboff  <msab...@apple.com>
+
+        Tests with infinite recursion frequently crash
+        https://bugs.webkit.org/show_bug.cgi?id=139548
+
+        Reviewed by Geoffrey Garen.
+
+        New test that exercises the various places that we do stack overflow checks.
+
+        * TestExpectations:
+        * js/regress-139548-expected.txt: Added.
+        * js/regress-139548.html: Added.
+        * js/script-tests/regress-139548.js: Added.
+        (ToStringObj):
+        (ToStringObj.prototype.toString):
+        (makeArgsArray):
+        (recurseNoDFG):
+        (recurse):
+        (probeAndRecurse):
+
 2014-12-16  Shivakumar JM  <shiva...@samsung.com>
 
         text node should not be created, On setting document.title to the empty string.

Modified: trunk/LayoutTests/TestExpectations (177459 => 177460)


--- trunk/LayoutTests/TestExpectations	2014-12-17 21:19:21 UTC (rev 177459)
+++ trunk/LayoutTests/TestExpectations	2014-12-17 21:38:43 UTC (rev 177460)
@@ -324,10 +324,6 @@
 [ Debug ] fast/history/history-back-while-pdf-in-pagecache.html [ Skip ]
 webkit.org/b/121628 [ Release ] fast/history/history-back-while-pdf-in-pagecache.html [ Pass ImageOnlyFailure ]
 
-# Catching infinite recursion is broken.
-webkit.org/b/139548 fast/workers/worker-constructor.html [ Skip ]
-webkit.org/b/139548 fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html [ Skip ]
-
 # Network process disk cache is not enabled yet
 webkit.org/b/30322 http/tests/cache/disk-cache-validation.html [ Skip ]
 

Added: trunk/LayoutTests/js/regress-139548-expected.txt (0 => 177460)


--- trunk/LayoutTests/js/regress-139548-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/regress-139548-expected.txt	2014-12-17 21:38:43 UTC (rev 177460)
@@ -0,0 +1,9 @@
+Regression test for https://webkit.org/b/139548. This test should not crash.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/regress-139548.html (0 => 177460)


--- trunk/LayoutTests/js/regress-139548.html	                        (rev 0)
+++ trunk/LayoutTests/js/regress-139548.html	2014-12-17 21:38:43 UTC (rev 177460)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/js/script-tests/regress-139548.js (0 => 177460)


--- trunk/LayoutTests/js/script-tests/regress-139548.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/regress-139548.js	2014-12-17 21:38:43 UTC (rev 177460)
@@ -0,0 +1,108 @@
+description("Regression test for https://webkit.org/b/139548. This test should not crash.");
+
+var maxArgCount = 8;
+var argIncrement = 1;
+
+function ToStringObj()
+{
+    s: ""
+}
+
+// Want a function that a native C++ function can call.
+ToStringObj.prototype.toString = function() { this.s = new String(""); return this.s; };
+
+var myObj = new ToStringObj();
+
+function makeArgsArray(firstArg, argCount)
+{
+    var args = [firstArg];
+    for (var argIndex = 1; argIndex < argCount; argIndex++)
+        args.push(argIndex);
+
+    return args;
+}
+
+function recurseNoDFG(depth)
+{
+    var s = "";
+    if (depth <= 0)
+        return 0;
+
+    for (var i = 1; i < maxArgCount; i += argIncrement) {
+        try {
+            s = myObj.toLocaleString();
+            return recurseNoDFG.apply(this, makeArgsArray(depth - 1, i));
+        } catch (e) {
+            if (e instanceof String)
+                throw e;
+
+            for (var j = 1; j < maxArgCount; j += argIncrement) {
+                try {
+                    s = myObj.toLocaleString();
+                    recurseNoDFG.apply(this, makeArgsArray(depth - 1, j)) + 1;
+                } catch (e1) {
+                }
+            }
+
+            throw "Got an exception";
+        }
+    }
+    return s.length;
+}
+
+function recurse(depth)
+{
+    var s = "";
+
+    if (depth <= 0)
+        return 0;
+
+    for (var i = 1; i < maxArgCount; i += argIncrement) {
+        s = myObj.toLocaleString();
+        return recurse.apply(this, makeArgsArray(depth - 1, i));
+    }
+
+    return s.length;
+}
+
+function probeAndRecurse(depth)
+{
+    var result;
+
+    // Probe stack depth
+    try {
+        result = probeAndRecurse(depth);
+        if (result == 0)
+            depth = 50;
+        else if (result < 0)
+            return result + 1;
+        else
+            return result;
+    } catch (e) {
+        // Go up a several frames and then call recursive functions that consume
+        // variable stack amounts in an effort to exercise various stack checks.
+        return -6;
+    }
+
+    for (var i = 1; i < maxArgCount; i += argIncrement) {
+        try {
+            recurseNoDFG.apply(this, makeArgsArray(depth, i));
+        } catch (e) {
+        }
+    }
+
+    for (var i = 1; i < maxArgCount; i += argIncrement) {
+        try {
+            recurse.apply(this, makeArgsArray(depth, i));
+        } catch (e) {
+        }
+    }
+
+    return 1;
+}
+
+// Warm up recurse functions
+for (var loopCount = 0; loopCount < 5000; loopCount++)
+    recurse(10);
+
+probeAndRecurse(0);

Modified: trunk/Source/_javascript_Core/ChangeLog (177459 => 177460)


--- trunk/Source/_javascript_Core/ChangeLog	2014-12-17 21:19:21 UTC (rev 177459)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-12-17 21:38:43 UTC (rev 177460)
@@ -1,3 +1,20 @@
+2014-12-17  Michael Saboff  <msab...@apple.com>
+
+        Tests with infinite recursion frequently crash
+        https://bugs.webkit.org/show_bug.cgi?id=139548
+
+        Reviewed by Geoffrey Garen.
+
+        While unwinding, if the call frame doesn't have a codeblock, then we
+        are in native code, handle appropriately.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::unwindCallFrame):
+        (JSC::UnwindFunctor::operator()):
+        Added checks for null CodeBlock.
+
+        (JSC::Interpreter::unwind): Removed wrong ASSERT.
+
 2014-12-17  Chris Dumez  <cdu...@apple.com>
 
         [iOS] Make it possible to toggle FeatureCounter support at runtime

Modified: trunk/Source/_javascript_Core/interpreter/Interpreter.cpp (177459 => 177460)


--- trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-12-17 21:19:21 UTC (rev 177459)
+++ trunk/Source/_javascript_Core/interpreter/Interpreter.cpp	2014-12-17 21:38:43 UTC (rev 177460)
@@ -436,7 +436,6 @@
 static bool unwindCallFrame(StackVisitor& visitor)
 {
     CallFrame* callFrame = visitor->callFrame();
-    CodeBlock* codeBlock = visitor->codeBlock();
     if (Debugger* debugger = callFrame->vmEntryGlobalObject()->debugger()) {
         ClearExceptionScope scope(&callFrame->vm());
         if (jsDynamicCast<JSFunction*>(callFrame->callee()))
@@ -446,20 +445,22 @@
         ASSERT(!callFrame->hadException());
     }
 
-    if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
+    if (CodeBlock* codeBlock = visitor->codeBlock()) {
+        if (codeBlock->codeType() == FunctionCode && codeBlock->needsActivation()) {
 #if ENABLE(DFG_JIT)
-        RELEASE_ASSERT(!visitor->isInlinedFrame());
+            RELEASE_ASSERT(!visitor->isInlinedFrame());
 #endif
-    }
+        }
 
-    if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
-        if (Arguments* arguments = visitor->existingArguments()) {
+        if (codeBlock->codeType() == FunctionCode && codeBlock->usesArguments()) {
+            if (Arguments* arguments = visitor->existingArguments()) {
 #if ENABLE(DFG_JIT)
-            if (visitor->isInlinedFrame())
-                arguments->tearOff(callFrame, visitor->inlineCallFrame());
-            else
+                if (visitor->isInlinedFrame())
+                    arguments->tearOff(callFrame, visitor->inlineCallFrame());
+                else
 #endif
-                arguments->tearOff(callFrame);
+                    arguments->tearOff(callFrame);
+            }
         }
     }
 
@@ -646,7 +647,7 @@
         m_codeBlock = visitor->codeBlock();
         unsigned bytecodeOffset = visitor->bytecodeOffset();
 
-        if (m_isTermination || !(m_handler = m_codeBlock->handlerForBytecodeOffset(bytecodeOffset))) {
+        if (m_isTermination || !(m_handler = m_codeBlock ? m_codeBlock->handlerForBytecodeOffset(bytecodeOffset) : nullptr)) {
             if (!unwindCallFrame(visitor)) {
                 if (LegacyProfiler* profiler = vm.enabledProfiler())
                     profiler->exceptionUnwind(m_callFrame);
@@ -669,7 +670,6 @@
 NEVER_INLINE HandlerInfo* Interpreter::unwind(VMEntryFrame*& vmEntryFrame, CallFrame*& callFrame, JSValue& exceptionValue)
 {
     CodeBlock* codeBlock = callFrame->codeBlock();
-    ASSERT(codeBlock);
     bool isTermination = false;
 
     ASSERT(!exceptionValue.isEmpty());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to