commit b81169268271e65b897e4df2a1f58dd2718af1c7 Author: Arthur Edelstein arthuredelstein@gmail.com Date: Tue Aug 12 15:14:39 2014 -0700
fixup! Bug #2874. Remove the Components shim introduced by Mozilla Bug #790732.
Includes a regression test to ensure the window.Components object is not exposed to untrusted content. --- dom/base/nsDOMClassInfo.cpp | 98 -------------------- js/xpconnect/tests/mochitest/Makefile.in | 3 +- js/xpconnect/tests/mochitest/file_bug790732.html | 56 ----------- js/xpconnect/tests/mochitest/test_bug790732.html | 46 --------- js/xpconnect/tests/mochitest/test_tor_bug2874.html | 25 +++++ toolkit/components/telemetry/Histograms.json | 4 - 6 files changed, 26 insertions(+), 206 deletions(-)
diff --git a/dom/base/nsDOMClassInfo.cpp b/dom/base/nsDOMClassInfo.cpp index e5fcebf..2a9d5a8 100644 --- a/dom/base/nsDOMClassInfo.cpp +++ b/dom/base/nsDOMClassInfo.cpp @@ -4282,98 +4282,6 @@ LocationSetterUnwrapper(JSContext *cx, JS::Handle<JSObject*> obj_, JS::Handle<js return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp); }
-struct InterfaceShimEntry { - const char *geckoName; - const char *domName; -}; - -// We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each -// interface that has interface constants that sites might be getting off -// of Ci. -const InterfaceShimEntry kInterfaceShimMap[] = -{ { "nsIDOMFileReader", "FileReader" }, - { "nsIXMLHttpRequest", "XMLHttpRequest" }, - { "nsIDOMDOMException", "DOMException" }, - { "nsIDOMNode", "Node" }, - { "nsIDOMUserDataHandler", "UserDataHandler" }, - { "nsIDOMCSSPrimitiveValue", "CSSPrimitiveValue" }, - { "nsIDOMCSSRule", "CSSRule" }, - { "nsIDOMCSSValue", "CSSValue" }, - { "nsIDOMEvent", "Event" }, - { "nsIDOMNSEvent", "Event" }, - { "nsIDOMKeyEvent", "KeyEvent" }, - { "nsIDOMMouseEvent", "MouseEvent" }, - { "nsIDOMMouseScrollEvent", "MouseScrollEvent" }, - { "nsIDOMMutationEvent", "MutationEvent" }, - { "nsIDOMSimpleGestureEvent", "SimpleGestureEvent" }, - { "nsIDOMUIEvent", "UIEvent" }, - { "nsIDOMGeoPositionError", "GeoPositionError" }, - { "nsIDOMHTMLMediaElement", "HTMLMediaElement" }, - { "nsIDOMMediaError", "MediaError" }, - { "nsIDOMLoadStatus", "LoadStatus" }, - { "nsIDOMOfflineResourceList", "OfflineResourceList" }, - { "nsIDOMRange", "Range" }, - { "nsIDOMSVGFETurbulenceElement", "SVGFETurbulenceElement" }, - { "nsIDOMSVGFEMorphologyElement", "SVGFEMorphologyElement" }, - { "nsIDOMSVGFEConvolveMatrixElement", "SVGFEConvolveMatrixElement" }, - { "nsIDOMSVGFEDisplacementMapElement", "SVGFEDisplacementMapElement" }, - { "nsIDOMSVGLength", "SVGLength" }, - { "nsIDOMSVGUnitTypes", "SVGUnitTypes" }, - { "nsIDOMNodeFilter", "NodeFilter" }, - { "nsIDOMXPathNamespace", "XPathNamespace" }, - { "nsIDOMXPathResult", "XPathResult" }, - { "nsIDOMXULButtonElement", "XULButtonElement" }, - { "nsIDOMXULCheckboxElement", "XULCheckboxElement" }, - { "nsIDOMXULPopupElement", "XULPopupElement" } }; - -static nsresult -DefineComponentsShim(JSContext *cx, JS::HandleObject global) -{ - // Keep track of how often this happens. - Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true); - - // Create a fake Components object. - JS::Rooted<JSObject*> components(cx, JS_NewObject(cx, nullptr, nullptr, global)); - NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY); - bool ok = JS_DefineProperty(cx, global, "Components", JS::ObjectValue(*components), - JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE); - NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); - - // Create a fake interfaces object. - JS::Rooted<JSObject*> interfaces(cx, JS_NewObject(cx, nullptr, nullptr, global)); - NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY); - ok = JS_DefineProperty(cx, components, "interfaces", JS::ObjectValue(*interfaces), - JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); - NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); - - // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM - // interfaces with constants. - for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) { - - // Grab the names from the table. - const char *geckoName = kInterfaceShimMap[i].geckoName; - const char *domName = kInterfaceShimMap[i].domName; - - // Look up the appopriate interface object on the global. - JS::RootedJS::Value v(cx, JS::UndefinedValue()); - ok = JS_GetProperty(cx, global, domName, v.address()); - NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); - if (!v.isObject()) { - NS_WARNING("Unable to find interface object on global"); - continue; - } - - // Define the shim on the interfaces object. - ok = JS_DefineProperty(cx, interfaces, geckoName, v, - JS_PropertyStub, JS_StrictPropertyStub, - JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY); - NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY); - } - - return NS_OK; -} - NS_IMETHODIMP nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, JSObject *obj_, jsid id_, uint32_t flags, @@ -4386,12 +4294,6 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; }
- MOZ_ASSERT(*_retval == true); // guaranteed by XPC_WN_Helper_NewResolve - if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) { - *objp = obj; - return DefineComponentsShim(cx, obj); - } - nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); MOZ_ASSERT(win->IsInnerWindow());
diff --git a/js/xpconnect/tests/mochitest/Makefile.in b/js/xpconnect/tests/mochitest/Makefile.in index e3e1b63..666d1e2 100644 --- a/js/xpconnect/tests/mochitest/Makefile.in +++ b/js/xpconnect/tests/mochitest/Makefile.in @@ -80,8 +80,6 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \ file_bug781476.html \ test_bug785096.html \ test_bug789713.html \ - test_bug790732.html \ - file_bug790732.html \ test_bug793969.html \ file_bug795275.html \ file_bug795275.xml \ @@ -101,6 +99,7 @@ MOCHITEST_FILES = chrome_wrappers_helper.html \ test_crosscompartment_weakmap.html \ test_asmjs.html \ file_asmjs.js \ + test_tor_bug2874.html \ $(NULL)
include $(topsrcdir)/config/rules.mk diff --git a/js/xpconnect/tests/mochitest/file_bug790732.html b/js/xpconnect/tests/mochitest/file_bug790732.html deleted file mode 100644 index 5515dfc..0000000 --- a/js/xpconnect/tests/mochitest/file_bug790732.html +++ /dev/null @@ -1,56 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<script> -function testShim() { - - // Basic stuff - ok(Components, "Components shim exists!"); - var Ci = Components.interfaces; - ok(Ci, "interfaces shim exists!"); - is(typeof Components.classes, 'undefined', "Shouldn't have a Cc"); - - // Check each interface that we shim. We start by checking specific - // constants for a couple of interfaces, and then once it's pretty clear that - // it's working as intended we just check that the objects themselves are the - // same. - is(Ci.nsIDOMFileReader.DONE, FileReader.DONE); - is(Ci.nsIXMLHttpRequest.HEADERS_RECEIVED, XMLHttpRequest.HEADERS_RECEIVED); - is(Ci.nsIDOMDOMException.DATA_CLONE_ERR, DOMException.DATA_CLONE_ERR); - is(Ci.nsIDOMNode.DOCUMENT_NODE, Node.DOCUMENT_NODE); - is(Ci.nsIDOMUserDataHandler.NODE_CLONED, UserDataHandler.NODE_CLONED); - is(Ci.nsIDOMCSSPrimitiveValue.CSS_PX, CSSPrimitiveValue.CSS_PX); - is(Ci.nsIDOMCSSRule.NAMESPACE_RULE, CSSRule.NAMESPACE_RULE); - is(Ci.nsIDOMCSSValue.CSS_PRIMITIVE_VALUE, CSSValue.CSS_PRIMITIVE_VALUE); - is(Ci.nsIDOMEvent.FOCUS, Event.FOCUS); - is(Ci.nsIDOMNSEvent.CLICK, Event.CLICK); - is(Ci.nsIDOMKeyEvent, KeyEvent); - is(Ci.nsIDOMMouseEvent, MouseEvent); - is(Ci.nsIDOMMouseScrollEvent, MouseScrollEvent); - is(Ci.nsIDOMMutationEvent, MutationEvent); - is(Ci.nsIDOMSimpleGestureEvent, SimpleGestureEvent); - is(Ci.nsIDOMUIEvent, UIEvent); - is(Ci.nsIDOMGeoPositionError, GeoPositionError); - is(Ci.nsIDOMHTMLMediaElement, HTMLMediaElement); - is(Ci.nsIDOMMediaError, MediaError); - is(Ci.nsIDOMLoadStatus, LoadStatus); - is(Ci.nsIDOMOfflineResourceList, OfflineResourceList); - is(Ci.nsIDOMRange, Range); - is(Ci.nsIDOMSVGFETurbulenceElement, SVGFETurbulenceElement); - is(Ci.nsIDOMSVGFEMorphologyElement, SVGFEMorphologyElement); - is(Ci.nsIDOMSVGFEConvolveMatrixElement, SVGFEConvolveMatrixElement); - is(Ci.nsIDOMSVGFEDisplacementMapElement, SVGFEDisplacementMapElement); - is(Ci.nsIDOMSVGLength, SVGLength); - is(Ci.nsIDOMSVGUnitTypes, SVGUnitTypes); - is(Ci.nsIDOMNodeFilter, NodeFilter); - is(Ci.nsIDOMXPathNamespace, XPathNamespace); - is(Ci.nsIDOMXPathResult, XPathResult); - is(Ci.nsIDOMXULButtonElement, XULButtonElement); - is(Ci.nsIDOMXULCheckboxElement, XULCheckboxElement); - is(Ci.nsIDOMXULPopupElement, XULPopupElement); -} -</script> -</head> -<body> -</body> -</html> diff --git a/js/xpconnect/tests/mochitest/test_bug790732.html b/js/xpconnect/tests/mochitest/test_bug790732.html deleted file mode 100644 index 771950e..0000000 --- a/js/xpconnect/tests/mochitest/test_bug790732.html +++ /dev/null @@ -1,46 +0,0 @@ -<!DOCTYPE HTML> -<html> -<!-- -https://bugzilla.mozilla.org/show_bug.cgi?id=790732 ---> -<head> - <meta charset="utf-8"> - <title>Test for Bug 790732</title> - <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> - <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> - <script type="application/javascript"> - - /** Test for the Components shim. We split into two files because this stuff - is currently pref-controlled. **/ - SimpleTest.waitForExplicitFinish(); - - function prepare() { - SpecialPowers.pushPrefEnv({set: [['dom.omit_components_in_content', true]]}, - function () { $('ifr').onload = go; - $('ifr').contentWindow.location = - '/tests/js/xpconnect/tests/mochitest/file_bug790732.html'; } - ); - } - - function go() { - ok(true, "Started test"); - var iwin = $('ifr').contentWindow; - iwin.ok = ok; - iwin.is = is; - iwin.testShim(); - SimpleTest.finish(); - } - - </script> -</head> -<body onload="prepare()"> -<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=790732">Mozilla Bug 790732</a> -<p id="display"></p> -<div id="content" style="display: none"> - -</div> -<pre id="test"> -</pre> -<iframe id="ifr"></iframe> -</body> -</html> diff --git a/js/xpconnect/tests/mochitest/test_tor_bug2874.html b/js/xpconnect/tests/mochitest/test_tor_bug2874.html new file mode 100644 index 0000000..c0a956e --- /dev/null +++ b/js/xpconnect/tests/mochitest/test_tor_bug2874.html @@ -0,0 +1,25 @@ +<!DOCTYPE HTML> +<html> +<!-- +Tor bug +https://trac.torproject.org/projects/tor/ticket/2874 +--> +<head> + <meta charset="utf-8"> + <title>Test for Tor Bug 2874</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> + <script type="application/javascript"> + is(typeof Components, 'undefined', "The global window object should not expose a Components property to untrusted content."); + </script> +</head> +<body> +<a target="_blank" href="https://trac.torproject.org/projects/tor/ticket/2874">Tor Bug 2874</a> +<p id="display"></p> +<div id="content" style="display: none"> + +</div> +<pre id="test"> +</pre> +</body> +</html> diff --git a/toolkit/components/telemetry/Histograms.json b/toolkit/components/telemetry/Histograms.json index 9698fac..5594e01 100644 --- a/toolkit/components/telemetry/Histograms.json +++ b/toolkit/components/telemetry/Histograms.json @@ -2955,10 +2955,6 @@ "kind": "flag", "description": "Whether content ever accesed Components.interfaces in this session" }, - "COMPONENTS_SHIM_ACCESSED_BY_CONTENT": { - "kind": "flag", - "description": "Whether content ever accesed the Components shim in this session" - }, "CHECK_ADDONS_MODIFIED_MS": { "kind": "exponential", "high": "5000",