mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 723111 - Add an option to js::UnwrapObject so that it doesn't stop at outer windows when unwrapping. This is useful for cases where we are trying to find the wrapped native for a security wrapper. r=bzbarsky
This commit is contained in:
parent
3c8ca91d37
commit
2718588789
@ -216,7 +216,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
|
||||
|
||||
/* Don't unwrap an outer window proxy. */
|
||||
if (!obj->getClass()->ext.innerObject) {
|
||||
obj = UnwrapObject(&vp->toObject(), &flags);
|
||||
obj = UnwrapObject(&vp->toObject(), true, &flags);
|
||||
vp->setObject(*obj);
|
||||
if (obj->compartment() == this)
|
||||
return true;
|
||||
|
@ -76,13 +76,13 @@ js::IsWrapper(const JSObject *wrapper)
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
js::UnwrapObject(JSObject *wrapped, uintN *flagsp)
|
||||
js::UnwrapObject(JSObject *wrapped, bool stopAtOuter, uintN *flagsp)
|
||||
{
|
||||
uintN flags = 0;
|
||||
while (wrapped->isWrapper()) {
|
||||
flags |= static_cast<Wrapper *>(GetProxyHandler(wrapped))->flags();
|
||||
wrapped = GetProxyPrivate(wrapped).toObjectOrNull();
|
||||
if (wrapped->getClass()->ext.innerObject)
|
||||
if (stopAtOuter && wrapped->getClass()->ext.innerObject)
|
||||
break;
|
||||
}
|
||||
if (flagsp)
|
||||
|
@ -206,7 +206,14 @@ TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, J
|
||||
uintN flags);
|
||||
|
||||
JS_FRIEND_API(bool) IsWrapper(const JSObject *obj);
|
||||
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, uintN *flagsp = NULL);
|
||||
|
||||
// Given a JSObject, returns that object stripped of wrappers. If
|
||||
// stopAtOuter is true, then this returns the outer window if it was
|
||||
// previously wrapped. Otherwise, this returns the first object for
|
||||
// which JSObject::isWrapper returns false.
|
||||
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true,
|
||||
uintN *flagsp = NULL);
|
||||
|
||||
bool IsCrossCompartmentWrapper(const JSObject *obj);
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -3046,7 +3046,7 @@ EvalInContext(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSAutoEnterCompartment ac;
|
||||
uintN flags;
|
||||
JSObject *unwrapped = UnwrapObject(sobj, &flags);
|
||||
JSObject *unwrapped = UnwrapObject(sobj, true, &flags);
|
||||
if (flags & Wrapper::CROSS_COMPARTMENT) {
|
||||
sobj = unwrapped;
|
||||
if (!ac.enter(cx, sobj))
|
||||
|
@ -1220,7 +1220,7 @@ XPCConvert::JSObject2NativeInterface(XPCCallContext& ccx,
|
||||
// we aren't, throw an exception eagerly.
|
||||
JSObject* inner = nsnull;
|
||||
if (XPCWrapper::IsSecurityWrapper(src)) {
|
||||
inner = XPCWrapper::Unwrap(cx, src);
|
||||
inner = XPCWrapper::Unwrap(cx, src, false);
|
||||
if (!inner) {
|
||||
if (pErr)
|
||||
*pErr = NS_ERROR_XPC_SECURITY_MANAGER_VETO;
|
||||
|
@ -788,7 +788,7 @@ getWrapper(JSContext *cx,
|
||||
XPCWrappedNativeTearOff **tearoff)
|
||||
{
|
||||
if (XPCWrapper::IsSecurityWrapper(obj) &&
|
||||
!(obj = XPCWrapper::Unwrap(cx, obj))) {
|
||||
!(obj = XPCWrapper::Unwrap(cx, obj, false))) {
|
||||
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
|
||||
}
|
||||
|
||||
|
@ -123,12 +123,12 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject)
|
||||
namespace XPCWrapper {
|
||||
|
||||
JSObject *
|
||||
Unwrap(JSContext *cx, JSObject *wrapper)
|
||||
Unwrap(JSContext *cx, JSObject *wrapper, bool stopAtOuter)
|
||||
{
|
||||
if (js::IsWrapper(wrapper)) {
|
||||
if (xpc::AccessCheck::isScriptAccessOnly(cx, wrapper))
|
||||
return nsnull;
|
||||
return js::UnwrapObject(wrapper);
|
||||
return js::UnwrapObject(wrapper, stopAtOuter);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
|
@ -93,7 +93,7 @@ IsSecurityWrapper(JSObject *wrapper)
|
||||
* exception on |cx|.
|
||||
*/
|
||||
JSObject *
|
||||
Unwrap(JSContext *cx, JSObject *wrapper);
|
||||
Unwrap(JSContext *cx, JSObject *wrapper, bool stopAtOuter = true);
|
||||
|
||||
JSObject *
|
||||
UnsafeUnwrapSecurityWrapper(JSObject *obj);
|
||||
|
@ -90,12 +90,22 @@ AccessCheck::isSameOrigin(JSCompartment *a, JSCompartment *b)
|
||||
bool
|
||||
AccessCheck::isLocationObjectSameOrigin(JSContext *cx, JSObject *wrapper)
|
||||
{
|
||||
// Location objects are parented to the outer window for which they
|
||||
// were created. This gives us an easy way to determine whether our
|
||||
// object is same origin with the current inner window:
|
||||
|
||||
// Grab the outer window...
|
||||
JSObject *obj = js::GetObjectParent(js::UnwrapObject(wrapper));
|
||||
if (!js::GetObjectClass(obj)->ext.innerObject) {
|
||||
// ...which might be wrapped in a security wrapper.
|
||||
obj = js::UnwrapObject(obj);
|
||||
JS_ASSERT(js::GetObjectClass(obj)->ext.innerObject);
|
||||
}
|
||||
|
||||
// Now innerize it to find the *current* inner window for our outer.
|
||||
obj = JS_ObjectToInnerObject(cx, obj);
|
||||
|
||||
// Which lets us compare the current compartment against the old one.
|
||||
return obj &&
|
||||
(isSameOrigin(js::GetObjectCompartment(wrapper),
|
||||
js::GetObjectCompartment(obj)) ||
|
||||
@ -384,7 +394,7 @@ AccessCheck::isScriptAccessOnly(JSContext *cx, JSObject *wrapper)
|
||||
JS_ASSERT(js::IsWrapper(wrapper));
|
||||
|
||||
uintN flags;
|
||||
JSObject *obj = js::UnwrapObject(wrapper, &flags);
|
||||
JSObject *obj = js::UnwrapObject(wrapper, true, &flags);
|
||||
|
||||
// If the wrapper indicates script-only access, we are done.
|
||||
if (flags & WrapperFactory::SCRIPT_ACCESS_ONLY_FLAG) {
|
||||
|
@ -53,7 +53,7 @@ class WrapperFactory {
|
||||
// Return true if any of any of the nested wrappers have the flag set.
|
||||
static bool HasWrapperFlag(JSObject *wrapper, uintN flag) {
|
||||
uintN flags = 0;
|
||||
js::UnwrapObject(wrapper, &flags);
|
||||
js::UnwrapObject(wrapper, true, &flags);
|
||||
return !!(flags & flag);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user