Bug 869740 - Non-LIFO use of Rooted in XPCConvert::NativeInterface2JSObject(). r=bholley

This commit is contained in:
Jon Coppeard 2013-05-08 10:01:00 -07:00
parent 720319bcd4
commit 06feff854a
2 changed files with 59 additions and 36 deletions

View File

@ -37,34 +37,43 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
mName(cx)
{
MOZ_ASSERT(cx);
Init(callerLanguage, callerLanguage == NATIVE_CALLER, obj, funobj,
Init(callerLanguage == NATIVE_CALLER, obj, funobj,
INIT_SHOULD_LOOKUP_WRAPPER, name, argc, argv, rval);
}
XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
JSContext* cx,
JSBool callBeginRequest,
HandleObject obj,
HandleObject flattenedJSObject,
XPCWrappedNative* wrapper,
XPCWrappedNativeTearOff* tearOff)
XPCCallContext::XPCCallContext(JSContext *cx)
: mState(INIT_FAILED),
mXPC(nsXPConnect::GetXPConnect()),
mXPCContext(nullptr),
mJSContext(cx),
mContextPopRequired(false),
mDestroyJSContextInDestructor(false),
mCallerLanguage(callerLanguage),
mCallerLanguage(XPCContext::LANG_UNKNOWN),
mScopeForNewJSObjects(cx),
mFlattenedJSObject(cx, flattenedJSObject),
mWrapper(wrapper),
mTearOff(tearOff),
mFlattenedJSObject(cx),
mName(cx)
{
MOZ_ASSERT(cx);
Init(callerLanguage, callBeginRequest, obj, NullPtr(),
WRAPPER_PASSED_TO_CONSTRUCTOR, JSID_VOIDHANDLE, NO_ARGS,
nullptr, nullptr);
// Called from XPCLazyCallContext only.
MOZ_ASSERT(mJSContext);
}
void
XPCCallContext::LazyInit(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
HandleObject obj,
HandleObject flattenedJSObject,
XPCWrappedNative* wrapper,
XPCWrappedNativeTearOff* tearOff)
{
// Called from XPCLazyCallContext only.
MOZ_ASSERT(mState == INIT_FAILED);
MOZ_ASSERT(mJSContext);
mCallerLanguage = callerLanguage;
mFlattenedJSObject = flattenedJSObject;
mWrapper = wrapper;
mTearOff = tearOff;
Init(callBeginRequest, obj, NullPtr(), WRAPPER_PASSED_TO_CONSTRUCTOR,
JSID_VOIDHANDLE, NO_ARGS, nullptr, nullptr);
}
#define IS_TEAROFF_CLASS(clazz) ((clazz) == &XPC_WN_Tearoff_JSClass)
@ -89,8 +98,7 @@ XPCCallContext::GetDefaultJSContext()
}
void
XPCCallContext::Init(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
XPCCallContext::Init(JSBool callBeginRequest,
HandleObject obj,
HandleObject funobj,
WrapperInitOptions wrapperInitOptions,

View File

@ -1214,22 +1214,29 @@ private:
XPCCallContext(const XPCCallContext& r); // not implemented
XPCCallContext& operator= (const XPCCallContext& r); // not implemented
// The following are for construction from XPCLazyCallContext. Delay doing
// the initialization work until we know that the XPCCallContext will
// actually be needed, but still eagerly construct the overall
// XPCCallContext because it contains Rooted<T> fields that must be
// destroyed in LIFO order. An XPCCallContext will always push its
// Rooted<T>'s onto the stack upon construction, and then pop them off in
// LIFO order during its destruction, regardless of whether LazyInit ever
// gets called.
friend class XPCLazyCallContext;
XPCCallContext(XPCContext::LangType callerLanguage,
JSContext* cx,
JSBool callBeginRequest,
JS::HandleObject obj,
JS::HandleObject flattenedJSObject,
XPCWrappedNative* wn,
XPCWrappedNativeTearOff* tearoff);
XPCCallContext(JSContext *cx);
void LazyInit(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
JS::HandleObject obj,
JS::HandleObject flattenedJSObject,
XPCWrappedNative* wn,
XPCWrappedNativeTearOff* tearoff);
enum WrapperInitOptions {
WRAPPER_PASSED_TO_CONSTRUCTOR,
INIT_SHOULD_LOOKUP_WRAPPER
};
void Init(XPCContext::LangType callerLanguage,
JSBool callBeginRequest,
void Init(JSBool callBeginRequest,
JS::HandleObject obj,
JS::HandleObject funobj,
WrapperInitOptions wrapperInitOptions,
@ -1323,7 +1330,6 @@ public:
: mCallBeginRequest(callerLanguage == NATIVE_CALLER ?
CALL_BEGINREQUEST : DONT_CALL_BEGINREQUEST),
mCcx(nullptr),
mCcxToDestroy(nullptr),
mCx(cx),
mCallerLanguage(callerLanguage),
mObj(cx, obj),
@ -1335,6 +1341,16 @@ public:
NS_ASSERTION(callerLanguage == NATIVE_CALLER ||
callerLanguage == JS_CALLER,
"Can't deal with unknown caller language!");
// Construct with placement new to allow for the other constructor,
// which accepts an existing XPCCallContext to use. This constructed
// XPCCallContext may never be needed, in which case its LazyInit will
// not be invoked, but it must be eagerly constructed here in order to
// maintain LIFO order of its Rooted<T> fields and the ones contained
// in XPCLazyCallContext. (If its construction were delayed, then any
// Rooted<T> created in between the construction of XPCLazyCallContext
// and the LazyInit call would not get destroyed during
// ~XPCLazyCallContext and therefore would not follow LIFO ordering.)
mCcxToDestroy = new (mData.addr()) XPCCallContext(mCx);
#ifdef DEBUG
AssertContextIsTopOfStack(cx);
#endif
@ -1388,16 +1404,15 @@ public:
XPCCallContext &GetXPCCallContext()
{
if (!mCcx) {
XPCCallContext *data = mData.addr();
xpc_UnmarkGrayObject(mObj);
xpc_UnmarkGrayObject(mFlattenedJSObject);
mCcxToDestroy = mCcx =
new (data) XPCCallContext(mCallerLanguage, mCx,
mCallBeginRequest == CALL_BEGINREQUEST,
mObj,
mFlattenedJSObject,
mWrapper,
mTearOff);
mCcxToDestroy = mCcx = mData.addr();
mCcx->LazyInit(mCallerLanguage,
mCallBeginRequest == CALL_BEGINREQUEST,
mObj,
mFlattenedJSObject,
mWrapper,
mTearOff);
if (!mCcx->IsValid()) {
NS_ERROR("This is not supposed to fail!");
}