Title: [205359] trunk
Revision
205359
Author
[email protected]
Date
2016-09-02 12:10:12 -0700 (Fri, 02 Sep 2016)

Log Message

Object.preventExtensions() should throw cross-origin
https://bugs.webkit.org/show_bug.cgi?id=161486

Reviewed by Geoffrey Garen.

Source/_javascript_Core:

Update JSProxy to forward preventExtensions() calls to its target.

* runtime/JSProxy.cpp:
(JSC::JSProxy::preventExtensions):
* runtime/JSProxy.h:

Source/WebCore:

Object.preventExtensions() should throw cross-origin:
- https://html.spec.whatwg.org/#windowproxy-preventextensions
- https://html.spec.whatwg.org/#location-preventextensions
- http://www.ecma-international.org/ecma-262/6.0/#sec-object.preventextensions

Firefox and Chrome both throw in the cross-origin case. Firefox also throws
a TypeError in the same-origin case for Window, as per the specification.
However, Firefox does not seem to throw yet in the same-origin case for
Location yet.

Test: http/tests/security/preventExtensions-window-location.html

* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::preventExtensions):
* bindings/js/JSLocationCustom.cpp:
(WebCore::JSLocation::preventExtensions):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
* bindings/scripts/IDLAttributes.txt:
* page/DOMWindow.idl:
* page/Location.idl:

LayoutTests:

Add layout test coverage. We have a few failures in the same origin case
because we don't fully match the specification yet:
- Object.preventExtensions() should throw a TypeError. However, our
  implementation currently does not throw if [[PreventExtensions]] returns
  false.
- We do not ignore calls to Object.preventExtensions() for the Location
  object yet because other browsers do not seem to either.

* http/tests/security/preventExtensions-window-location-expected.txt: Added.
* http/tests/security/preventExtensions-window-location.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (205358 => 205359)


--- trunk/LayoutTests/ChangeLog	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/LayoutTests/ChangeLog	2016-09-02 19:10:12 UTC (rev 205359)
@@ -1,5 +1,23 @@
 2016-09-02  Chris Dumez  <[email protected]>
 
+        Object.preventExtensions() should throw cross-origin
+        https://bugs.webkit.org/show_bug.cgi?id=161486
+
+        Reviewed by Geoffrey Garen.
+
+        Add layout test coverage. We have a few failures in the same origin case
+        because we don't fully match the specification yet:
+        - Object.preventExtensions() should throw a TypeError. However, our
+          implementation currently does not throw if [[PreventExtensions]] returns
+          false.
+        - We do not ignore calls to Object.preventExtensions() for the Location
+          object yet because other browsers do not seem to either.
+
+        * http/tests/security/preventExtensions-window-location-expected.txt: Added.
+        * http/tests/security/preventExtensions-window-location.html: Added.
+
+2016-09-02  Chris Dumez  <[email protected]>
+
         Object.defineProperty() should throw cross-origin
         https://bugs.webkit.org/show_bug.cgi?id=161460
 

Added: trunk/LayoutTests/http/tests/security/preventExtensions-window-location-expected.txt (0 => 205359)


--- trunk/LayoutTests/http/tests/security/preventExtensions-window-location-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/preventExtensions-window-location-expected.txt	2016-09-02 19:10:12 UTC (rev 205359)
@@ -0,0 +1,24 @@
+Test the behavior of Object.preventExtensions() for Window / Location.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+* Cross origin
+PASS Object.isExtensible(frames[0]) is true
+PASS Object.preventExtensions(frames[0]) threw exception SecurityError (DOM Exception 18): Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match..
+PASS Object.isExtensible(frames[0]) is true
+PASS Object.isExtensible(frames[0].location) is true
+PASS Object.preventExtensions(frames[0].location) threw exception SecurityError (DOM Exception 18): Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match..
+PASS Object.isExtensible(frames[0].location) is true
+
+* Same origin
+PASS Object.isExtensible(window) is true
+FAIL Object.preventExtensions(window) should throw a TypeError. Did not throw.
+PASS Object.isExtensible(window) is true
+PASS Object.isExtensible(window.location) is true
+FAIL Object.preventExtensions(window.location) should throw a TypeError. Did not throw.
+FAIL Object.isExtensible(window.location) should be true. Was false.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/http/tests/security/preventExtensions-window-location.html (0 => 205359)


