Change native call frames to use the scope from their Callee instead of their caller...
authormsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Oct 2014 20:03:28 +0000 (20:03 +0000)
committermsaboff@apple.com <msaboff@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Oct 2014 20:03:28 +0000 (20:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=137907

Source/JavaScriptCore:

Reviewed by Mark Lam.

Changed setting of scope for native CallFrames to use the scope associated with the
Callee instead of the caller's scope.

* jit/ThunkGenerators.cpp:
(JSC::nativeForGenerator):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:

LayoutTests:

Updated tests to reflect that the results of changing where a native call frame
and therefore the lexicalGlobalObject came from.  Verified that these tests changes
are consistent with the HTML standard.  These changes are also closer to the behavior
of other browsers.

Reviewed by Mark Lam.

* fast/frames/sandboxed-iframe-navigation-parent-expected.txt:
* fast/frames/sandboxed-iframe-navigation-parent.html:
Changed the test and results to show that a sandboxed iframe can navigate its
ancesters when it is sandbox with both "allow-scripts" and "allow-same-origin".

* http/tests/security/calling-versus-current.html:
Updated the test to really have a different domain.  We do a simple string comparison
to check for that we are part of the same domain.  The test expected that 0.0.1 was
from the same domain as 127.0.0.1.  Changed the test to try 0.0.2 and expect a
security exception.

* http/tests/security/frameNavigation/context-for-location-assign-expected.txt:
Updated test results.

* traversal/node-iterator-prototype-expected.txt:
* traversal/node-iterator-prototype.html:
Fixed as a result of this change.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@174996 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/frames/sandboxed-iframe-navigation-parent-expected.txt
LayoutTests/fast/frames/sandboxed-iframe-navigation-parent.html
LayoutTests/http/tests/security/calling-versus-current.html
LayoutTests/http/tests/security/frameNavigation/context-for-location-assign-expected.txt
LayoutTests/traversal/node-iterator-prototype-expected.txt
LayoutTests/traversal/node-iterator-prototype.html
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jit/ThunkGenerators.cpp
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

index bd5a877..40a3ef1 100644 (file)
@@ -1,3 +1,33 @@
+2014-10-21  Michael Saboff  <msaboff@apple.com>
+
+        Change native call frames to use the scope from their Callee instead of their caller's scope
+        https://bugs.webkit.org/show_bug.cgi?id=137907
+
+        Updated tests to reflect that the results of changing where a native call frame
+        and therefore the lexicalGlobalObject came from.  Verified that these tests changes
+        are consistent with the HTML standard.  These changes are also closer to the behavior
+        of other browsers.
+
+        Reviewed by Mark Lam.
+
+        * fast/frames/sandboxed-iframe-navigation-parent-expected.txt:
+        * fast/frames/sandboxed-iframe-navigation-parent.html:
+        Changed the test and results to show that a sandboxed iframe can navigate its
+        ancesters when it is sandbox with both "allow-scripts" and "allow-same-origin".
+
+        * http/tests/security/calling-versus-current.html:
+        Updated the test to really have a different domain.  We do a simple string comparison
+        to check for that we are part of the same domain.  The test expected that 0.0.1 was
+        from the same domain as 127.0.0.1.  Changed the test to try 0.0.2 and expect a
+        security exception.
+
+        * http/tests/security/frameNavigation/context-for-location-assign-expected.txt:
+        Updated test results.
+
+        * traversal/node-iterator-prototype-expected.txt:
+        * traversal/node-iterator-prototype.html:
+        Fixed as a result of this change.
+
 2014-10-21  Joanmarie Diggs  <jdiggs@igalia.com>
 
         AX: [ATK] CSS-generated text content not exposed to assistive technologies
index e4031df..f754c8a 100644 (file)
@@ -1,8 +1,4 @@
-CONSOLE MESSAGE: Unsafe JavaScript attempt to initiate navigation for frame with URL 'sandboxed-iframe-navigation-source.html'. The frame attempting navigation is sandboxed, and is therefore disallowed from navigating its ancestors.
-
-This test verifies that a sandboxed IFrame cannot navigate an ancestor in the frame tree by assigning the location attribute.
-
-This is done by loading ten non-sandboxed IFrames, and a single sandboxed one. Expect ten frames to be navigated, but the sandboxed one to not be one of them.
+This test verifies that a sandboxed IFrame with the keywords allow-scripts and allow-same-origin is allowed to navigate an ancestor in the frame tree by assigning the location attribute.
 
 This test will print "PASS" on success.
 
index 3b7e1a6..2169b90 100644 (file)
@@ -13,9 +13,9 @@ function checkResults()
 {
     var testStatus = document.getElementById('testStatus');
 
-    if (self.navigated.location.href.indexOf('parent.html') == -1)
-        testStatus.innerHTML = 'FAIL: disallowed frame navigated';
-    else if (navigatedFrames == 10)
+    if (self.navigated.location.href.indexOf('parent.html') != -1)
+        testStatus.innerHTML = 'FAIL: sandboxed frame couldn\'t navigate';
+    else if (navigatedFrames == 11)
         testStatus.innerHTML = 'PASS';
     else
         testStatus.innerHTML = 'FAIL: frames not navigated properly';
@@ -28,7 +28,7 @@ function countFrame()
 {
     ++navigatedFrames;
 
-    if (navigatedFrames == 10)
+    if (navigatedFrames == 11)
         checkResults();
 }
 
@@ -37,13 +37,10 @@ function countFrame()
 
 <body>
 
-    <p>This test verifies that a sandboxed IFrame cannot navigate an ancestor
+    <p>This test verifies that a sandboxed IFrame with the keywords
+    allow-scripts and allow-same-origin is allowed to navigate an ancestor
     in the frame tree by assigning the location attribute.</p>
 
-    <p>This is done by loading ten non-sandboxed IFrames, and a single
-    sandboxed one. Expect ten frames to be navigated, but the sandboxed
-    one to <b>not</b> be one of them.</p>
-    
     <p>This test will print &quot;PASS&quot; on success.</p>
 
     <iframe src="resources/non-sandboxed-iframe-navigation.html"></iframe>
index 028a413..188f136 100644 (file)
@@ -6,8 +6,15 @@ if (window.testRunner)
 
 window.onload = function() {
     window.f = frames[0].atob;
-    document.domain = "0.0.1";
-    if (btoa(window.f("PASS")) == "PASS")
-        document.getElementById("console").innerHTML = "PASS"
+    try {
+        document.domain = "0.0.2";
+    } catch (e) {
+        if ("message" in e || (e.message.search("SecurityError:") != -1)) {
+            document.getElementById("console").innerHTML = "PASS"
+            return
+        }
+    }
+    if (btoa(window.f("TEST")) == "TEST")
+        document.getElementById("console").innerHTML = "FAIL"
 }
 </script>
index 588bc87..a0ea3a7 100644 (file)
@@ -1,11 +1,9 @@
 This test checks whether DOM wrappers created by NodeIterator have their prototypes attached to the correct objects. These nodes are from the child frame, so that's where their prototypes should be attached.
 
-Unfortunately, our implementation is buggy and we get wrappers from the parent frame here. This test documents the bug so we'll know when we fix it.
-
 test: child PASS
-A: parent FAIL
-B: parent FAIL
-C: parent FAIL
-D: parent FAIL
-D: parent FAIL
+A: child PASS
+B: child PASS
+C: child PASS
+D: child PASS
+D: child PASS
 
index feaf7a2..adf1e59 100644 (file)
@@ -4,9 +4,6 @@
 prototypes attached to the correct objects.  These nodes are from the child
 frame, so that's where their prototypes should be attached.</p>
 
-<p>Unfortunately, our implementation is buggy and we get wrappers from the
-parent frame here.  This test documents the bug so we'll know when we fix
-it.</p>
 <div id="console"></div>
 <script>
 if (window.testRunner)
index fb533b3..22cefcd 100644 (file)
@@ -1,3 +1,18 @@
+2014-10-21  Michael Saboff  <msaboff@apple.com>
+
+        Change native call frames to use the scope from their Callee instead of their caller's scope
+        https://bugs.webkit.org/show_bug.cgi?id=137907
+
+        Reviewed by Mark Lam.
+
+        Changed setting of scope for native CallFrames to use the scope associated with the
+        Callee instead of the caller's scope.
+
+        * jit/ThunkGenerators.cpp:
+        (JSC::nativeForGenerator):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+
 2014-10-21  Tibor Meszaros  <tmeszaros.u-szeged@partner.samsung.com>
 
         Add missing ENABLE(FTL_NATIVE_CALL_INLINING) guard to BundlePath.cpp after r174940
index 56245b5..b48c9c9 100644 (file)
@@ -276,10 +276,10 @@ static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind k
     jit.storePtr(JSInterfaceJIT::callFrameRegister, &vm->topCallFrame);
 
 #if CPU(X86)
-    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // Load callee's scope chain into this callframe so that whatever we call can
     // get to its global data.
-    jit.emitGetCallerFrameFromCallFrameHeaderPtr(JSInterfaceJIT::regT0);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, JSInterfaceJIT::regT1, JSInterfaceJIT::regT0);
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::Callee, JSInterfaceJIT::regT1);
+    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT1, JSCallee::offsetOfScopeChain()), JSInterfaceJIT::regT1);
     jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
 
     // Calling convention:      f(ecx, edx, ...);
