From 63736f55610fd2b9df8421f761467d7626562ef5 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 11 Apr 2013 11:10:19 -0700 Subject: [PATCH] Bug 859957 - Simplify [[DefaultValue]] security wrapping setup. r=mrbkap,gabor,ejpbruel --- js/src/jswrapper.cpp | 46 +++++++++++++++----------------------------- js/src/jswrapper.h | 6 ++---- 2 files changed, 17 insertions(+), 35 deletions(-) diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 0c4f4b03893..c1a7e5812cd 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -126,34 +126,6 @@ Wrapper::~Wrapper() { } -/* - * Ordinarily, the convert trap would require unwrapping. However, the default - * implementation of convert, JS_ConvertStub, obtains a default value by calling - * the toString/valueOf method on the wrapper, if any. Throwing if we can't unwrap - * in this case would be overly conservative. To make matters worse, XPConnect sometimes - * installs a custom convert trap that obtains a default value by calling the - * toString method on the wrapper. Doing a puncture in this case would be overly - * conservative as well. We deal with these anomalies by falling back to the DefaultValue - * algorithm whenever unwrapping is forbidden. - */ -bool -Wrapper::defaultValue(JSContext *cx, HandleObject wrapper, JSType hint, MutableHandleValue vp) -{ - if (!wrapperHandler(wrapper)->isSafeToUnwrap()) - return DefaultValue(cx, wrapper, hint, vp); - - /* - * We enter the compartment of the wrappee here, even if we're not a cross - * compartment wrapper. Moreover, cross compartment wrappers do not enter - * the compartment of the wrappee before calling this function. This is - * necessary because the DefaultValue algorithm above operates on the - * wrapper, not the wrappee, so we want to delay the decision to switch - * compartments until this point. - */ - AutoCompartment call(cx, wrappedObject(wrapper)); - return DirectProxyHandler::defaultValue(cx, wrapper, hint, vp); -} - Wrapper Wrapper::singleton((unsigned)0); Wrapper Wrapper::singletonWithPrototype((unsigned)0, true); @@ -608,9 +580,10 @@ bool CrossCompartmentWrapper::defaultValue(JSContext *cx, HandleObject wrapper, JSType hint, MutableHandleValue vp) { - if (!Wrapper::defaultValue(cx, wrapper, hint, vp)) - return false; - return cx->compartment->wrap(cx, vp); + PIERCE(cx, wrapper, + NOTHING, + Wrapper::defaultValue(cx, wrapper, hint, vp), + cx->compartment->wrap(cx, vp)); } bool @@ -684,6 +657,17 @@ SecurityWrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeIm return false; } +// For security wrappers, we run the DefaultValue algorithm on the wrapper +// itself, which means that the existing security policy on operations like +// toString() will take effect and do the right thing here. +template +bool +SecurityWrapper::defaultValue(JSContext *cx, HandleObject wrapper, + JSType hint, MutableHandleValue vp) +{ + return DefaultValue(cx, wrapper, hint, vp); +} + template bool SecurityWrapper::objectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx) diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 419b9030561..fb3ae420067 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -65,10 +65,6 @@ class JS_FRIEND_API(Wrapper) : public DirectProxyHandler virtual ~Wrapper(); - /* ES5 Harmony fundamental wrapper traps. */ - virtual bool defaultValue(JSContext *cx, HandleObject wrapper, JSType hint, - MutableHandleValue vp) MOZ_OVERRIDE; - static Wrapper singleton; static Wrapper singletonWithPrototype; @@ -150,6 +146,8 @@ class JS_FRIEND_API(SecurityWrapper) : public Base bool *bp) MOZ_OVERRIDE; virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args) MOZ_OVERRIDE; + virtual bool defaultValue(JSContext *cx, HandleObject wrapper, JSType hint, + MutableHandleValue vp) MOZ_OVERRIDE; virtual bool objectClassIs(HandleObject obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE; virtual bool regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) MOZ_OVERRIDE;