--- trunk/LayoutTests/http/tests/security/preventExtensions-window-location.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/security/preventExtensions-window-location.html	2016-09-02 19:10:12 UTC (rev 205359)
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<iframe src=""
+<script>
+description("Test the behavior of Object.preventExtensions() for Window / Location.");
+jsTestIsAsync = true;
+
+_onload_ = function() {
+    debug ("* Cross origin");
+    shouldBeTrue("Object.isExtensible(frames[0])");
+    shouldThrowErrorName("Object.preventExtensions(frames[0])", "SecurityError");
+    shouldBeTrue("Object.isExtensible(frames[0])");
+
+    shouldBeTrue("Object.isExtensible(frames[0].location)");
+    shouldThrowErrorName("Object.preventExtensions(frames[0].location)", "SecurityError");
+    shouldBeTrue("Object.isExtensible(frames[0].location)");
+
+    debug("");
+    debug("* Same origin");
+    shouldBeTrue("Object.isExtensible(window)");
+    shouldThrowErrorName("Object.preventExtensions(window)", "TypeError");
+    shouldBeTrue("Object.isExtensible(window)");
+
+    shouldBeTrue("Object.isExtensible(window.location)");
+    shouldThrowErrorName("Object.preventExtensions(window.location)", "TypeError");
+    shouldBeTrue("Object.isExtensible(window.location)");
+
+    finishJSTest();
+};
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (205358 => 205359)


--- trunk/Source/_javascript_Core/ChangeLog	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-09-02 19:10:12 UTC (rev 205359)
@@ -1,5 +1,18 @@
 2016-09-02  Chris Dumez  <[email protected]>
 
+        Object.preventExtensions() should throw cross-origin
+        https://bugs.webkit.org/show_bug.cgi?id=161486
+
+        Reviewed by Geoffrey Garen.
+
+        Update JSProxy to forward preventExtensions() calls to its target.
+
+        * runtime/JSProxy.cpp:
+        (JSC::JSProxy::preventExtensions):
+        * runtime/JSProxy.h:
+
+2016-09-02  Chris Dumez  <[email protected]>
+
         Align proto getter / setter behavior with other browsers
         https://bugs.webkit.org/show_bug.cgi?id=161455
 

Modified: trunk/Source/_javascript_Core/runtime/JSProxy.cpp (205358 => 205359)


--- trunk/Source/_javascript_Core/runtime/JSProxy.cpp	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/_javascript_Core/runtime/JSProxy.cpp	2016-09-02 19:10:12 UTC (rev 205359)
@@ -102,6 +102,12 @@
     return thisObject->target()->methodTable(exec->vm())->deleteProperty(thisObject->target(), exec, propertyName);
 }
 
+bool JSProxy::preventExtensions(JSObject* object, ExecState* exec)
+{
+    JSProxy* thisObject = jsCast<JSProxy*>(object);
+    return thisObject->target()->methodTable(exec->vm())->preventExtensions(thisObject->target(), exec);
+}
+
 bool JSProxy::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
 {
     JSProxy* thisObject = jsCast<JSProxy*>(cell);

Modified: trunk/Source/_javascript_Core/runtime/JSProxy.h (205358 => 205359)


--- trunk/Source/_javascript_Core/runtime/JSProxy.h	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/_javascript_Core/runtime/JSProxy.h	2016-09-02 19:10:12 UTC (rev 205359)
@@ -96,6 +96,7 @@
     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow);
     JS_EXPORT_PRIVATE static bool setPrototype(JSObject*, ExecState*, JSValue, bool shouldThrowIfCantSet);
     JS_EXPORT_PRIVATE static JSValue getPrototype(JSObject*, ExecState*);
+    JS_EXPORT_PRIVATE static bool preventExtensions(JSObject*, ExecState*);
 
 private:
     WriteBarrier<JSObject> m_target;

Modified: trunk/Source/WebCore/ChangeLog (205358 => 205359)


--- trunk/Source/WebCore/ChangeLog	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/ChangeLog	2016-09-02 19:10:12 UTC (rev 205359)
@@ -1,5 +1,34 @@
 2016-09-02  Chris Dumez  <[email protected]>
 
