diff --git a/js/xpconnect/wrappers/AccessCheck.h b/js/xpconnect/wrappers/AccessCheck.h index 9afd8dbd78a1..84ee1177cad5 100644 --- a/js/xpconnect/wrappers/AccessCheck.h +++ b/js/xpconnect/wrappers/AccessCheck.h @@ -35,6 +35,7 @@ enum CrossOriginObjectType { CrossOriginObjectType IdentifyCrossOriginObject(JSObject *obj); struct Policy { + static const bool AllowGetPrototypeOf = false; }; // This policy allows no interaction with the underlying callable. Everything throws. @@ -83,6 +84,12 @@ struct CrossOriginAccessiblePropertiesOnly : public Policy { // This policy only permits access to properties if they appear in the // objects exposed properties list. struct ExposedPropertiesOnly : public Policy { + + // COWs are the only type of filtering wrapper that allow access to the + // prototype, because the standard prototypes are remapped into the + // wrapper's compartment. + static const bool AllowGetPrototypeOf = true; + static bool check(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, js::Wrapper::Action act); static bool deny(js::Wrapper::Action act, JS::HandleId id); diff --git a/js/xpconnect/wrappers/FilteringWrapper.cpp b/js/xpconnect/wrappers/FilteringWrapper.cpp index a40572fb56f9..272e370b90f9 100644 --- a/js/xpconnect/wrappers/FilteringWrapper.cpp +++ b/js/xpconnect/wrappers/FilteringWrapper.cpp @@ -152,6 +152,20 @@ FilteringWrapper::defaultValue(JSContext *cx, HandleObject obj, return Base::defaultValue(cx, obj, hint, vp); } +template +bool +FilteringWrapper::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, + JS::MutableHandleObject protop) const +{ + // If the policy explicitly allows access to the prototype, bounce to the base. + if (Policy::AllowGetPrototypeOf) + return Base::getPrototypeOf(cx, wrapper, protop); + + // In general, filtering wrappers do not allow access to the prototype. + protop.set(nullptr); + return true; +} + template bool FilteringWrapper::enter(JSContext *cx, HandleObject wrapper, @@ -201,15 +215,6 @@ CrossOriginXrayWrapper::getOwnPropertyDescriptor(JSContext *cx, return getPropertyDescriptor(cx, wrapper, id, desc); } -bool -CrossOriginXrayWrapper::getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, - JS::MutableHandleObject protop) const -{ - // Cross-origin objects have null prototypes. - protop.set(nullptr); - return true; -} - bool CrossOriginXrayWrapper::ownPropertyKeys(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const diff --git a/js/xpconnect/wrappers/FilteringWrapper.h b/js/xpconnect/wrappers/FilteringWrapper.h index c6910e3b8d59..021252f69499 100644 --- a/js/xpconnect/wrappers/FilteringWrapper.h +++ b/js/xpconnect/wrappers/FilteringWrapper.h @@ -49,6 +49,9 @@ class FilteringWrapper : public Base { virtual bool defaultValue(JSContext *cx, JS::Handle obj, JSType hint, JS::MutableHandleValue vp) const MOZ_OVERRIDE; + virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, + JS::MutableHandleObject protop) const MOZ_OVERRIDE; + static const FilteringWrapper singleton; }; @@ -73,8 +76,6 @@ class CrossOriginXrayWrapper : public SecurityXrayDOM { JS::Handle id, bool *bp) const MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, JS::Handle wrapper, JS::AutoIdVector &props) const MOZ_OVERRIDE; - virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper, - JS::MutableHandleObject protop) const MOZ_OVERRIDE; virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle wrapper, JS::Handle id,