Fixing bug 294795. Don't leave references from cloned member functions to the scope where xpconnect creates the functions (safe context). r=bzbarsky@mit.edu, sr=brendan@mozilla.org, a=brendan@mozilla.org

git-svn-id: svn://10.0.0.236/trunk@174082 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jst%mozilla.jstenback.com 2005-06-02 21:33:18 +00:00
parent e7a2bd369e
commit 08a7614911
9 changed files with 72 additions and 28 deletions

View File

@ -418,20 +418,13 @@ JSBool XPCDispObject::Invoke(XPCCallContext & ccx, CallMode mode)
static
JSBool GetMember(XPCCallContext& ccx, JSObject* funobj, XPCNativeInterface*& iface, XPCDispInterface::Member*& member)
{
// We expect funobj to be a clone, we need the real funobj.
JSFunction* fun = (JSFunction*) JS_GetPrivate(ccx, funobj);
if(!fun)
return JS_FALSE;
JSObject* realFunObj = JS_GetFunctionObject(fun);
if(!realFunObj)
return JS_FALSE;
jsval val;
if(!JS_GetReservedSlot(ccx, realFunObj, 1, &val))
if(!JS_GetReservedSlot(ccx, funobj, 1, &val))
return JS_FALSE;
if(!JSVAL_IS_INT(val))
return JS_FALSE;
iface = NS_REINTERPRET_CAST(XPCNativeInterface*,JSVAL_TO_PRIVATE(val));
if(!JS_GetReservedSlot(ccx, realFunObj, 0, &val))
if(!JS_GetReservedSlot(ccx, funobj, 0, &val))
return JS_FALSE;
if(!JSVAL_IS_INT(val))
return JS_FALSE;

View File

@ -266,7 +266,7 @@ JSBool XPCIDispatchExtension::DefineProperty(XPCCallContext & ccx,
// Protect the jsval
AUTO_MARK_JSVAL(ccx, funval);
// clone a function we can use for this object
JSObject* funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(funval), obj);
if(!funobj)
return JS_FALSE;
jsid id;

View File

@ -476,8 +476,8 @@ XPC_NW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
AUTO_MARK_JSVAL(ccx, memberval);
// clone a function we can use for this object
JSObject* funobj = ::JS_CloneFunctionObject(cx, JSVAL_TO_OBJECT(memberval),
wrapper->GetFlatJSObject());
JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(memberval),
wrapper->GetFlatJSObject());
if (!funobj) {
return JS_FALSE;
}
@ -701,9 +701,8 @@ XPC_NW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
// use for this object. NB: cx's newborn roots will protect funobj
// and funWrapper and its object from GC.
JSObject* funobj =
::JS_CloneFunctionObject(cx, JSVAL_TO_OBJECT(memberval),
wrapper->GetFlatJSObject());
JSObject* funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(memberval),
wrapper->GetFlatJSObject());
if (!funobj) {
return JS_FALSE;
}

View File

@ -2092,8 +2092,8 @@ NS_IMETHODIMP nsXPCComponents::LookupMethod()
return NS_ERROR_XPC_BAD_CONVERT_JS;
// clone a function we can use for this object
JSObject* funobj = JS_CloneFunctionObject(cx, JSVAL_TO_OBJECT(funval),
wrapper->GetFlatJSObject());
JSObject* funobj = xpc_CloneJSFunction(inner_cc, JSVAL_TO_OBJECT(funval),
wrapper->GetFlatJSObject());
if(!funobj)
return NS_ERROR_XPC_BAD_CONVERT_JS;

View File

@ -55,6 +55,7 @@ const char* XPCJSRuntime::mStrings[] = {
"Components", // IDX_COMPONENTS
"wrappedJSObject", // IDX_WRAPPED_JSOBJECT
"Object", // IDX_OBJECT
"Function", // IDX_FUNCTION
"prototype", // IDX_PROTOTYPE
"createInstance", // IDX_CREATE_INSTANCE
"item" // IDX_ITEM

View File

@ -558,6 +558,7 @@ public:
IDX_COMPONENTS ,
IDX_WRAPPED_JSOBJECT ,
IDX_OBJECT ,
IDX_FUNCTION ,
IDX_PROTOTYPE ,
IDX_CREATE_INSTANCE ,
IDX_ITEM ,
@ -1014,6 +1015,9 @@ public:
JSObject*
GetPrototypeJSObject() const {return mPrototypeJSObject;}
JSObject*
GetPrototypeJSFunction() const {return mPrototypeJSFunction;}
void RemoveWrappedNativeProtos();
static XPCWrappedNativeScope*
@ -1076,6 +1080,7 @@ private:
XPCWrappedNativeScope* mNext;
JSObject* mGlobalJSObject;
JSObject* mPrototypeJSObject;
JSObject* mPrototypeJSFunction;
};
/***************************************************************************/
@ -3311,6 +3316,9 @@ protected:
JSBool xpc_IsReportableErrorCode(nsresult code);
JSObject* xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj,
JSObject *parent);
/***************************************************************************/
// Inlined utilities.