+        Object.preventExtensions() should throw cross-origin
+        https://bugs.webkit.org/show_bug.cgi?id=161486
+
+        Reviewed by Geoffrey Garen.
+
+        Object.preventExtensions() should throw cross-origin:
+        - https://html.spec.whatwg.org/#windowproxy-preventextensions
+        - https://html.spec.whatwg.org/#location-preventextensions
+        - http://www.ecma-international.org/ecma-262/6.0/#sec-object.preventextensions
+
+        Firefox and Chrome both throw in the cross-origin case. Firefox also throws
+        a TypeError in the same-origin case for Window, as per the specification.
+        However, Firefox does not seem to throw yet in the same-origin case for
+        Location yet.
+
+        Test: http/tests/security/preventExtensions-window-location.html
+
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::preventExtensions):
+        * bindings/js/JSLocationCustom.cpp:
+        (WebCore::JSLocation::preventExtensions):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        * bindings/scripts/IDLAttributes.txt:
+        * page/DOMWindow.idl:
+        * page/Location.idl:
+
+2016-09-02  Chris Dumez  <[email protected]>
+
         Object.defineProperty() should throw cross-origin
         https://bugs.webkit.org/show_bug.cgi?id=161460
 

Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (205358 => 205359)


--- trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp	2016-09-02 19:10:12 UTC (rev 205359)
@@ -361,6 +361,14 @@
     return Base::getPrototype(object, exec);
 }
 
+bool JSDOMWindow::preventExtensions(JSObject* object, ExecState* exec)
+{
+    JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError))
+        return false;
+    return false;
+}
+
 // Custom Attributes
 
 void JSDOMWindow::setLocation(ExecState& state, JSValue value)

Modified: trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp (205358 => 205359)


--- trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp	2016-09-02 19:10:12 UTC (rev 205359)
@@ -147,6 +147,16 @@
     return Base::getPrototype(object, exec);
 }
 
+bool JSLocation::preventExtensions(JSObject* object, ExecState* exec)
+{
+    JSLocation* thisObject = jsCast<JSLocation*>(object);
+    if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError))
+        return false;
+    // FIXME: The specification says to return false in the same origin case as well but other browsers have
+    // not implemented this yet.
+    return Base::preventExtensions(object, exec);
+}
+
 bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult)
 {
     putResult = false;

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (205358 => 205359)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm	2016-09-02 19:10:12 UTC (rev 205359)
@@ -1326,6 +1326,9 @@
     push (@headerContent, "    static JSC::JSValue getPrototype(JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{"CustomGetPrototype"};
     push (@headerContent, "    static bool setPrototype(JSC::JSObject*, JSC::ExecState*, JSC::JSValue, bool shouldThrowIfCantSet);\n") if $interface->extendedAttributes->{"CustomSetPrototype"};
 
+    # Custom preventExtensions function.
+    push(@headerContent, "    static bool preventExtensions(JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{"CustomPreventExtensions"};
+    
     # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'.
     if ($interface->extendedAttributes->{"MasqueradesAsUndefined"}) {
         $structureFlags{"JSC::MasqueradesAsUndefined"} = 1;

Modified: trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt (205358 => 205359)


--- trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt	2016-09-02 19:10:12 UTC (rev 205359)
@@ -47,6 +47,7 @@
 CustomIsReachable
 CustomNamedGetter
 CustomNamedSetter
+CustomPreventExtensions
 CustomProxyToJSObject
 CustomPutFunction
 CustomReturn

Modified: trunk/Source/WebCore/page/DOMWindow.idl (205358 => 205359)


--- trunk/Source/WebCore/page/DOMWindow.idl	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/page/DOMWindow.idl	2016-09-02 19:10:12 UTC (rev 205359)
@@ -30,6 +30,7 @@
     CustomEnumerateProperty,
     CustomGetOwnPropertySlot,
     CustomGetPrototype,
+    CustomPreventExtensions,
     CustomProxyToJSObject,
     CustomPutFunction,
     CustomSetPrototype,

Modified: trunk/Source/WebCore/page/Location.idl (205358 => 205359)


--- trunk/Source/WebCore/page/Location.idl	2016-09-02 19:00:22 UTC (rev 205358)
+++ trunk/Source/WebCore/page/Location.idl	2016-09-02 19:10:12 UTC (rev 205359)
@@ -32,6 +32,7 @@
     CustomEnumerateProperty,
     CustomGetPrototype,
     CustomNamedSetter,
+    CustomPreventExtensions,
     CustomSetPrototype,
     GenerateIsReachable=ImplFrame,
     JSCustomDefineOwnProperty,
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to