mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 965901 - Track and assert the policy action in AutoEnterPolicy/assertEnteredPolicy. r=gabor sr=mrbkap
This commit is contained in:
parent
9ab1f93eca
commit
66cc972e63
@ -1991,13 +1991,6 @@ class JS_FRIEND_API(AutoCTypesActivityCallback) {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
extern JS_FRIEND_API(void)
|
||||
assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id);
|
||||
#else
|
||||
inline void assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id) {};
|
||||
#endif
|
||||
|
||||
typedef bool
|
||||
(* ObjectMetadataCallback)(JSContext *cx, JSObject **pmetadata);
|
||||
|
||||
|
@ -46,12 +46,13 @@ js::AutoEnterPolicy::reportErrorIfExceptionIsNotPending(JSContext *cx, jsid id)
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
js::AutoEnterPolicy::recordEnter(JSContext *cx, HandleObject proxy, HandleId id)
|
||||
js::AutoEnterPolicy::recordEnter(JSContext *cx, HandleObject proxy, HandleId id, Action act)
|
||||
{
|
||||
if (allowed()) {
|
||||
context = cx;
|
||||
enteredProxy.construct(proxy);
|
||||
enteredId.construct(id);
|
||||
enteredAction = act;
|
||||
prev = cx->runtime()->enteredPolicy;
|
||||
cx->runtime()->enteredPolicy = this;
|
||||
}
|
||||
@ -67,12 +68,14 @@ js::AutoEnterPolicy::recordLeave()
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id)
|
||||
js::assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id,
|
||||
BaseProxyHandler::Action act)
|
||||
{
|
||||
MOZ_ASSERT(proxy->is<ProxyObject>());
|
||||
MOZ_ASSERT(cx->runtime()->enteredPolicy);
|
||||
MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredProxy.ref().get() == proxy);
|
||||
MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredId.ref().get() == id);
|
||||
MOZ_ASSERT(cx->runtime()->enteredPolicy->enteredAction & act);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -98,7 +101,7 @@ BaseProxyHandler::enter(JSContext *cx, HandleObject wrapper, HandleId id, Action
|
||||
bool
|
||||
BaseProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!getPropertyDescriptor(cx, proxy, id, &desc, 0))
|
||||
return false;
|
||||
@ -109,7 +112,9 @@ BaseProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
bool
|
||||
BaseProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
// Note: Proxy::set needs to invoke hasOwn to determine where the setter
|
||||
// lives, so we allow SET operations to invoke us.
|
||||
assertEnteredPolicy(cx, proxy, id, GET | SET);
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!getOwnPropertyDescriptor(cx, proxy, id, &desc, 0))
|
||||
return false;
|
||||
@ -121,7 +126,7 @@ bool
|
||||
BaseProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!getPropertyDescriptor(cx, proxy, id, &desc, 0))
|
||||
@ -155,7 +160,7 @@ bool
|
||||
BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!getOwnPropertyDescriptor(cx, proxy, id, &desc, JSRESOLVE_ASSIGNING))
|
||||
@ -226,7 +231,7 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
bool
|
||||
BaseProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
JS_ASSERT(props.length() == 0);
|
||||
|
||||
if (!getOwnPropertyNames(cx, proxy, props))
|
||||
@ -239,7 +244,7 @@ BaseProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
for (size_t j = 0, len = props.length(); j < len; j++) {
|
||||
JS_ASSERT(i <= j);
|
||||
id = props[j];
|
||||
AutoWaivePolicy policy(cx, proxy, id);
|
||||
AutoWaivePolicy policy(cx, proxy, id, BaseProxyHandler::GET);
|
||||
if (!getOwnPropertyDescriptor(cx, proxy, id, &desc, 0))
|
||||
return false;
|
||||
if (desc.object() && desc.isEnumerable())
|
||||
@ -255,7 +260,7 @@ BaseProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
bool
|
||||
BaseProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
|
||||
AutoIdVector props(cx);
|
||||
if ((flags & JSITER_OWNONLY)
|
||||
@ -319,7 +324,7 @@ BaseProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl im
|
||||
bool
|
||||
BaseProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
RootedValue val(cx, ObjectValue(*proxy.get()));
|
||||
js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS,
|
||||
JSDVG_SEARCH_STACK, val, NullPtr());
|
||||
@ -378,7 +383,7 @@ bool
|
||||
BaseProxyHandler::slice(JSContext *cx, HandleObject proxy, uint32_t begin, uint32_t end,
|
||||
HandleObject result)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
|
||||
return js::SliceSlowly(cx, proxy, proxy, begin, end, result);
|
||||
}
|
||||
@ -387,7 +392,7 @@ bool
|
||||
DirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc, unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET | SET);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JS_GetPropertyDescriptorById(cx, target, id, 0, desc);
|
||||
@ -414,7 +419,7 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
|
||||
HandleId id, MutableHandle<PropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET | SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetOwnPropertyDescriptor(cx, target, id, 0, desc);
|
||||
}
|
||||
@ -423,7 +428,7 @@ bool
|
||||
DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
MutableHandle<PropertyDescriptor> desc)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
RootedValue v(cx, desc.value());
|
||||
return CheckDefineProperty(cx, target, id, v, desc.getter(), desc.setter(), desc.attributes()) &&
|
||||
@ -434,7 +439,7 @@ bool
|
||||
DirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetPropertyNames(cx, target, JSITER_OWNONLY | JSITER_HIDDEN, &props);
|
||||
}
|
||||
@ -442,7 +447,7 @@ DirectProxyHandler::getOwnPropertyNames(JSContext *cx, HandleObject proxy,
|
||||
bool
|
||||
DirectProxyHandler::delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JS_DeletePropertyById2(cx, target, id, bp);
|
||||
}
|
||||
@ -451,7 +456,7 @@ bool
|
||||
DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetPropertyNames(cx, target, 0, &props);
|
||||
@ -460,7 +465,7 @@ DirectProxyHandler::enumerate(JSContext *cx, HandleObject proxy,
|
||||
bool
|
||||
DirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
|
||||
RootedValue target(cx, proxy->as<ProxyObject>().private_());
|
||||
return Invoke(cx, args.thisv(), target, args.length(), args.array(), args.rval());
|
||||
}
|
||||
@ -468,7 +473,7 @@ DirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args
|
||||
bool
|
||||
DirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
|
||||
RootedValue target(cx, proxy->as<ProxyObject>().private_());
|
||||
return InvokeConstructor(cx, target, args.length(), args.array(), args.rval().address());
|
||||
}
|
||||
@ -490,7 +495,7 @@ bool
|
||||
DirectProxyHandler::hasInstance(JSContext *cx, HandleObject proxy, MutableHandleValue v,
|
||||
bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
bool b;
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
if (!HasInstance(cx, target, v, &b))
|
||||
@ -524,7 +529,7 @@ DirectProxyHandler::objectClassIs(HandleObject proxy, ESClassValue classValue,
|
||||
const char *
|
||||
DirectProxyHandler::className(JSContext *cx, HandleObject proxy)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::className(cx, target);
|
||||
}
|
||||
@ -533,7 +538,7 @@ JSString *
|
||||
DirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy,
|
||||
unsigned indent)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return fun_toStringHelper(cx, target, indent);
|
||||
}
|
||||
@ -560,7 +565,7 @@ DirectProxyHandler::DirectProxyHandler(const void *family)
|
||||
bool
|
||||
DirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
bool found;
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
@ -573,7 +578,9 @@ DirectProxyHandler::has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp
|
||||
bool
|
||||
DirectProxyHandler::hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
// Note: Proxy::set needs to invoke hasOwn to determine where the setter
|
||||
// lives, so we allow SET operations to invoke us.
|
||||
assertEnteredPolicy(cx, proxy, id, GET | SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!JS_GetPropertyDescriptorById(cx, target, id, 0, &desc))
|
||||
@ -586,7 +593,7 @@ bool
|
||||
DirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, GET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::getGeneric(cx, target, receiver, id, vp);
|
||||
}
|
||||
@ -595,7 +602,7 @@ bool
|
||||
DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, bool strict, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, id);
|
||||
assertEnteredPolicy(cx, proxy, id, SET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return JSObject::setGeneric(cx, target, receiver, id, vp, strict);
|
||||
}
|
||||
@ -603,7 +610,7 @@ DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver
|
||||
bool
|
||||
DirectProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetPropertyNames(cx, target, JSITER_OWNONLY, &props);
|
||||
}
|
||||
@ -612,7 +619,7 @@ bool
|
||||
DirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigned flags,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
JS_ASSERT(!hasPrototype()); // Should never be called if there's a prototype.
|
||||
RootedObject target(cx, proxy->as<ProxyObject>().target());
|
||||
return GetIterator(cx, target, flags, vp);
|
||||
@ -1033,7 +1040,7 @@ ScriptedIndirectProxyHandler::iterate(JSContext *cx, HandleObject proxy, unsigne
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
|
||||
RootedObject ccHolder(cx, &proxy->as<ProxyObject>().extra(0).toObject());
|
||||
JS_ASSERT(ccHolder->getClass() == &CallConstructHolder);
|
||||
RootedValue call(cx, ccHolder->getReservedSlot(0));
|
||||
@ -1044,7 +1051,7 @@ ScriptedIndirectProxyHandler::call(JSContext *cx, HandleObject proxy, const Call
|
||||
bool
|
||||
ScriptedIndirectProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, CALL);
|
||||
RootedObject ccHolder(cx, &proxy->as<ProxyObject>().extra(0).toObject());
|
||||
JS_ASSERT(ccHolder->getClass() == &CallConstructHolder);
|
||||
RootedValue construct(cx, ccHolder->getReservedSlot(1));
|
||||
@ -1063,7 +1070,7 @@ ScriptedIndirectProxyHandler::nativeCall(JSContext *cx, IsAcceptableThis test, N
|
||||
JSString *
|
||||
ScriptedIndirectProxyHandler::fun_toString(JSContext *cx, HandleObject proxy, unsigned indent)
|
||||
{
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID);
|
||||
assertEnteredPolicy(cx, proxy, JSID_VOID, GET);
|
||||
if (!proxy->isCallable()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
|
||||
JSMSG_INCOMPATIBLE_PROTO,
|
||||
|
@ -139,12 +139,18 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
* The |act| parameter to enter() specifies the action being performed.
|
||||
* If |bp| is false, the trap suggests that the caller throw (though it
|
||||
* may still decide to squelch the error).
|
||||
*
|
||||
* We make these OR-able so that assertEnteredPolicy can pass a union of them.
|
||||
* For example, get{,Own}PropertyDescriptor is invoked by both calls to ::get()
|
||||
* and ::set() (since we need to look up the accessor), so its
|
||||
* assertEnteredPolicy would pass GET | SET.
|
||||
*/
|
||||
enum Action {
|
||||
GET,
|
||||
SET,
|
||||
CALL
|
||||
};
|
||||
typedef uint32_t Action;
|
||||
static const Action VOID = 0x00;
|
||||
static const Action GET = 0x01;
|
||||
static const Action SET = 0x02;
|
||||
static const Action CALL = 0x04;
|
||||
|
||||
virtual bool enter(JSContext *cx, HandleObject wrapper, HandleId id, Action act,
|
||||
bool *bp);
|
||||
|
||||
@ -462,7 +468,7 @@ class JS_FRIEND_API(AutoEnterPolicy)
|
||||
{
|
||||
allow = handler->hasSecurityPolicy() ? handler->enter(cx, wrapper, id, act, &rv)
|
||||
: true;
|
||||
recordEnter(cx, wrapper, id);
|
||||
recordEnter(cx, wrapper, id, act);
|
||||
// We want to throw an exception if all of the following are true:
|
||||
// * The policy disallowed access.
|
||||
// * The policy set rv to false, indicating that we should throw.
|
||||
@ -481,6 +487,7 @@ class JS_FRIEND_API(AutoEnterPolicy)
|
||||
AutoEnterPolicy()
|
||||
#ifdef JS_DEBUG
|
||||
: context(nullptr)
|
||||
, enteredAction(BaseProxyHandler::VOID)
|
||||
#endif
|
||||
{};
|
||||
void reportErrorIfExceptionIsNotPending(JSContext *cx, jsid id);
|
||||
@ -491,16 +498,18 @@ class JS_FRIEND_API(AutoEnterPolicy)
|
||||
JSContext *context;
|
||||
mozilla::Maybe<HandleObject> enteredProxy;
|
||||
mozilla::Maybe<HandleId> enteredId;
|
||||
Action enteredAction;
|
||||
|
||||
// NB: We explicitly don't track the entered action here, because sometimes
|
||||
// SET traps do an implicit GET during their implementation, leading to
|
||||
// spurious assertions.
|
||||
AutoEnterPolicy *prev;
|
||||
void recordEnter(JSContext *cx, HandleObject proxy, HandleId id);
|
||||
void recordEnter(JSContext *cx, HandleObject proxy, HandleId id, Action act);
|
||||
void recordLeave();
|
||||
|
||||
friend JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id);
|
||||
friend JS_FRIEND_API(void) assertEnteredPolicy(JSContext *cx, JSObject *proxy, jsid id, Action act);
|
||||
#else
|
||||
inline void recordEnter(JSContext *cx, JSObject *proxy, jsid id) {}
|
||||
inline void recordEnter(JSContext *cx, JSObject *proxy, jsid id, Action act) {}
|
||||
inline void recordLeave() {}
|
||||
#endif
|
||||
|
||||
@ -509,18 +518,32 @@ class JS_FRIEND_API(AutoEnterPolicy)
|
||||
#ifdef JS_DEBUG
|
||||
class JS_FRIEND_API(AutoWaivePolicy) : public AutoEnterPolicy {
|
||||
public:
|
||||
AutoWaivePolicy(JSContext *cx, HandleObject proxy, HandleId id)
|
||||
AutoWaivePolicy(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
BaseProxyHandler::Action act)
|
||||
{
|
||||
allow = true;
|
||||
recordEnter(cx, proxy, id);
|
||||
recordEnter(cx, proxy, id, act);
|
||||
}
|
||||
};
|
||||
#else
|
||||
class JS_FRIEND_API(AutoWaivePolicy) {
|
||||
public: AutoWaivePolicy(JSContext *cx, HandleObject proxy, HandleId id) {};
|
||||
public:
|
||||
AutoWaivePolicy(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
BaseProxyHandler::Action act)
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef JS_DEBUG
|
||||
extern JS_FRIEND_API(void)
|
||||
assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id,
|
||||
BaseProxyHandler::Action act);
|
||||
#else
|
||||
inline void assertEnteredPolicy(JSContext *cx, JSObject *obj, jsid id,
|
||||
BaseProxyHandler::Action act)
|
||||
{};
|
||||
#endif
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
|
@ -67,7 +67,7 @@ ChromeObjectWrapper::getPropertyDescriptor(JSContext *cx,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, GET | SET);
|
||||
// First, try a lookup on the base wrapper if permitted.
|
||||
desc.object().set(nullptr);
|
||||
if (AllowedByBase(cx, wrapper, id, Wrapper::GET) &&
|
||||
@ -98,7 +98,7 @@ bool
|
||||
ChromeObjectWrapper::has(JSContext *cx, HandleObject wrapper,
|
||||
HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, GET);
|
||||
// Try the lookup on the base wrapper if permitted.
|
||||
if (AllowedByBase(cx, wrapper, id, js::Wrapper::GET) &&
|
||||
!ChromeObjectWrapperBase::has(cx, wrapper, id, bp))
|
||||
@ -127,7 +127,7 @@ ChromeObjectWrapper::get(JSContext *cx, HandleObject wrapper,
|
||||
HandleObject receiver, HandleId id,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, GET);
|
||||
vp.setUndefined();
|
||||
// Only call through to the get trap on the underlying object if we're
|
||||
// allowed to see the property, and if what we'll find is not on a standard
|
||||
@ -183,7 +183,7 @@ ChromeObjectWrapper::enter(JSContext *cx, HandleObject wrapper,
|
||||
|
||||
// Note that PropIsFromStandardPrototype needs to invoke getPropertyDescriptor
|
||||
// before we've fully entered the policy. Waive our policy.
|
||||
js::AutoWaivePolicy policy(cx, wrapper, id);
|
||||
js::AutoWaivePolicy policy(cx, wrapper, id, act);
|
||||
return PropIsFromStandardPrototype(cx, wrapper, id);
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ FilteringWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, HandleObjec
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET);
|
||||
if (!Base::getPropertyDescriptor(cx, wrapper, id, desc, flags))
|
||||
return false;
|
||||
return FilterSetter<Policy>(cx, wrapper, id, desc);
|
||||
@ -76,7 +76,7 @@ FilteringWrapper<Base, Policy>::getOwnPropertyDescriptor(JSContext *cx, HandleOb
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET);
|
||||
if (!Base::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags))
|
||||
return false;
|
||||
return FilterSetter<Policy>(cx, wrapper, id, desc);
|
||||
@ -87,7 +87,7 @@ bool
|
||||
FilteringWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
return Base::getOwnPropertyNames(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
@ -97,7 +97,7 @@ bool
|
||||
FilteringWrapper<Base, Policy>::enumerate(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
return Base::enumerate(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
@ -107,7 +107,7 @@ bool
|
||||
FilteringWrapper<Base, Policy>::keys(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
return Base::keys(cx, wrapper, props) &&
|
||||
Filter<Policy>(cx, wrapper, props);
|
||||
}
|
||||
@ -117,7 +117,7 @@ bool
|
||||
FilteringWrapper<Base, Policy>::iterate(JSContext *cx, HandleObject wrapper,
|
||||
unsigned flags, MutableHandleValue vp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
// We refuse to trigger the iterator hook across chrome wrappers because
|
||||
// we don't know how to censor custom iterator objects. Instead we trigger
|
||||
// the default proxy iterate trap, which will ask enumerate() for the list
|
||||
|
@ -30,6 +30,7 @@ using namespace JS;
|
||||
using namespace mozilla;
|
||||
|
||||
using js::Wrapper;
|
||||
using js::BaseProxyHandler;
|
||||
using js::IsCrossCompartmentWrapper;
|
||||
using js::UncheckedUnwrap;
|
||||
using js::CheckedUnwrap;
|
||||
@ -1438,7 +1439,7 @@ XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, HandleObject wra
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET);
|
||||
RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc.object().set(nullptr);
|
||||
@ -1585,7 +1586,7 @@ XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext *cx, HandleObject
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::GET | BaseProxyHandler::SET);
|
||||
RootedObject holder(cx, Traits::singleton.ensureHolder(cx, wrapper));
|
||||
if (Traits::isResolving(cx, holder, id)) {
|
||||
desc.object().set(nullptr);
|
||||
@ -1666,7 +1667,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
|
||||
HandleId id, MutableHandle<JSPropertyDescriptor> desc)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
|
||||
|
||||
// NB: We still need JSRESOLVE_ASSIGNING here for the time being, because it
|
||||
// tells things like nodelists whether they should create the property or not.
|
||||
@ -1713,7 +1714,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::getOwnPropertyNames(JSContext *cx, HandleObject wrapper,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
return enumerate(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
||||
}
|
||||
|
||||
@ -1722,7 +1723,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::delete_(JSContext *cx, HandleObject wrapper,
|
||||
HandleId id, bool *bp)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, id);
|
||||
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
|
||||
|
||||
// Check the expando object.
|
||||
RootedObject target(cx, Traits::getTargetObject(wrapper));
|
||||
@ -1740,7 +1741,7 @@ bool
|
||||
XrayWrapper<Base, Traits>::enumerate(JSContext *cx, HandleObject wrapper, unsigned flags,
|
||||
AutoIdVector &props)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::GET);
|
||||
if (!AccessCheck::wrapperSubsumes(wrapper)) {
|
||||
JS_ReportError(cx, "Not allowed to enumerate cross origin objects");
|
||||
return false;
|
||||
@ -1833,7 +1834,7 @@ template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::call(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::CALL);
|
||||
return Traits::call(cx, wrapper, args, Base::singleton);
|
||||
}
|
||||
|
||||
@ -1841,7 +1842,7 @@ template <typename Base, typename Traits>
|
||||
bool
|
||||
XrayWrapper<Base, Traits>::construct(JSContext *cx, HandleObject wrapper, const JS::CallArgs &args)
|
||||
{
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID);
|
||||
assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::CALL);
|
||||
return Traits::construct(cx, wrapper, args, Base::singleton);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user