Bug 629227 - ObjectIsNativeWrapper lies for document.domain. a=blocker

This commit is contained in:
Blake Kaplan 2011-02-16 20:29:14 -08:00
Родитель cd71f1272a
Коммит 6cd196e2d6
6 изменённых файлов: 133 добавлений и 136 удалений

Просмотреть файл

@ -514,7 +514,6 @@ static const char kDOMStringBundleURL[] =
nsIXPCScriptable::WANT_SETPROPERTY | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_ADDPROPERTY | \
nsIXPCScriptable::WANT_DELPROPERTY | \
nsIXPCScriptable::WANT_FINALIZE | \
nsIXPCScriptable::WANT_EQUALITY | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
@ -1947,7 +1946,8 @@ nsDOMClassInfo::ThrowJSException(JSContext *cx, nsresult aResult)
PRBool
nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj)
{
return xpc::WrapperFactory::IsXrayWrapper(obj);
return xpc::WrapperFactory::IsXrayWrapper(obj) &&
!xpc::WrapperFactory::IsPartiallyTransparent(obj);
}
nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData)
@ -5292,35 +5292,6 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
#endif
JSObject *realObj;
wrapper->GetJSObject(&realObj);
if (win->IsOuterWindow() && realObj == obj) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
JSObject *innerObj;
if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) {
#ifdef DEBUG_SH_FORWARDING
printf(" --- Forwarding get to inner window %p\n", (void *)innerWin);
#endif
// Forward the get to the inner object
if (JSID_IS_STRING(id)) {
*_retval = ::JS_GetPropertyById(cx, innerObj, id, vp);
} else if (JSID_IS_INT(id)) {
*_retval = ::JS_GetElement(cx, innerObj, JSID_TO_INT(id), vp);
} else {
NS_ERROR("Write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
}
// The order in which things are done in this method are a bit
// whacky, that's because this method is *extremely* performace
// critical. Don't touch this unless you know what you're doing.
@ -5412,53 +5383,6 @@ NS_IMETHODIMP
nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
{
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
#ifdef DEBUG_SH_FORWARDING
{
nsDependentJSString str(::JS_ValueToString(cx, id));
if (win->IsInnerWindow()) {
#ifdef DEBUG_PRINT_INNER
printf("Property '%s' set on inner window %p\n",
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
#endif
} else {
printf("Property '%s' set on outer window %p\n",
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
}
}
#endif
JSObject *realObj;
wrapper->GetJSObject(&realObj);
if (win->IsOuterWindow() && obj == realObj) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
JSObject *innerObj;
if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) {
#ifdef DEBUG_SH_FORWARDING
printf(" --- Forwarding set to inner window %p\n", (void *)innerWin);
#endif
// Forward the set to the inner object
if (JSID_IS_STRING(id)) {
*_retval = ::JS_SetPropertyById(cx, innerObj, id, vp);
} else if (JSID_IS_INT(id)) {
*_retval = ::JS_SetElement(cx, innerObj, JSID_TO_INT(id), vp);
} else {
NS_ERROR("Write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
return NS_OK;
}
}
if (id == sLocation_id) {
JSAutoRequest ar(cx);
@ -5488,50 +5412,6 @@ nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return nsEventReceiverSH::SetProperty(wrapper, cx, obj, id, vp, _retval);
}
NS_IMETHODIMP
nsWindowSH::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
{
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
#ifdef DEBUG_SH_FORWARDING
{
nsDependentJSString str(::JS_ValueToString(cx, id));
if (win->IsInnerWindow()) {
#ifdef DEBUG_PRINT_INNER
printf("Property '%s' del on inner window %p\n",
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
#endif
} else {
printf("Property '%s' del on outer window %p\n",
NS_ConvertUTF16toUTF8(str).get(), (void *)win);
}
}
#endif
if (win->IsOuterWindow() && !ObjectIsNativeWrapper(cx, obj)) {
// XXXjst: Do security checks here when we remove the security
// checks on the inner window.
nsGlobalWindow *innerWin = win->GetCurrentInnerWindowInternal();
JSObject *innerObj;
if (innerWin && (innerObj = innerWin->GetGlobalJSObject())) {
#ifdef DEBUG_SH_FORWARDING
printf(" --- Forwarding del to inner window %p\n", (void *)innerWin);
#endif
// Forward the del to the inner object
*_retval = JS_DeletePropertyById(cx, innerObj, id);
return NS_OK;
}
}
return NS_OK;
}
static const char*
FindConstructorContractID(const nsDOMClassInfoData *aDOMClassInfoData)
{
@ -6692,7 +6572,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSBool ok = JS_TRUE;
jsval exn = JSVAL_VOID;
if (win->IsInnerWindow()) {
if (!ObjectIsNativeWrapper(cx, obj)) {
JSAutoEnterCompartment ac;
if (!my_context) {
@ -6709,14 +6589,9 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSAutoRequest transfer(my_cx);
JSObject *realObj;
wrapper->GetJSObject(&realObj);
// Don't resolve standard classes on XPCNativeWrapper etc, only
// resolve them if we're resolving on the real global object.
ok = obj == realObj ?
::JS_ResolveStandardClass(my_cx, obj, id, &did_resolve) :
JS_TRUE;
ok = JS_ResolveStandardClass(my_cx, obj, id, &did_resolve);
if (!ok) {
// Trust the JS engine (or the script security manager) to set
@ -6768,8 +6643,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// method on an interface that would let us just call into the
// window code directly...
if (!xpc::WrapperFactory::IsXrayWrapper(obj) ||
xpc::WrapperFactory::IsPartiallyTransparent(obj)) {
if (!ObjectIsNativeWrapper(cx, obj)) {
nsCOMPtr<nsIDocShellTreeNode> dsn(do_QueryInterface(win->GetDocShell()));
PRInt32 count = 0;
@ -6993,7 +6867,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// property
*objp = obj;
if (ObjectIsNativeWrapper(cx, obj)) {
// NB: We need to do this for any Xray wrapper.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
// Unless our object is a native wrapper, in which case we have to
// define it ourselves.
@ -7068,8 +6943,7 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// binding a name) a new undefined property that's not already
// defined on our prototype chain. This way we can access this
// expando w/o ever getting back into XPConnect.
if ((flags & JSRESOLVE_ASSIGNING) && !(flags & JSRESOLVE_WITH) &&
win->IsInnerWindow()) {
if ((flags & JSRESOLVE_ASSIGNING) && !(flags & JSRESOLVE_WITH)) {
JSObject *realObj;
wrapper->GetJSObject(&realObj);
@ -10280,9 +10154,19 @@ nsStorageSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval)
{
if (ObjectIsNativeWrapper(cx, obj)) {
return NS_OK;
}
JSObject *realObj;
wrapper->GetJSObject(&realObj);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, realObj)) {
*_retval = PR_FALSE;
return NS_ERROR_FAILURE;
}
// First check to see if the property is defined on our prototype.
JSObject *proto = ::JS_GetPrototype(cx, realObj);
@ -10450,9 +10334,19 @@ nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval)
{
if (ObjectIsNativeWrapper(cx, obj)) {
return NS_OK;
}
JSObject *realObj;
wrapper->GetJSObject(&realObj);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, realObj)) {
*_retval = PR_FALSE;
return NS_ERROR_FAILURE;
}
// First check to see if the property is defined on our prototype,
// after converting id to a string if it's an integer.

Просмотреть файл

@ -177,6 +177,17 @@ public:
static nsresult ThrowJSException(JSContext *cx, nsresult aResult);
/*
* The following two functions exist because of the way that Xray wrappers
* work. In order to allow scriptable helpers to define non-IDL defined but
* still "safe" properties for Xray wrappers, we call into the scriptable
* helper with |obj| being the wrapper.
*
* Ideally, that would be the end of the story, however due to complications
* dealing with document.domain, it's possible to end up in a scriptable
* helper with a wrapper, even though we should be treating the lookup as a
* transparent one.
*/
static PRBool ObjectIsNativeWrapper(JSContext* cx, JSObject* obj);
static nsISupports *GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj);
@ -541,8 +552,6 @@ public:
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
JSObject **objp, PRBool *_retval);

Просмотреть файл

@ -80,6 +80,9 @@ _TEST_FILES = bug500931_helper.html \
test_bug605167.html \
test_bug623437.html \
test_bug601299.html \
test_bug629227.html \
file1_bug629227.html \
file2_bug629227.html \
test_bug629331.html \
test1_bug629331.html \
test2_bug629331.html \

Просмотреть файл

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<script>
function doIt() {
var doc = window.frames[0].document;
var ok = (doc.form1 == doc.getElementById("test1"));
window.parent.postMessage(
JSON.stringify({ ok: ok,
reason: "Should be able to get named items by name" }),
"*");
window.parent.postMessage("finish", "*");
}
window.onmessage = function(ev) {
if (ev.data == "start") {
doIt();
}
}
document.domain = "example.org";
</script>
</head>
<body>
<iframe id="subframe"></iframe>
<script>
document.getElementById("subframe").src =
"http://test2.example.org" +
location.pathname.replace(/file1_bug629227.html/, "file2_bug629227.html");
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<script>
document.domain = "example.org";
</script>
</head>
<body>
<form name="form1" id="test1"></form>
</body>
</html>

Просмотреть файл

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=629227
-->
<head>
<title>Test for Bug 629227</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629227">Mozilla Bug 629227</a>
<p id="display">
<iframe id="testTarget"></iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 629227 **/
SimpleTest.waitForExplicitFinish();
$("testTarget").src =
"http://test1.example.org" +
location.pathname.replace(/test_bug629227.html/, "file1_bug629227.html");
window.onmessage = function(ev) {
if (ev.data == "finish") {
SimpleTest.finish();
} else {
var data = JSON.parse(ev.data);
if ("ok" in data) {
ok(data.ok, data.reason);
}
}
}
addLoadEvent(function() {
$("testTarget").contentWindow.postMessage("start", "*");
});
</script>
</pre>
</body>
</html>