JavaScriptCore:
authorantti <antti@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Sep 2007 13:54:12 +0000 (13:54 +0000)
committerantti <antti@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Sep 2007 13:54:12 +0000 (13:54 +0000)
        Reviewed by Geoff, Maciej.

        Fix <rdar://problem/5445058>
        REGRESSION: Unable to upload picture to eBay auction due to domain security check

        eBay uses window.eval() between windows. In Firefox window.eval() switches execution
        and security context to the target window, something WebKit did not do. With WebKit
        security tightening in r24781, this broke picture uploads.

        Fix by making WebKit switch context in window.eval().

        * kjs/Context.cpp:
        (KJS::Context::Context):
        (KJS::Context::~Context):
        * kjs/context.h:
        Save and restore interpreter context independently from calling context.

        * kjs/function.cpp:
        (KJS::GlobalFuncImp::callAsFunction):
        If eval is called for global object different than current one, switch execution context
        to that object and push it to scope.

LayoutTests:

        Reviewed by Geoff, Maciej.

        Test for <rdar://problem/5445058>
        REGRESSION: Unable to upload picture to eBay auction due to domain security check

        * fast/js/window-eval-context-expected.txt: Added.
        * fast/js/window-eval-context.html: Added.

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

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/Context.cpp
JavaScriptCore/kjs/context.h
JavaScriptCore/kjs/function.cpp
LayoutTests/ChangeLog
LayoutTests/fast/js/window-eval-context-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/window-eval-context.html [new file with mode: 0644]

index 8a7793ab5c7a344f38777e3b4e003d0dc420f609..5b8e0c5e5a3505b59e3a81778d91cb849701ea6e 100644 (file)
@@ -1,3 +1,27 @@
+2007-09-12  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Geoff, Maciej.
+        
+        Fix <rdar://problem/5445058>
+        REGRESSION: Unable to upload picture to eBay auction due to domain security check
+        
+        eBay uses window.eval() between windows. In Firefox window.eval() switches execution
+        and security context to the target window, something WebKit did not do. With WebKit
+        security tightening in r24781, this broke picture uploads.
+        
+        Fix by making WebKit switch context in window.eval().
+        
+        * kjs/Context.cpp:
+        (KJS::Context::Context):
+        (KJS::Context::~Context):
+        * kjs/context.h:
+        Save and restore interpreter context independently from calling context.
+        
+        * kjs/function.cpp:
+        (KJS::GlobalFuncImp::callAsFunction):
+        If eval is called for global object different than current one, switch execution context
+        to that object and push it to scope.
+
 2007-09-12  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Geoffrey Garen.
index caf1ff824e6853f775d7cfb624e54a5f3e5efce0..014c9911ff8c257e6f8ba8626de2afe469268724 100644 (file)
@@ -31,6 +31,7 @@ Context::Context(JSObject* glob, Interpreter* interpreter, JSObject* thisV,
                  FunctionBodyNode* currentBody, CodeType type, Context* callingCon, 
                  FunctionImp* func, const List* args)
     : m_interpreter(interpreter)
+    , m_savedContext(interpreter->context())
     , m_currentBody(currentBody)
     , m_function(func)
     , m_arguments(args)
