Bug 1481467 part 2 - Use JSAutoRealm instead of JSAutoRealmAllowCCW in JSXrayTraits::getOwnPropertyFromTargetIfSafe. r=bz

Because getOwnPropertyFromTargetIfSafe operates in the Xray target realm/compartment and we cannot use the Xray wrapper with JSAutoRealm, we pass the caller's global as wrapperGlobal and use that.
This commit is contained in:
Jan de Mooij 2018-08-08 15:12:16 +02:00
Родитель 21af7a61b0
Коммит 48b99bc1f0
2 изменённых файлов: 24 добавлений и 9 удалений

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

@ -277,10 +277,11 @@ bool JSXrayTraits::getOwnPropertyFromWrapperIfSafe(JSContext* cx,
{ {
MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx)); MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
RootedObject target(cx, getTargetObject(wrapper)); RootedObject target(cx, getTargetObject(wrapper));
RootedObject wrapperGlobal(cx, JS::CurrentGlobalOrNull(cx));
{ {
JSAutoRealm ar(cx, target); JSAutoRealm ar(cx, target);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, outDesc)) if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, wrapperGlobal, id, outDesc))
return false; return false;
} }
return JS_WrapPropertyDescriptor(cx, outDesc); return JS_WrapPropertyDescriptor(cx, outDesc);
@ -289,6 +290,7 @@ bool JSXrayTraits::getOwnPropertyFromWrapperIfSafe(JSContext* cx,
bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx, bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
HandleObject target, HandleObject target,
HandleObject wrapper, HandleObject wrapper,
HandleObject wrapperGlobal,
HandleId id, HandleId id,
MutableHandle<PropertyDescriptor> outDesc) MutableHandle<PropertyDescriptor> outDesc)
{ {
@ -297,6 +299,8 @@ bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
MOZ_ASSERT(getTargetObject(wrapper) == target); MOZ_ASSERT(getTargetObject(wrapper) == target);
MOZ_ASSERT(js::IsObjectInContextCompartment(target, cx)); MOZ_ASSERT(js::IsObjectInContextCompartment(target, cx));
MOZ_ASSERT(WrapperFactory::IsXrayWrapper(wrapper)); MOZ_ASSERT(WrapperFactory::IsXrayWrapper(wrapper));
MOZ_ASSERT(JS_IsGlobalObject(wrapperGlobal));
js::AssertSameCompartment(wrapper, wrapperGlobal);
MOZ_ASSERT(outDesc.object() == nullptr); MOZ_ASSERT(outDesc.object() == nullptr);
Rooted<PropertyDescriptor> desc(cx); Rooted<PropertyDescriptor> desc(cx);
@ -309,7 +313,7 @@ bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
// Disallow accessor properties. // Disallow accessor properties.
if (desc.hasGetterOrSetter()) { if (desc.hasGetterOrSetter()) {
JSAutoRealmAllowCCW ar(cx, wrapper); JSAutoRealm ar(cx, wrapperGlobal);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
return ReportWrapperDenial(cx, id, WrapperDenialForXray, "property has accessor"); return ReportWrapperDenial(cx, id, WrapperDenialForXray, "property has accessor");
} }
@ -321,7 +325,7 @@ bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
// Disallow non-subsumed objects. // Disallow non-subsumed objects.
if (!AccessCheck::subsumes(target, propObj)) { if (!AccessCheck::subsumes(target, propObj)) {
JSAutoRealmAllowCCW ar(cx, wrapper); JSAutoRealm ar(cx, wrapperGlobal);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not same-origin with target"); return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not same-origin with target");
} }
@ -329,14 +333,14 @@ bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
// Disallow non-Xrayable objects. // Disallow non-Xrayable objects.
XrayType xrayType = GetXrayType(propObj); XrayType xrayType = GetXrayType(propObj);
if (xrayType == NotXray || xrayType == XrayForOpaqueObject) { if (xrayType == NotXray || xrayType == XrayForOpaqueObject) {
JSAutoRealmAllowCCW ar(cx, wrapper); JSAutoRealm ar(cx, wrapperGlobal);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not Xrayable"); return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value not Xrayable");
} }
// Disallow callables. // Disallow callables.
if (JS::IsCallable(propObj)) { if (JS::IsCallable(propObj)) {
JSAutoRealmAllowCCW ar(cx, wrapper); JSAutoRealm ar(cx, wrapperGlobal);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value is callable"); return ReportWrapperDenial(cx, id, WrapperDenialForXray, "value is callable");
} }
@ -344,7 +348,7 @@ bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext* cx,
// Disallow any property that shadows something on its (Xrayed) // Disallow any property that shadows something on its (Xrayed)
// prototype chain. // prototype chain.
JSAutoRealmAllowCCW ar2(cx, wrapper); JSAutoRealm ar2(cx, wrapperGlobal);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
RootedObject proto(cx); RootedObject proto(cx);
bool foundOnProto = false; bool foundOnProto = false;
@ -659,6 +663,8 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, HandleObject wrapper,
bool bool
JSXrayTraits::delete_(JSContext* cx, HandleObject wrapper, HandleId id, ObjectOpResult& result) JSXrayTraits::delete_(JSContext* cx, HandleObject wrapper, HandleId id, ObjectOpResult& result)
{ {
MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
RootedObject holder(cx, ensureHolder(cx, wrapper)); RootedObject holder(cx, ensureHolder(cx, wrapper));
if (!holder) if (!holder)
return false; return false;
@ -670,11 +676,12 @@ JSXrayTraits::delete_(JSContext* cx, HandleObject wrapper, HandleId id, ObjectOp
bool isObjectOrArrayInstance = (key == JSProto_Object || key == JSProto_Array) && bool isObjectOrArrayInstance = (key == JSProto_Object || key == JSProto_Array) &&
!isPrototype(holder); !isPrototype(holder);
if (isObjectOrArrayInstance) { if (isObjectOrArrayInstance) {
RootedObject wrapperGlobal(cx, JS::CurrentGlobalOrNull(cx));
RootedObject target(cx, getTargetObject(wrapper)); RootedObject target(cx, getTargetObject(wrapper));
JSAutoRealm ar(cx, target); JSAutoRealm ar(cx, target);
JS_MarkCrossZoneId(cx, id); JS_MarkCrossZoneId(cx, id);
Rooted<PropertyDescriptor> desc(cx); Rooted<PropertyDescriptor> desc(cx);
if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, &desc)) if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, wrapperGlobal, id, &desc))
return false; return false;
if (desc.object()) if (desc.object())
return JS_DeletePropertyById(cx, target, id, result); return JS_DeletePropertyById(cx, target, id, result);
@ -799,6 +806,8 @@ bool
JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags, JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags,
AutoIdVector& props) AutoIdVector& props)
{ {
MOZ_ASSERT(js::IsObjectInContextCompartment(wrapper, cx));
RootedObject target(cx, getTargetObject(wrapper)); RootedObject target(cx, getTargetObject(wrapper));
RootedObject holder(cx, ensureHolder(cx, wrapper)); RootedObject holder(cx, ensureHolder(cx, wrapper));
if (!holder) if (!holder)
@ -810,6 +819,7 @@ JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags
// object, but only after filtering them carefully. // object, but only after filtering them carefully.
if (key == JSProto_Object || key == JSProto_Array) { if (key == JSProto_Object || key == JSProto_Array) {
MOZ_ASSERT(props.empty()); MOZ_ASSERT(props.empty());
RootedObject wrapperGlobal(cx, JS::CurrentGlobalOrNull(cx));
{ {
JSAutoRealm ar(cx, target); JSAutoRealm ar(cx, target);
AutoIdVector targetProps(cx); AutoIdVector targetProps(cx);
@ -822,8 +832,11 @@ JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags
for (size_t i = 0; i < targetProps.length(); ++i) { for (size_t i = 0; i < targetProps.length(); ++i) {
Rooted<PropertyDescriptor> desc(cx); Rooted<PropertyDescriptor> desc(cx);
RootedId id(cx, targetProps[i]); RootedId id(cx, targetProps[i]);
if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, &desc)) if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, wrapperGlobal, id,
&desc))
{
return false; return false;
}
if (desc.object()) if (desc.object())
props.infallibleAppend(id); props.infallibleAppend(id);
} }

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

@ -267,10 +267,12 @@ public:
JS::HandleId id, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc); JS::MutableHandle<JS::PropertyDescriptor> desc);
// Like the above, but operates in the target compartment. // Like the above, but operates in the target compartment. wrapperGlobal is
// the caller's global (must be in the wrapper compartment).
static bool getOwnPropertyFromTargetIfSafe(JSContext* cx, static bool getOwnPropertyFromTargetIfSafe(JSContext* cx,
JS::HandleObject target, JS::HandleObject target,
JS::HandleObject wrapper, JS::HandleObject wrapper,
JS::HandleObject wrapperGlobal,
JS::HandleId id, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc); JS::MutableHandle<JS::PropertyDescriptor> desc);