View File

@ -43,6 +43,44 @@
#include "xpcprivate.h"
/***************************************************************************/
/*
* Helper that clones JS Function objects along with both of its
* reserved slots.
*/
JSObject *
xpc_CloneJSFunction(XPCCallContext &ccx, JSObject *funobj, JSObject *parent)
{
JSObject *clone = JS_CloneFunctionObject(ccx, funobj, parent);
if(!clone)
return nsnull;
XPCWrappedNativeScope *scope =
XPCWrappedNativeScope::FindInJSObjectScope(ccx, parent);
if (!scope) {
return nsnull;
}
// Make sure to break the prototype chain to the function object
// we cloned to prevent its scope from leaking into the clones
// scope.
JS_SetPrototype(ccx, clone, scope->GetPrototypeJSFunction());
// Copy the reserved slots to the clone.
jsval ifaceVal, memberVal;
if(!JS_GetReservedSlot(ccx, funobj, 0, &ifaceVal) ||
!JS_GetReservedSlot(ccx, funobj, 1, &memberVal))
return nsnull;
if(!JS_SetReservedSlot(ccx, clone, 0, ifaceVal) ||
!JS_SetReservedSlot(ccx, clone, 1, memberVal))
return nsnull;
return clone;
}
// XPCNativeMember
// static
@ -52,19 +90,11 @@ XPCNativeMember::GetCallInfo(XPCCallContext& ccx,
XPCNativeInterface** pInterface,
XPCNativeMember** pMember)
{
JSFunction* fun;
JSObject* realFunObj;
// We expect funobj to be a clone, we need the real funobj.
fun = (JSFunction*) JS_GetPrivate(ccx, funobj);
realFunObj = JS_GetFunctionObject(fun);
jsval ifaceVal;
jsval memberVal;
if(!JS_GetReservedSlot(ccx, realFunObj, 0, &ifaceVal) ||
!JS_GetReservedSlot(ccx, realFunObj, 1, &memberVal) ||
if(!JS_GetReservedSlot(ccx, funobj, 0, &ifaceVal) ||
!JS_GetReservedSlot(ccx, funobj, 1, &memberVal) ||
!JSVAL_IS_INT(ifaceVal) || !JSVAL_IS_INT(memberVal))
{
return JS_FALSE;

View File

@ -447,7 +447,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
AUTO_MARK_JSVAL(ccx, funval);
funobj = JS_CloneFunctionObject(ccx, JSVAL_TO_OBJECT(funval), obj);
funobj = xpc_CloneJSFunction(ccx, JSVAL_TO_OBJECT(funval), obj);
if(!funobj)
return JS_FALSE;
}

View File

@ -183,6 +183,7 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
jsval val;
jsid idObj = mRuntime->GetStringID(XPCJSRuntime::IDX_OBJECT);
jsid idFun = mRuntime->GetStringID(XPCJSRuntime::IDX_FUNCTION);
jsid idProto = mRuntime->GetStringID(XPCJSRuntime::IDX_PROTOTYPE);
if(OBJ_GET_PROPERTY(ccx, aGlobal, idObj, &val) &&
@ -196,6 +197,18 @@ XPCWrappedNativeScope::SetGlobal(XPCCallContext& ccx, JSObject* aGlobal)
{
NS_ERROR("Can't get globalObject.Object.prototype");
}
if(OBJ_GET_PROPERTY(ccx, aGlobal, idFun, &val) &&
!JSVAL_IS_PRIMITIVE(val) &&
OBJ_GET_PROPERTY(ccx, JSVAL_TO_OBJECT(val), idProto, &val) &&
!JSVAL_IS_PRIMITIVE(val))
{
mPrototypeJSFunction = JSVAL_TO_OBJECT(val);
}
else
{
NS_ERROR("Can't get globalObject.Function.prototype");
}
}
}