@@ -296,10 +296,10 @@ static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind k
     jit.addPtr(JSInterfaceJIT::TrustedImm32(8), JSInterfaceJIT::stackPointerRegister);
 
 #elif CPU(X86_64)
-    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // Load callee's scope chain into this callframe so that whatever we call can
     // get to its global data.
-    jit.emitGetCallerFrameFromCallFrameHeaderPtr(JSInterfaceJIT::regT0);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, JSInterfaceJIT::regT1, JSInterfaceJIT::regT0);
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::Callee, JSInterfaceJIT::regT1);
+    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT1, JSCallee::offsetOfScopeChain()), JSInterfaceJIT::regT1);
     jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
 #if !OS(WINDOWS)
     // Calling convention:      f(edi, esi, edx, ecx, ...);
@@ -333,10 +333,10 @@ static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind k
     COMPILE_ASSERT(ARM64Registers::x1 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_1);
     COMPILE_ASSERT(ARM64Registers::x2 != JSInterfaceJIT::regT3, T3_not_trampled_by_arg_2);
 
-    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // Load callee's scope chain into this callframe so that whatever we call can
     // get to its global data.
-    jit.emitGetCallerFrameFromCallFrameHeaderPtr(ARM64Registers::x3);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, JSInterfaceJIT::regT1, ARM64Registers::x3);
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::Callee, JSInterfaceJIT::regT1);
+    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT1, JSCallee::offsetOfScopeChain()), JSInterfaceJIT::regT1);
     jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
 
     // Host function signature: f(ExecState*);
