Bug 514081 - Don't overload the parent slot in SJOWs. r=jst

This commit is contained in:
Blake Kaplan 2009-09-01 19:03:53 -07:00
Родитель 4df7c0116b
Коммит bd2b55e183
8 изменённых файлов: 63 добавлений и 55 удалений

Просмотреть файл

@ -251,8 +251,10 @@ RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
XPCWrappedNative* wrappedNative =
XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, nativeObj);
if (!wrappedNative)
return XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, v, rval);
if (!wrappedNative) {
return XPCSafeJSObjectWrapper::WrapObject(cx, JS_GetScopeChain(cx),
v, rval);
}
if (HAS_FLAGS(flags, FLAG_EXPLICIT)) {
#ifdef DEBUG_XPCNativeWrapper
@ -278,6 +280,7 @@ RewrapIfDeepWrapper(JSContext *cx, JSObject *obj, jsval v, jsval *rval)
// GetWrappedNativeOfJSObject will give the right thing -- the unique deep
// implicit wrapper associated with wrappedNative.
JSObject* wrapperObj = XPCNativeWrapper::GetNewOrUsed(cx, wrappedNative,
JS_GetScopeChain(cx),
nsnull);
if (!wrapperObj) {
return JS_FALSE;
@ -912,7 +915,8 @@ MirrorWrappedNativeParent(JSContext *cx, XPCWrappedNative *wrapper,
// scope. In that case, the best we can do is just use the
// non-native-wrapped sandbox global object for our parent.
if (parent_wrapper) {
*result = XPCNativeWrapper::GetNewOrUsed(cx, parent_wrapper, nsnull);
*result = XPCNativeWrapper::GetNewOrUsed(cx, parent_wrapper, nsnull,
nsnull);
if (!*result)
return JS_FALSE;
} else {
@ -1230,7 +1234,7 @@ XPCNativeWrapper::AttachNewConstructorObject(XPCCallContext &ccx,
// static
JSObject *
XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
nsIPrincipal *aObjectPrincipal)
JSObject *scope, nsIPrincipal *aObjectPrincipal)
{
if (aObjectPrincipal) {
nsIScriptSecurityManager *ssm = GetSecurityManager();
@ -1259,7 +1263,7 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
// Make sure v doesn't get collected while we're re-wrapping it.
AUTO_MARK_JSVAL(ccx, v);
if (XPCSafeJSObjectWrapper::WrapObject(cx, nsnull, v, &v))
if (XPCSafeJSObjectWrapper::WrapObject(cx, scope, v, &v))
return JSVAL_TO_OBJECT(v);
return nsnull;

Просмотреть файл

@ -51,7 +51,7 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject);
JSObject *
GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper,
nsIPrincipal *aObjectPrincipal);
JSObject *scope, nsIPrincipal *aObjectPrincipal);
JSBool
CreateExplicitWrapper(JSContext *cx, XPCWrappedNative *wrapper, JSBool deep,
jsval *rval);

Просмотреть файл

@ -286,11 +286,6 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject)
return PR_FALSE;
}
// Null out the class object's parent to prevent code in this class
// from thinking the class object is a wrapper for the global
// object.
::JS_SetParent(ccx, class_obj, nsnull);
// Make sure our prototype chain is empty and that people can't mess
// with XPCSafeJSObjectWrapper.prototype.
::JS_SetPrototype(ccx, class_obj, nsnull);
@ -307,7 +302,7 @@ AttachNewConstructorObject(XPCCallContext &ccx, JSObject *aGlobalObject)
}
JSObject *
GetUnsafeObject(JSObject *obj)
GetUnsafeObject(JSContext *cx, JSObject *obj)
{
obj = FindSafeObject(obj);
@ -315,7 +310,13 @@ GetUnsafeObject(JSObject *obj)
return nsnull;
}
return STOBJ_GET_PARENT(obj);
jsval v;
if (!JS_GetReservedSlot(cx, obj, XPCWrapper::sWrappedObjSlot, &v)) {
JS_ClearPendingException(cx);
return nsnull;
}
return JSVAL_IS_OBJECT(v) ? JSVAL_TO_OBJECT(v) : nsnull;
}
} // namespace XPCSafeJSObjectWrapper
@ -408,13 +409,13 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval)
}
static jsval
UnwrapJSValue(jsval val)
UnwrapJSValue(JSContext *cx, jsval val)
{
if (JSVAL_IS_PRIMITIVE(val)) {
return val;
}
JSObject *unsafeObj = GetUnsafeObject(JSVAL_TO_OBJECT(val));
JSObject *unsafeObj = GetUnsafeObject(cx, JSVAL_TO_OBJECT(val));
if (unsafeObj) {
return OBJECT_TO_JSVAL(unsafeObj);
}
@ -443,7 +444,7 @@ XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
return ok;
}
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return ThrowException(NS_ERROR_UNEXPECTED, cx);
}
@ -460,7 +461,7 @@ XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
static JSBool
XPC_SJOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return ThrowException(NS_ERROR_UNEXPECTED, cx);
}
@ -533,7 +534,7 @@ XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
obj = FindSafeObject(obj);
NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return ThrowException(NS_ERROR_UNEXPECTED, cx);
}
@ -556,7 +557,7 @@ XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
}
if (aIsSet) {
*vp = UnwrapJSValue(*vp);
*vp = UnwrapJSValue(cx, *vp);
}
JSBool ok = aIsSet
@ -595,7 +596,7 @@ XPC_SJOW_Enumerate(JSContext *cx, JSObject *obj)
// enumerated identifiers from the unsafe object to the safe
// wrapper.
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return JS_TRUE;
}
@ -621,7 +622,7 @@ XPC_SJOW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
obj = FindSafeObject(obj);
NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
// No unsafe object, nothing to resolve here.
@ -679,7 +680,7 @@ XPC_SJOW_CheckAccess(JSContext *cx, JSObject *obj, jsval id,
return JS_FALSE;
}
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return JS_TRUE;
}
@ -732,7 +733,7 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
}
unsafeObj = GetUnsafeObject(obj);
unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
return ThrowException(NS_ERROR_UNEXPECTED, cx);
}
@ -742,7 +743,7 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
JSObject *safeObj = JSVAL_TO_OBJECT(argv[-2]);
JSObject *funToCall = GetUnsafeObject(safeObj);
JSObject *funToCall = GetUnsafeObject(cx, safeObj);
if (!funToCall) {
// Someone has called XPCSafeJSObjectWrapper.prototype() causing
@ -762,7 +763,7 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
SafeCallGuard guard(cx, FindObjectPrincipals(cx, safeObj, funToCall));
for (uintN i = 0; i < argc; ++i) {
argv[i] = UnwrapJSValue(argv[i]);
argv[i] = UnwrapJSValue(cx, argv[i]);
}
if (!JS_CallFunctionValue(cx, callThisObj, OBJECT_TO_JSVAL(funToCall),
@ -782,9 +783,10 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return ThrowException(NS_ERROR_XPC_NOT_ENOUGH_ARGS, cx);
}
// |obj| almost always has the wrong proto and parent so we have to create
// our own object anyway. Set |obj| to null so we don't use it by accident.
obj = nsnull;
// We're not going to use obj because we have callers who aren't the JS
// engine, but we can use it to figure out what scope we're creating this
// SJOW for.
JSObject *scope = JS_GetGlobalForObject(cx, obj);
if (JSVAL_IS_PRIMITIVE(argv[0])) {
JSStackFrame *fp = nsnull;
@ -810,7 +812,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
}
SLIM_LOG_WILL_MORPH(cx, objToWrap);
if(IS_SLIM_WRAPPER(objToWrap) && !MorphSlimWrapper(cx, objToWrap)) {
if (IS_SLIM_WRAPPER(objToWrap) && !MorphSlimWrapper(cx, objToWrap)) {
return ThrowException(NS_ERROR_FAILURE, cx);
}
@ -820,7 +822,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
JSObject *unsafeObj = GetUnsafeObject(objToWrap);
JSObject *unsafeObj = GetUnsafeObject(cx, objToWrap);
if (unsafeObj) {
// We're asked to wrap an already wrapped object. Re-wrap the
@ -829,23 +831,21 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
objToWrap = unsafeObj;
}
// Don't use the object the JS engine created for us, it is in most
// cases incorectly parented and has a proto from the wrong scope.
JSObject *wrapperObj =
::JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
objToWrap);
JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull, scope);
if (!wrapperObj) {
// JS_NewObjectWithGivenProto already threw.
return JS_FALSE;
}
if (!::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, JSVAL_ZERO)) {
*rval = OBJECT_TO_JSVAL(wrapperObj);
if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot,
OBJECT_TO_JSVAL(objToWrap)) ||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot, JSVAL_ZERO)) {
return JS_FALSE;
}
*rval = OBJECT_TO_JSVAL(wrapperObj);
return JS_TRUE;
}
@ -854,8 +854,8 @@ XPC_SJOW_Create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)
{
JSObject *callee = JSVAL_TO_OBJECT(argv[-2]);
NS_ASSERTION(GetUnsafeObject(callee), "How'd we get here?");
JSObject *unsafeObj = GetUnsafeObject(callee);
NS_ASSERTION(GetUnsafeObject(cx, callee), "How'd we get here?");
JSObject *unsafeObj = GetUnsafeObject(cx, callee);
// Check that the caller can access the unsafe object.
if (!CanCallerAccess(cx, unsafeObj)) {
@ -884,10 +884,10 @@ XPC_SJOW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
if (JSVAL_IS_PRIMITIVE(v)) {
*bp = JS_FALSE;
} else {
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
JSObject *other = JSVAL_TO_OBJECT(v);
JSObject *otherUnsafe = GetUnsafeObject(other);
JSObject *otherUnsafe = GetUnsafeObject(cx, other);
// An object is equal to a SJOW if:
// - The other object is the same SJOW.
@ -915,7 +915,7 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
obj = FindSafeObject(obj);
NS_ASSERTION(obj != nsnull, "FindSafeObject() returned null in class hook!");
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
ThrowException(NS_ERROR_INVALID_ARG, cx);
@ -944,13 +944,16 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
// Create our dummy SJOW.
JSObject *wrapperIter =
::JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
unsafeObj);
JS_NewObjectWithGivenProto(cx, &SJOWClass.base, nsnull,
JS_GetGlobalForObject(cx, obj));
if (!wrapperIter) {
return nsnull;
}
if (!::JS_SetReservedSlot(cx, wrapperIter, sFlagsSlot, JSVAL_ZERO)) {
if (!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sWrappedObjSlot,
OBJECT_TO_JSVAL(unsafeObj)) ||
!JS_SetReservedSlot(cx, wrapperIter, XPCWrapper::sFlagsSlot,
JSVAL_ZERO)) {
return nsnull;
}
@ -964,7 +967,7 @@ XPC_SJOW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
static JSObject *
XPC_SJOW_WrappedObject(JSContext *cx, JSObject *obj)
{
return GetUnsafeObject(obj);
return GetUnsafeObject(cx, obj);
}
static JSBool
@ -976,7 +979,7 @@ XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return ThrowException(NS_ERROR_INVALID_ARG, cx);
}
JSObject *unsafeObj = GetUnsafeObject(obj);
JSObject *unsafeObj = GetUnsafeObject(cx, obj);
if (!unsafeObj) {
// No unsafe object, nothing to stringify here, return "[object

Просмотреть файл

@ -75,7 +75,8 @@ Unwrap(JSContext *cx, JSObject *wrapper)
}
if (clasp == &XPCSafeJSObjectWrapper::SJOWClass.base) {
JSObject *wrappedObj = STOBJ_GET_PARENT(wrapper);
JSObject *wrappedObj =
XPCSafeJSObjectWrapper::GetUnsafeObject(cx, wrapper);
if (NS_FAILED(XPCCrossOriginWrapper::CanAccessWrapper(cx, wrappedObj, nsnull))) {
JS_ClearPendingException(cx);

Просмотреть файл

@ -131,7 +131,7 @@ WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp);
namespace XPCSafeJSObjectWrapper {
JSObject *
GetUnsafeObject(JSObject *obj);
GetUnsafeObject(JSContext *cx, JSObject *obj);
JSBool
WrapObject(JSContext *cx, JSObject *scope, jsval v, jsval *vp);

Просмотреть файл

@ -2569,12 +2569,12 @@ nsXPConnect::GetWrapperForObject(JSContext* aJSContext,
}
wrappedObj = XPCNativeWrapper::GetNewOrUsed(aJSContext, wrapper,
aPrincipal);
aScope, aPrincipal);
}
else if(aFilenameFlags & JSFILENAME_SYSTEM)
{
jsval val = OBJECT_TO_JSVAL(aObject);
if(XPCSafeJSObjectWrapper::WrapObject(aJSContext, nsnull, val, &val))
if(XPCSafeJSObjectWrapper::WrapObject(aJSContext, aScope, val, &val))
wrappedObj = JSVAL_TO_OBJECT(val);
}
else

Просмотреть файл

@ -1352,7 +1352,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
destObj =
XPCNativeWrapper::GetNewOrUsed(ccx, wrapper,
objPrincipal);
scope, objPrincipal);
triedWrapping = JS_TRUE;
}
else if (flags & JSFILENAME_SYSTEM)
@ -1362,7 +1362,7 @@ XPCConvert::NativeInterface2JSObject(XPCLazyCallContext& lccx,
"XPCSafeJSObjectWrapper\n");
#endif
if(XPCSafeJSObjectWrapper::WrapObject(ccx, nsnull, v, &v))
if(XPCSafeJSObjectWrapper::WrapObject(ccx, scope, v, &v))
destObj = JSVAL_TO_OBJECT(v);
triedWrapping = JS_TRUE;
}

Просмотреть файл

@ -818,7 +818,7 @@ XPC_GetIdentityObject(JSContext *cx, JSObject *obj)
wrapper = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
if(!wrapper) {
JSObject *unsafeObj = XPCSafeJSObjectWrapper::GetUnsafeObject(obj);
JSObject *unsafeObj = XPCSafeJSObjectWrapper::GetUnsafeObject(cx, obj);
if(unsafeObj)
return XPC_GetIdentityObject(cx, unsafeObj);
@ -855,7 +855,7 @@ XPC_WN_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
if(!*bp && !JSVAL_IS_PRIMITIVE(v) &&
STOBJ_GET_CLASS(JSVAL_TO_OBJECT(v)) == &XPCSafeJSObjectWrapper::SJOWClass.base)
{
v = OBJECT_TO_JSVAL(XPCSafeJSObjectWrapper::GetUnsafeObject(JSVAL_TO_OBJECT(v)));
v = OBJECT_TO_JSVAL(XPCSafeJSObjectWrapper::GetUnsafeObject(cx, JSVAL_TO_OBJECT(v)));
rv = si->GetCallback()->Equality(wrapper, cx, obj, v, bp);
if(NS_FAILED(rv))