Changeset 205354 in webkit
- Timestamp:
- Sep 2, 2016 11:04:25 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 3 deleted
- 41 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r205348 r205354 1 2016-09-02 Chris Dumez <cdumez@apple.com> 2 3 Align proto getter / setter behavior with other browsers 4 https://bugs.webkit.org/show_bug.cgi?id=161455 5 6 Reviewed by Mark Lam. 7 8 Add layout test coverage and update a few existing test to reflect 9 behavior change. 10 11 * http/tests/security/cross-frame-access-object-getPrototypeOf-expected.txt: 12 * http/tests/security/cross-frame-access-object-getPrototypeOf.html: 13 * http/tests/security/cross-frame-access-object-setPrototypeOf-expected.txt: 14 * http/tests/security/cross-frame-access-object-setPrototypeOf.html: 15 * http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt: 16 * http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html: 17 * http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt: 18 * http/tests/security/xss-DENIED-method-with-iframe-proto.html: 19 * http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt: 20 * http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html: 21 * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt: 22 * http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html: 23 * js/dom/setPrototypeOf-location-window-expected.txt: Added. 24 * js/dom/setPrototypeOf-location-window.html: Added. 25 1 26 2016-09-02 Eric Carlson <eric.carlson@apple.com> 2 27 -
trunk/LayoutTests/fast/dom/Window/window-custom-prototype-crash-expected.txt
r30157 r205354 1 CONSOLE MESSAGE: line 7: TypeError: Cannot set prototype of this object 1 2 If this did not crash the test has succeeded. -
trunk/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf-expected.txt
r205301 r205354 1 CONSOLE MESSAGE: line 1: 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.2 CONSOLE MESSAGE: line 1: 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.3 1 This tests that you can't get the prototype of the window or history objects cross-origin using Object.getPrototypeOf(). 4 2 5 3 PASS: Object.getPrototypeOf(targetWindow) should be 'null' and is. 6 4 PASS: Object.getPrototypeOf(targetWindow.location) should be 'null' and is. 5 PASS: protoGetter.call(targetWindow) should be 'null' and is. 6 PASS: protoGetter.call(targetWindow.location) should be 'null' and is. 7 7 PASS targetWindow.history 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.. 8 8 PASS: successfullyParsed should be 'true' and is. -
trunk/LayoutTests/http/tests/security/cross-frame-access-object-getPrototypeOf.html
r205301 r205354 19 19 shouldBeNull("Object.getPrototypeOf(targetWindow)"); 20 20 shouldBeNull("Object.getPrototypeOf(targetWindow.location)"); 21 protoGetter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').get; 22 shouldBeNull("protoGetter.call(targetWindow)"); 23 shouldBeNull("protoGetter.call(targetWindow.location)"); 24 21 25 shouldThrowErrorName("targetWindow.history", "SecurityError"); 22 26 -
trunk/LayoutTests/http/tests/security/cross-frame-access-object-setPrototypeOf-expected.txt
r205301 r205354 1 CONSOLE MESSAGE: line 1: 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.2 CONSOLE MESSAGE: line 1: 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.3 1 This tests that you can't set the prototype of the window or location objects cross-origin using Object.setPrototypeOf() 4 2 … … 7 5 8 6 PASS: targetWindow instanceof Array should be 'false' and is. 9 PASS Object.setPrototypeOf(targetWindow, Array.prototype) threw exception TypeError: Permission denied.7 PASS Object.setPrototypeOf(targetWindow, Array.prototype) threw exception TypeError: Cannot set prototype of this object. 10 8 PASS: targetWindow instanceof Array should be 'false' and is. 11 9 PASS: targetWindow.location instanceof Array should be 'false' and is. 12 PASS Object.setPrototypeOf(targetWindow.location, Array.prototype) threw exception TypeError: Permission denied. 10 PASS Object.setPrototypeOf(targetWindow.location, Array.prototype) threw exception TypeError: Cannot set prototype of this object. 11 PASS: targetWindow.location instanceof Array should be 'false' and is. 12 PASS: targetWindow instanceof Array should be 'false' and is. 13 PASS protoSetter.call(targetWindow, Array.prototype) threw exception TypeError: Cannot set prototype of this object. 14 PASS: targetWindow instanceof Array should be 'false' and is. 15 PASS: targetWindow.location instanceof Array should be 'false' and is. 16 PASS protoSetter.call(targetWindow.location, Array.prototype) threw exception TypeError: Cannot set prototype of this object. 13 17 PASS: targetWindow.location instanceof Array should be 'false' and is. 14 18 PASS: successfullyParsed should be 'true' and is. -
trunk/LayoutTests/http/tests/security/cross-frame-access-object-setPrototypeOf.html
r205301 r205354 25 25 shouldBeFalse("targetWindow.location instanceof Array"); 26 26 27 protoSetter = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set; 28 shouldBeFalse("targetWindow instanceof Array"); 29 shouldThrowErrorName("protoSetter.call(targetWindow, Array.prototype)", "TypeError"); 30 shouldBeFalse("targetWindow instanceof Array"); 31 32 shouldBeFalse("targetWindow.location instanceof Array"); 33 shouldThrowErrorName("protoSetter.call(targetWindow.location, Array.prototype)", "TypeError"); 34 shouldBeFalse("targetWindow.location instanceof Array"); 35 27 36 finishJSTest(); 28 37 } -
trunk/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto-expected.txt
r205136 r205354 5 5 6 6 7 PASS __proto__ = targetWindow threw exception TypeError: Cannot set prototype of this object. 7 8 PASS targetWindow.myinput 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.. 8 9 PASS: successfullyParsed should be 'true' and is. -
trunk/LayoutTests/http/tests/security/xss-DENIED-htmlelelment-with-iframe-proto.html
r205136 r205354 15 15 16 16 window.onload = function() { 17 __proto__ = targetWindow;17 shouldThrowErrorName("__proto__ = targetWindow", "TypeError"); 18 18 shouldThrowErrorName('targetWindow.myinput', 'SecurityError'); 19 19 finishJSTest(); -
trunk/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto-expected.txt
r205136 r205354 1 CONSOLE MESSAGE: line 40: 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.2 CONSOLE MESSAGE: line 4 7: 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.3 CONSOLE MESSAGE: line 5 4: 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.1 CONSOLE MESSAGE: line 36: 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. 2 CONSOLE MESSAGE: line 43: 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. 3 CONSOLE MESSAGE: line 50: 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. 4 4 5 5 Tests that making other frame window a prototype doesn't expose that window methods 6 6 7 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 8 9 10 PASS __proto__ = targetWindow threw exception TypeError: Cannot set prototype of this object. 11 PASS: successfullyParsed should be 'true' and is. 12 13 TEST COMPLETE 14 -
trunk/LayoutTests/http/tests/security/xss-DENIED-method-with-iframe-proto.html
r205096 r205354 1 1 <html> 2 2 <head> 3 <script src="/js-test-resources/js-test-pre.js"></script> 3 4 <script src="resources/cross-frame-access.js"></script> 4 5 </head> … … 7 8 <pre id="console"></pre> 8 9 <script> 9 if (window.testRunner) { 10 testRunner.dumpAsText(); 11 testRunner.waitUntilDone(); 12 } 13 14 log("Tests that making other frame window a prototype doesn't expose that window methods"); 10 description("Tests that making other frame window a prototype doesn't expose that window methods"); 11 jsTestIsAsync = true; 15 12 16 13 targetWindow = frames[0]; … … 24 21 function check() { 25 22 shouldBeFalse('this.wasInvoked'); 26 if (window.testRunner) 27 testRunner.notifyDone(); 23 finishJSTest(); 28 24 } 29 25 … … 31 27 originalSetTimeout = setTimeout; 32 28 33 __proto__ = targetWindow;29 shouldThrowErrorName("__proto__ = targetWindow", "TypeError"); 34 30 35 31 var needsCheck = false; … … 58 54 originalSetTimeout(check, 10); 59 55 } else { 60 if (window.testRunner) 61 testRunner.notifyDone(); 56 finishJSTest(); 62 57 } 63 58 } 64 59 </script> 60 <script src="/js-test-resources/js-test-post.js"></script> 65 61 </body> 66 62 </html> -
trunk/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto-expected.txt
r48484 r205354 1 1 2 2 Tests that making other frame window a prototype doesn't expose that window properties 3 4 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 5 6 7 PASS __proto__ = targetWindow threw exception TypeError: Cannot set prototype of this object. 3 8 PASS: location === originalLocation should be 'true' and is. 4 9 PASS: this.location === originalLocation should be 'true' and is. 10 PASS: successfullyParsed should be 'true' and is. 5 11 12 TEST COMPLETE 13 -
trunk/LayoutTests/http/tests/security/xss-DENIED-non-shadowable-propterty-with-iframe-proto.html
r120174 r205354 1 1 <html> 2 2 <head> 3 <script src="/js-test-resources/js-test-pre.js"></script> 3 4 <script src="resources/cross-frame-access.js"></script> 4 5 </head> … … 7 8 <pre id="console"></pre> 8 9 <script> 9 if (window.testRunner) 10 testRunner.dumpAsText(); 11 12 log("Tests that making other frame window a prototype doesn't expose that window properties"); 10 description("Tests that making other frame window a prototype doesn't expose that window properties"); 11 jsTestIsAsync = true; 13 12 14 13 targetWindow = frames[0]; … … 17 16 originalLocation = location; 18 17 19 __proto__ = targetWindow;18 shouldThrowErrorName("__proto__ = targetWindow", "TypeError"); 20 19 21 20 shouldBeTrue('location === originalLocation'); 22 21 shouldBeTrue('this.location === originalLocation'); 22 finishJSTest(); 23 23 } 24 24 </script> 25 <script src="/js-test-resources/js-test-post.js"></script> 25 26 </body> 26 27 </html> -
trunk/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto-expected.txt
r48484 r205354 1 1 2 2 Tests that making other frame window a prototype doesn't expose that window properties 3 4 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". 5 6 7 PASS __proto__ = targetWindow threw exception TypeError: Cannot set prototype of this object. 3 8 PASS: innerHeight === originalInnerHeight should be 'true' and is. 4 9 PASS: this.innerHeight === originalInnerHeight should be 'true' and is. 10 PASS: successfullyParsed should be 'true' and is. 5 11 12 TEST COMPLETE 13 -
trunk/LayoutTests/http/tests/security/xss-DENIED-regular-propterty-with-iframe-proto.html
r120174 r205354 1 1 <html> 2 2 <head> 3 <script src="/js-test-resources/js-test-pre.js"></script> 3 4 <script src="resources/cross-frame-access.js"></script> 4 5 </head> … … 7 8 <pre id="console"></pre> 8 9 <script> 9 if (window.testRunner) 10 testRunner.dumpAsText(); 11 12 log("Tests that making other frame window a prototype doesn't expose that window properties"); 10 description("Tests that making other frame window a prototype doesn't expose that window properties"); 11 jsTestIsAsync = true; 13 12 14 13 targetWindow = frames[0]; … … 17 16 originalInnerHeight = innerHeight; 18 17 19 __proto__ = targetWindow;18 shouldThrowErrorName("__proto__ = targetWindow", "TypeError"); 20 19 21 20 shouldBeTrue('innerHeight === originalInnerHeight'); 22 21 shouldBeTrue('this.innerHeight === originalInnerHeight'); 22 finishJSTest(); 23 23 } 24 24 </script> 25 <script src="/js-test-resources/js-test-post.js"></script> 25 26 </body> 26 27 </html> -
trunk/LayoutTests/js/object-literal-shorthand-construction-expected.txt
r181179 r205354 62 62 PASS !!Object.getOwnPropertyDescriptor({set 'x'(value){}}, 'x').set is true 63 63 PASS !!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set is true 64 PASS __proto__ = []; ({__proto__: __proto__}) instanceof Array is true 65 PASS __proto__ = []; ({__proto__}) instanceof Array is false 66 PASS __proto__ = []; ({__proto__}).__proto__ instanceof Array is true 64 PASS __proto__ = [] threw exception TypeError: Cannot set prototype of this object. 67 65 PASS successfullyParsed is true 68 66 -
trunk/LayoutTests/js/script-tests/object-literal-shorthand-construction.js
r181179 r205354 110 110 shouldBeTrue("!!Object.getOwnPropertyDescriptor({set 42(value){}}, '42').set"); 111 111 112 // __proto__ shorthand should be not modify the prototype. 113 shouldBeTrue("__proto__ = []; ({__proto__: __proto__}) instanceof Array"); 114 shouldBeFalse("__proto__ = []; ({__proto__}) instanceof Array"); 115 shouldBeTrue("__proto__ = []; ({__proto__}).__proto__ instanceof Array"); 112 shouldThrowErrorName("__proto__ = []", "TypeError"); -
trunk/LayoutTests/js/script-tests/sloppy-getter-setter-global-object.js
r183275 r205354 34 34 35 35 var top_level_sloppy_setter = Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set; 36 should NotThrow("top_level_sloppy_setter(['foo']);");36 shouldThrowErrorName("top_level_sloppy_setter(['foo']);", "TypeError"); -
trunk/LayoutTests/js/sloppy-getter-setter-global-object-expected.txt
r183275 r205354 12 12 PASS (0,Object.getOwnPropertyDescriptor(Object.prototype,'__proto__').set)(['foo']) threw exception TypeError: Can't convert undefined or null to object. 13 13 PASS top_level_sloppy_getter(); did not throw exception. 14 PASS top_level_sloppy_setter(['foo']); did not throw exception.14 PASS top_level_sloppy_setter(['foo']); threw exception TypeError: Cannot set prototype of this object. 15 15 PASS successfullyParsed is true 16 16 -
trunk/Source/JavaScriptCore/ChangeLog
r205335 r205354 1 2016-09-02 Chris Dumez <cdumez@apple.com> 2 3 Align proto getter / setter behavior with other browsers 4 https://bugs.webkit.org/show_bug.cgi?id=161455 5 6 Reviewed by Mark Lam. 7 8 Drop allowsAccessFrom from the methodTable and delegate cross-origin 9 checking to the DOM bindings for [[SetPrototypeOf]] / [[GetPrototypeOf]]. 10 This is more consistent with other operations (e.g. [[GetOwnProperty]]). 11 12 * jsc.cpp: 13 * runtime/JSGlobalObject.cpp: 14 * runtime/JSGlobalObject.h: 15 * runtime/JSGlobalObjectFunctions.cpp: 16 (JSC::globalFuncProtoGetter): 17 (JSC::globalFuncProtoSetter): 18 (JSC::globalFuncBuiltinLog): Deleted. 19 * runtime/JSGlobalObjectFunctions.h: 20 * runtime/JSObject.h: 21 (JSC::JSObject::getArrayLength): Deleted. 22 * runtime/JSProxy.cpp: 23 (JSC::JSProxy::setPrototype): 24 (JSC::JSProxy::getPrototype): 25 * runtime/JSProxy.h: 26 * runtime/ObjectConstructor.cpp: 27 (JSC::objectConstructorGetPrototypeOf): 28 (JSC::objectConstructorSetPrototypeOf): 29 (JSC::objectConstructorGetOwnPropertyDescriptor): Deleted. 30 (JSC::objectConstructorGetOwnPropertyDescriptors): Deleted. 31 * runtime/ObjectConstructor.h: 32 * runtime/ReflectObject.cpp: 33 (JSC::reflectObjectGetPrototypeOf): 34 (JSC::reflectObjectSetPrototypeOf): 35 36 * runtime/JSObject.cpp: 37 (JSC::JSObject::setPrototypeWithCycleCheck): 38 Comment out check added in r197648. This check was added to match 39 the latest EcmaScript spec: 40 - https://tc39.github.io/ecma262/#sec-ordinarysetprototypeof (step 8) 41 This check allowed for [[Prototype]] chain cycles if the prototype 42 chain includes objects that do not use the ordinary object definitions 43 for [[GetPrototypeOf]] and [[SetPrototypeOf]]. 44 The issue is that the rest of our code base does not properly handle 45 such cycles and we can end up in infinite loops. This became obvious 46 because this patch updates Window / Location so that they no longer 47 use the default [[GetPrototypeOf]] / [[SetPrototypeOf]]. If I do not 48 comment out this check, I get an infinite loop in 49 Structure::anyObjectInChainMayInterceptIndexedAccesses(), which is 50 called from JSObject::setPrototypeDirect(), when running the following 51 layout test: 52 - html/browsers/history/the-location-interface/allow_prototype_cycle_through_location.sub.html 53 I filed https://bugs.webkit.org/show_bug.cgi?id=161534 to track this 54 issue. 55 1 56 2016-09-01 Yusuke Suzuki <utatane.tea@gmail.com> 2 57 -
trunk/Source/JavaScriptCore/jsc.cpp
r205328 r205354 904 904 905 905 const ClassInfo GlobalObject::s_info = { "global", &JSGlobalObject::s_info, nullptr, CREATE_METHOD_TABLE(GlobalObject) }; 906 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { & allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr };906 const GlobalObjectMethodTable GlobalObject::s_globalObjectMethodTable = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, 0, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, nullptr, nullptr }; 907 907 908 908 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r205198 r205354 208 208 const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &Base::s_info, &globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) }; 209 209 210 const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { & allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, nullptr, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };210 const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, nullptr, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr }; 211 211 212 212 /* Source for JSGlobalObject.lut.h -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h
r205278 r205354 149 149 150 150 struct GlobalObjectMethodTable { 151 typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*);152 AllowsAccessFromFunctionPtr allowsAccessFrom;153 154 151 typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*); 155 152 SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo; … … 713 710 const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; } 714 711 715 static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; }716 712 static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; } 717 713 -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp
r205301 r205354 867 867 } 868 868 869 class GlobalFuncProtoGetterFunctor {870 public:871 GlobalFuncProtoGetterFunctor(ExecState* exec, JSObject* thisObject)872 : m_exec(exec)873 , m_hasSkippedFirstFrame(false)874 , m_thisObject(thisObject)875 , m_result(JSValue::encode(jsUndefined()))876 {877 }878 879 EncodedJSValue result() { return m_result; }880 881 StackVisitor::Status operator()(StackVisitor& visitor) const882 {883 if (!m_hasSkippedFirstFrame) {884 m_hasSkippedFirstFrame = true;885 return StackVisitor::Continue;886 }887 888 if (m_thisObject->allowsAccessFrom(visitor->callFrame()))889 m_result = JSValue::encode(m_thisObject->getPrototype(m_exec->vm(), m_exec));890 891 return StackVisitor::Done;892 }893 894 private:895 ExecState* m_exec;896 mutable bool m_hasSkippedFirstFrame;897 JSObject* m_thisObject;898 mutable EncodedJSValue m_result;899 };900 901 869 EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec) 902 870 { … … 916 884 } 917 885 918 GlobalFuncProtoGetterFunctor functor(exec, thisObject); 919 // This can throw but it's just unneeded extra work to check for it. The return 920 // value from this function is only used as the return value from a host call. 921 // Therefore, the return value is only used if there wasn't an exception. 922 exec->iterate(functor); 923 return functor.result(); 924 } 925 926 class GlobalFuncProtoSetterFunctor { 927 public: 928 GlobalFuncProtoSetterFunctor(JSObject* thisObject) 929 : m_hasSkippedFirstFrame(false) 930 , m_allowsAccess(false) 931 , m_thisObject(thisObject) 932 { 933 } 934 935 bool allowsAccess() const { return m_allowsAccess; } 936 937 StackVisitor::Status operator()(StackVisitor& visitor) const 938 { 939 if (!m_hasSkippedFirstFrame) { 940 m_hasSkippedFirstFrame = true; 941 return StackVisitor::Continue; 942 } 943 944 m_allowsAccess = m_thisObject->allowsAccessFrom(visitor->callFrame()); 945 return StackVisitor::Done; 946 } 947 948 private: 949 mutable bool m_hasSkippedFirstFrame; 950 mutable bool m_allowsAccess; 951 JSObject* m_thisObject; 952 }; 953 954 bool checkProtoSetterAccessAllowed(ExecState* exec, JSObject* object) 955 { 956 GlobalFuncProtoSetterFunctor functor(object); 957 exec->iterate(functor); 958 return functor.allowsAccess(); 886 return JSValue::encode(thisObject->getPrototype(vm, exec)); 959 887 } 960 888 … … 975 903 return JSValue::encode(jsUndefined()); 976 904 977 if (!checkProtoSetterAccessAllowed(exec, thisObject))978 return JSValue::encode(jsUndefined());979 980 905 // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. 981 906 if (!value.isObject() && !value.isNull()) -
trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h
r202680 r205354 53 53 EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*); 54 54 55 bool checkProtoSetterAccessAllowed(ExecState*, JSObject*);56 57 55 static const double mantissaOverflowLowerBound = 9007199254740992.0; 58 56 double parseIntOverflow(const LChar*, unsigned length, int radix); -
trunk/Source/JavaScriptCore/runtime/JSObject.cpp
r205198 r205354 1372 1372 1373 1373 JSValue nextPrototype = prototype; 1374 MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;1375 1374 while (nextPrototype && nextPrototype.isObject()) { 1376 1375 if (nextPrototype == this) { … … 1379 1378 return false; 1380 1379 } 1381 if (UNLIKELY(asObject(nextPrototype)->methodTable(vm)->getPrototype != defaultGetPrototype)) 1382 break; // We're done. Set the prototype. 1380 // FIXME: The specification says we should do this but this allows for cycles and our 1381 // code base currently does not deal properly with such cycles. 1382 // https://bugs.webkit.org/show_bug.cgi?id=161534 1383 // if (UNLIKELY(asObject(nextPrototype)->methodTable(vm)->getPrototype != JSObject::getPrototype)) 1384 // break; // We're done. Set the prototype. 1383 1385 nextPrototype = asObject(nextPrototype)->getPrototypeDirect(); 1384 1386 } … … 1400 1402 { 1401 1403 return methodTable(vm)->setPrototype(this, exec, prototype, shouldThrowIfCantSet); 1402 }1403 1404 bool JSObject::allowsAccessFrom(ExecState* exec)1405 {1406 JSGlobalObject* globalObject = this->globalObject();1407 return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec);1408 1404 } 1409 1405 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r205324 r205354 169 169 JS_EXPORT_PRIVATE bool getOwnPropertyDescriptor(ExecState*, PropertyName, PropertyDescriptor&); 170 170 171 JS_EXPORT_PRIVATE bool allowsAccessFrom(ExecState*);172 173 171 unsigned getArrayLength() const 174 172 { -
trunk/Source/JavaScriptCore/runtime/JSProxy.cpp
r198023 r205354 140 140 } 141 141 142 bool JSProxy::setPrototype(JSObject* object, ExecState* exec, JSValue value, bool shouldThrowIfCantSet) 143 { 144 JSProxy* thisObject = jsCast<JSProxy*>(object); 145 return thisObject->target()->methodTable(exec->vm())->setPrototype(thisObject->target(), exec, value, shouldThrowIfCantSet); 146 } 147 148 JSValue JSProxy::getPrototype(JSObject* object, ExecState* exec) 149 { 150 JSProxy* thisObject = jsCast<JSProxy*>(object); 151 return thisObject->target()->methodTable(exec->vm())->getPrototype(thisObject->target(), exec); 152 } 153 142 154 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/JSProxy.h
r201808 r205354 95 95 JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); 96 96 JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool shouldThrow); 97 JS_EXPORT_PRIVATE static bool setPrototype(JSObject*, ExecState*, JSValue, bool shouldThrowIfCantSet); 98 JS_EXPORT_PRIVATE static JSValue getPrototype(JSObject*, ExecState*); 97 99 98 100 private: -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.cpp
r205258 r205354 167 167 } 168 168 169 class ObjectConstructorGetPrototypeOfFunctor {170 public:171 ObjectConstructorGetPrototypeOfFunctor(ExecState* exec, JSObject* object)172 : m_exec(exec)173 , m_hasSkippedFirstFrame(false)174 , m_object(object)175 , m_result(jsUndefined())176 {177 }178 179 JSValue result() const { return m_result; }180 181 StackVisitor::Status operator()(StackVisitor& visitor) const182 {183 if (!m_hasSkippedFirstFrame) {184 m_hasSkippedFirstFrame = true;185 return StackVisitor::Continue;186 }187 188 if (m_object->allowsAccessFrom(visitor->callFrame()))189 m_result = m_object->getPrototype(m_exec->vm(), m_exec);190 else191 m_result = jsNull();192 return StackVisitor::Done;193 }194 195 private:196 ExecState* m_exec;197 mutable bool m_hasSkippedFirstFrame;198 JSObject* m_object;199 mutable JSValue m_result;200 };201 202 JSValue objectConstructorGetPrototypeOf(ExecState* exec, JSObject* object)203 {204 ObjectConstructorGetPrototypeOfFunctor functor(exec, object);205 // This can throw but it's just unneeded extra work to check for it. The return206 // value from this function is only used as the return value from a host call.207 // Therefore, the return value is only used if there wasn't an exception.208 exec->iterate(functor);209 return functor.result();210 }211 212 169 EncodedJSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState* exec) 213 170 { … … 215 172 if (exec->hadException()) 216 173 return JSValue::encode(jsUndefined()); 217 return JSValue::encode(object ConstructorGetPrototypeOf(exec, object));174 return JSValue::encode(object->getPrototype(exec->vm(), exec)); 218 175 } 219 176 … … 234 191 if (exec->hadException()) 235 192 return JSValue::encode(objectValue); 236 237 if (!checkProtoSetterAccessAllowed(exec, object)) {238 throwTypeError(exec, scope, ASCIILiteral("Permission denied"));239 return JSValue::encode(objectValue);240 }241 193 242 194 bool shouldThrowIfCantSet = true; -
trunk/Source/JavaScriptCore/runtime/ObjectConstructor.h
r204679 r205354 125 125 126 126 JS_EXPORT_PRIVATE JSObject* objectConstructorFreeze(ExecState*, JSObject*); 127 JSValue objectConstructorGetPrototypeOf(ExecState*, JSObject*);128 127 JSValue objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, const Identifier&); 129 128 JSValue objectConstructorGetOwnPropertyDescriptors(ExecState*, JSObject*); -
trunk/Source/JavaScriptCore/runtime/ReflectObject.cpp
r205198 r205354 216 216 if (!target.isObject()) 217 217 return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Reflect.getPrototypeOf requires the first argument be an object"))); 218 return JSValue::encode( objectConstructorGetPrototypeOf(exec, asObject(target)));218 return JSValue::encode(asObject(target)->getPrototype(exec->vm(), exec)); 219 219 } 220 220 … … 302 302 303 303 JSObject* object = asObject(target); 304 305 if (!checkProtoSetterAccessAllowed(exec, object))306 return JSValue::encode(jsBoolean(false));307 304 308 305 bool shouldThrowIfCantSet = false; -
trunk/Source/WebCore/ChangeLog
r205348 r205354 1 2016-09-02 Chris Dumez <cdumez@apple.com> 2 3 Align proto getter / setter behavior with other browsers 4 https://bugs.webkit.org/show_bug.cgi?id=161455 5 6 Reviewed by Mark Lam. 7 8 Align cross-origin __proto__ getter / setter behavior with other 9 browsers and the specification: 10 11 [[SetPrototypeOf]] should throw a TypeError: 12 - https://html.spec.whatwg.org/#windowproxy-setprototypeof 13 - https://html.spec.whatwg.org/#location-setprototypeof 14 - https://tc39.github.io/ecma262/#sec-object.setprototypeof (step 5) 15 16 [[GetPrototypeOf]] should return null cross-origin: 17 - https://html.spec.whatwg.org/#windowproxy-getprototypeof 18 - https://html.spec.whatwg.org/#location-getprototypeof 19 20 Test: js/dom/setPrototypeOf-location-window.html 21 22 * bindings/js/JSDOMWindowBase.cpp: 23 (WebCore::JSDOMWindowBase::JSDOMWindowBase): Deleted. 24 * bindings/js/JSDOMWindowCustom.cpp: 25 (WebCore::JSDOMWindow::setPrototype): 26 (WebCore::JSDOMWindow::getPrototype): 27 * bindings/js/JSLocationCustom.cpp: 28 (WebCore::JSLocation::setPrototype): 29 (WebCore::JSLocation::getPrototype): 30 * bindings/js/JSWorkerGlobalScopeBase.cpp: 31 (WebCore::JSWorkerGlobalScopeBase::supportsRichSourceInfo): Deleted. 32 * bindings/js/JSWorkerGlobalScopeBase.h: 33 * bindings/scripts/CodeGeneratorJS.pm: 34 (GenerateHeader): 35 * bindings/scripts/IDLAttributes.txt: 36 * page/DOMWindow.idl: 37 * page/Location.idl: 38 1 39 2016-09-02 Eric Carlson <eric.carlson@apple.com> 2 40 -
trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
r205278 r205354 58 58 namespace WebCore { 59 59 60 static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec)61 {62 return BindingSecurity::shouldAllowAccessToDOMWindow(exec, asJSDOMWindow(thisObject)->wrapped());63 }64 65 60 const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) }; 66 61 67 const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &s houldAllowAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, &moduleLoaderEvaluate, &defaultLanguage };62 const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout, &moduleLoaderResolve, &moduleLoaderFetch, nullptr, nullptr, &moduleLoaderEvaluate, &defaultLanguage }; 68 63 69 64 JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, RefPtr<DOMWindow>&& window, JSDOMWindowShell* shell) -
trunk/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
r205200 r205354 343 343 } 344 344 345 bool JSDOMWindow::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrowIfCantSet) 346 { 347 auto scope = DECLARE_THROW_SCOPE(exec->vm()); 348 349 if (shouldThrowIfCantSet) 350 throwTypeError(exec, scope, ASCIILiteral("Cannot set prototype of this object")); 351 352 return false; 353 } 354 355 JSValue JSDOMWindow::getPrototype(JSObject* object, ExecState* exec) 356 { 357 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object); 358 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) 359 return jsNull(); 360 361 return Base::getPrototype(object, exec); 362 } 363 345 364 // Custom Attributes 346 365 -
trunk/Source/WebCore/bindings/js/JSLocationCustom.cpp
r205200 r205354 125 125 } 126 126 127 bool JSLocation::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrowIfCantSet) 128 { 129 auto scope = DECLARE_THROW_SCOPE(exec->vm()); 130 131 if (shouldThrowIfCantSet) 132 throwTypeError(exec, scope, ASCIILiteral("Cannot set prototype of this object")); 133 134 return false; 135 } 136 137 JSValue JSLocation::getPrototype(JSObject* object, ExecState* exec) 138 { 139 JSLocation* thisObject = jsCast<JSLocation*>(object); 140 if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError)) 141 return jsNull(); 142 143 return Base::getPrototype(object, exec); 144 } 145 127 146 bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult) 128 147 { -
trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
r201808 r205354 46 46 const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) }; 47 47 48 const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = { & allowsAccessFrom, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, &defaultLanguage };48 const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = { &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptRuntimeFlags, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout, nullptr, nullptr, nullptr, nullptr, nullptr, &defaultLanguage }; 49 49 50 50 JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, RefPtr<WorkerGlobalScope>&& impl) … … 78 78 { 79 79 return m_wrapped.get(); 80 }81 82 bool JSWorkerGlobalScopeBase::allowsAccessFrom(const JSGlobalObject* object, ExecState* exec)83 {84 return JSGlobalObject::allowsAccessFrom(object, exec);85 80 } 86 81 -
trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
r201808 r205354 54 54 static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable; 55 55 56 static bool allowsAccessFrom(const JSC::JSGlobalObject*, JSC::ExecState*);57 56 static bool supportsRichSourceInfo(const JSC::JSGlobalObject*); 58 57 static bool shouldInterruptScript(const JSC::JSGlobalObject*); -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r205257 r205354 1322 1322 # Custom defineOwnProperty function 1323 1323 push(@headerContent, " static bool defineOwnProperty(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, const JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interface->extendedAttributes->{"JSCustomDefineOwnProperty"}; 1324 1325 # Custom getPrototype / setPrototype functions. 1326 push (@headerContent, " static JSC::JSValue getPrototype(JSC::JSObject*, JSC::ExecState*);\n") if $interface->extendedAttributes->{"CustomGetPrototype"}; 1327 push (@headerContent, " static bool setPrototype(JSC::JSObject*, JSC::ExecState*, JSC::JSValue, bool shouldThrowIfCantSet);\n") if $interface->extendedAttributes->{"CustomSetPrototype"}; 1324 1328 1325 1329 # Override toBoolean to return false for objects that want to 'MasqueradesAsUndefined'. -
trunk/Source/WebCore/bindings/scripts/IDLAttributes.txt
r204717 r205354 42 42 CustomEnumerateProperty 43 43 CustomGetOwnPropertySlot 44 CustomGetPrototype 44 45 CustomGetter 45 46 CustomIndexedSetter … … 50 51 CustomPutFunction 51 52 CustomReturn 53 CustomSetPrototype 52 54 CustomSetter 53 55 CustomToJSObject -
trunk/Source/WebCore/page/DOMWindow.idl
r205280 r205354 30 30 CustomEnumerateProperty, 31 31 CustomGetOwnPropertySlot, 32 CustomGetPrototype, 32 33 CustomProxyToJSObject, 33 34 CustomPutFunction, 35 CustomSetPrototype, 34 36 ExportMacro=WEBCORE_EXPORT, 35 37 ImplicitThis, -
trunk/Source/WebCore/page/Location.idl
r205154 r205354 31 31 CustomDeleteProperty, 32 32 CustomEnumerateProperty, 33 CustomGetPrototype, 33 34 CustomNamedSetter, 35 CustomSetPrototype, 34 36 GenerateIsReachable=ImplFrame, 35 37 JSCustomDefineOwnProperty,
Note: See TracChangeset
for help on using the changeset viewer.