@@ -83,7 +84,7 @@ Context::Context(JSObject* glob, Interpreter* interpreter, JSObject* thisV,
 
 Context::~Context()
 {
-    m_interpreter->setContext(m_callingContext);
+    m_interpreter->setContext(m_savedContext);
 
     // The arguments list is only needed to potentially create the  arguments object, 
     // which isn't accessible from nested scopes so we can discard the list as soon 
index 75ec3c22b44c56a2126f49095d024096c17c7e7c..37883e6dcacd3dc411529d2ec88909d726b04dd5 100644 (file)
@@ -129,6 +129,7 @@ namespace KJS  {
 
     Interpreter* m_interpreter;
     Context* m_callingContext;
+    Context* m_savedContext;
     FunctionBodyNode* m_currentBody;
     ExecState* m_execState;
 
index 74d7c2d1be089fbdd5c5d486d89099628c904434..cf3179b3a55225a9a432e1721ca8f3b62cfb93e2 100644 (file)
@@ -770,7 +770,7 @@ static double parseFloat(const UString& s)
     return s.toDouble( true /*tolerant*/, false /* NaN for empty string */ );
 }
 
-JSValue* GlobalFuncImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, const List& args)
+JSValue* GlobalFuncImp::callAsFunction(ExecState* exec, JSObject* thisObj, const List& args)
 {
   JSValue* res = jsUndefined();
 
@@ -817,22 +817,31 @@ JSValue* GlobalFuncImp::callAsFunction(ExecState* exec, JSObject* /*thisObj*/, c
         if (!progNode)
           return throwError(exec, SyntaxError, errMsg, errLine, sid, NULL);
 
+        bool switchGlobal = exec->dynamicInterpreter()->isGlobalObject(thisObj) && thisObj != exec->dynamicInterpreter()->globalObject();
+          
         // enter a new execution context
+        Interpreter* interpreter = switchGlobal ? exec->dynamicInterpreter()->interpreterForGlobalObject(thisObj) : exec->dynamicInterpreter();
         JSObject* thisVal = static_cast<JSObject*>(exec->context()->thisValue());
-        Context ctx(exec->dynamicInterpreter()->globalObject(),
-                       exec->dynamicInterpreter(),
+        Context ctx(interpreter->globalObject(),
+                       interpreter,
                        thisVal,
                        progNode.get(),
                        EvalCode,
                        exec->context());
-        ExecState newExec(exec->dynamicInterpreter(), &ctx);
+        ExecState newExec(interpreter, &ctx);
         if (exec->hadException())
             newExec.setException(exec->exception());
         ctx.setExecState(&newExec);
+          
+        if (switchGlobal)
+            ctx.pushScope(thisObj);
         
         // execute the code
         progNode->processVarDecls(&newExec);
         Completion c = progNode->execute(&newExec);
+          
+        if (switchGlobal)
+            ctx.popScope();
 
         // if an exception occured, propogate it back to the previous execution object
         if (newExec.hadException())
index 381c48f13e7e5ff86705d01ad4c9ec76aea99470..05a4e18019758bb22fcb46180089b6be58bb80e2 100644 (file)
@@ -1,3 +1,13 @@
+2007-09-12  Antti Koivisto  <antti@apple.com>
+
+        Reviewed by Geoff, Maciej.
+        
+        Test for <rdar://problem/5445058>
+        REGRESSION: Unable to upload picture to eBay auction due to domain security check
+
+        * fast/js/window-eval-context-expected.txt: Added.
+        * fast/js/window-eval-context.html: Added.
+
 2007-09-12  John Seif <johneseif@gmail.com>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/js/window-eval-context-expected.txt b/LayoutTests/fast/js/window-eval-context-expected.txt
new file mode 100644 (file)
index 0000000..f91700a
--- /dev/null
@@ -0,0 +1,5 @@
+
+Test that otherWindow.eval() keeps variables of calling context visible: PASS
+Test that otherWindow.eval() is executed with otherWindow in scope PASS
+Test that otherWindow.eval() has otherWindow as the window object : PASS
+Test that otherWindow.eval() does not change 'this': PASS
diff --git a/LayoutTests/fast/js/window-eval-context.html b/LayoutTests/fast/js/window-eval-context.html
new file mode 100644 (file)
index 0000000..57b70f5
--- /dev/null
@@ -0,0 +1,37 @@
+<body>
+<script>
+function print(message, color) 
+{
+    var paragraph = document.createElement("div");
+    paragraph.appendChild(document.createTextNode(message));
+    paragraph.style.fontFamily = "monospace";
+    if (color)
+        paragraph.style.color = color;
+    document.getElementById("console").appendChild(paragraph);
+}
+
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+</script>
+<iframe id=i src='about:blank' width=10 height=10>
+</iframe><br>
+<div id=console></div>
+<script>
+var otherWindow = document.getElementById('i').contentWindow;
+var res;
+var localVar = 1;
+
+res = otherWindow.eval('localVar == 1');
+print("Test that otherWindow.eval() keeps variables of calling context visible: " + (res ? "PASS" : "FAIL")) ;
+
+otherWindow.localVar = 2;
+res = otherWindow.eval('localVar == 2');
+print("Test that otherWindow.eval() is executed with otherWindow in scope " + (res ? "PASS" : "FAIL")) ;
+
+res = otherWindow.eval('window == otherWindow');
+print("Test that otherWindow.eval() has otherWindow as the window object : " + (res ? "PASS" : "FAIL")) ;
+
+var savedThis = this;
+res = otherWindow.eval('this == savedThis');
+print("Test that otherWindow.eval() does not change 'this': " + (res ? "PASS" : "FAIL")) ;
+</script>