@@ -346,9 +346,10 @@ static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind k
     jit.loadPtr(JSInterfaceJIT::Address(ARM64Registers::x1, JSFunction::offsetOfExecutable()), ARM64Registers::x2);
     jit.call(JSInterfaceJIT::Address(ARM64Registers::x2, executableOffsetToFunction));
 #elif CPU(ARM) || CPU(SH4) || CPU(MIPS)
-    // Load caller frame's scope chain into this callframe so that whatever we call can get to its global data.
-    jit.emitGetCallerFrameFromCallFrameHeaderPtr(JSInterfaceJIT::regT2);
-    jit.emitGetFromCallFrameHeaderPtr(JSStack::ScopeChain, JSInterfaceJIT::regT1, JSInterfaceJIT::regT2);
+    // Load callee's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    jit.emitGetFromCallFrameHeaderPtr(JSStack::Callee, JSInterfaceJIT::regT1);
+    jit.loadPtr(JSInterfaceJIT::Address(JSInterfaceJIT::regT1, JSCallee::offsetOfScopeChain()), JSInterfaceJIT::regT1);
     jit.emitPutCellToCallFrameHeader(JSInterfaceJIT::regT1, JSStack::ScopeChain);
 
 #if CPU(MIPS)
index cffc87c..c66f037 100644 (file)
@@ -2084,11 +2084,11 @@ macro nativeCallTrampoline(executableOffsetToFunction)
 
     functionPrologue()
     storep 0, CodeBlock[cfr]
-    loadp CallerFrame[cfr], t0
-    loadi ScopeChain + PayloadOffset[t0], t1
+    loadi Callee + PayloadOffset[cfr], t1
+    loadi JSCallee::m_scope[t1], t0
     storei CellTag, ScopeChain + TagOffset[cfr]
-    storei t1, ScopeChain + PayloadOffset[cfr]
-    loadi Callee + PayloadOffset[t0], t1
+    storei t0, ScopeChain + PayloadOffset[cfr]
+    // Callee is still in t1 for code below
     if X86 or X86_WIN
         subp 8, sp # align stack pointer
         andp MarkedBlockMask, t1
index 6f8dcbe..5b8ba67 100644 (file)
@@ -1918,11 +1918,11 @@ macro nativeCallTrampoline(executableOffsetToFunction)
             const temp = t0
         end
         loadp Callee[cfr], t0
-        andp MarkedBlockMask, t0
-        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
-        storep cfr, VM::topCallFrame[t0]
-        loadp CallerFrame[cfr], t0
-        loadq ScopeChain[t0], t1
+        andp MarkedBlockMask, t0, t1
+        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
+        storep cfr, VM::topCallFrame[t1]
+        // Callee still in t0
+        loadp JSCallee::m_scope[t0], t1
         storeq t1, ScopeChain[cfr]
         move cfr, arg1
         loadp Callee[cfr], arg2
@@ -1940,11 +1940,11 @@ macro nativeCallTrampoline(executableOffsetToFunction)
         loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t3], t3
     elsif ARM64 or C_LOOP
         loadp Callee[cfr], t0
-        andp MarkedBlockMask, t0
-        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t0], t0
-        storep cfr, VM::topCallFrame[t0]
-        loadp CallerFrame[cfr], t2
-        loadp ScopeChain[t2], t1
+        andp MarkedBlockMask, t0, t1
+        loadp MarkedBlock::m_weakSet + WeakSet::m_vm[t1], t1
+        storep cfr, VM::topCallFrame[t1]
+        // Callee still in t0
+        loadp JSCallee::m_scope[t0], t1
         storep t1, ScopeChain[cfr]
         preserveReturnAddressAfterCall(t3)
         storep t3, ReturnPC[cfr]