Fix bug 567069. r=jorendorff/luke

This commit is contained in:
Blake Kaplan 2010-06-10 10:48:59 -07:00
parent b502607b06
commit d85ecf0625
3 changed files with 156 additions and 9 deletions

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -1537,6 +1537,81 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
/************************************************************************/
static bool
SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs &regs, JSObject *scopeobj)
{
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, scopeobj);
JS_ASSERT(fun->minArgs() == 0 && !fun->isInterpreted() && fun->u.n.extra == 0);
const uintN vplen = 2;
const uintN nfixed = 0;
if (!cx->stack().getExecuteFrame(cx, js_GetTopStackFrame(cx), vplen, nfixed, frame))
return false;
jsval *vp = frame.getvp();
PodZero(vp, vplen);
vp[0] = OBJECT_TO_JSVAL(scopeobj);
JSStackFrame *fp = frame.getFrame();
PodZero(fp);
fp->fun = fun;
fp->argv = vp + 2;
fp->scopeChain = scopeobj->getGlobal();
regs.pc = NULL;
regs.sp = fp->slots();
cx->stack().pushExecuteFrame(cx, frame, regs, NULL);
return true;
}
JS_FRIEND_API(JSBool)
js_GetPropertyByIdWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsid id,
jsval *vp)
{
ExecuteFrameGuard frame;
JSFrameRegs regs;
if (!SetupFakeFrame(cx, frame, regs, scopeobj))
return false;
bool ok = JS_GetPropertyById(cx, obj, id, vp);
frame.getFrame()->putActivationObjects(cx);
return ok;
}
JS_FRIEND_API(JSBool)
js_SetPropertyByIdWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsid id,
jsval *vp)
{
ExecuteFrameGuard frame;
JSFrameRegs regs;
if (!SetupFakeFrame(cx, frame, regs, scopeobj))
return false;
bool ok = JS_SetPropertyById(cx, obj, id, vp);
frame.getFrame()->putActivationObjects(cx);
return ok;
}
JS_FRIEND_API(JSBool)
js_CallFunctionValueWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsval funval,
uintN argc, jsval *argv, jsval *rval)
{
ExecuteFrameGuard frame;
JSFrameRegs regs;
if (!SetupFakeFrame(cx, frame, regs, scopeobj))
return false;
bool ok = JS_CallFunctionValue(cx, obj, funval, argc, argv, rval);
frame.getFrame()->putActivationObjects(cx);
return ok;
}
/************************************************************************/
JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
{

View File

@ -1,5 +1,5 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=78:
* vim: set ts=8 sw=4 et tw=99:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -337,6 +337,20 @@ JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
/************************************************************************/
extern JS_FRIEND_API(JSBool)
js_GetPropertyByIdWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsid id,
jsval *vp);
extern JS_FRIEND_API(JSBool)
js_SetPropertyByIdWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsid id,
jsval *vp);
extern JS_FRIEND_API(JSBool)
js_CallFunctionValueWithFakeFrame(JSContext *cx, JSObject *obj, JSObject *scopeobj, jsval funval,
uintN argc, jsval *argv, jsval *rval);
/************************************************************************/
extern JS_PUBLIC_API(JSBool)
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler hook, void *closure);

View File

@ -194,6 +194,11 @@ CanCallerAccess(JSContext *cx, JSObject *wrapperObj, JSObject *unsafeObj)
// (nsIPrincipal, strong reference).
static const PRUint32 sPrincipalSlot = sNumSlots;
// Slot for holding the function that we fill our fake frame with.
static const PRUint32 sScopeFunSlot = sNumSlots + 1;
static const PRUint32 sSJOWSlots = sNumSlots + 2;
// Returns a weak reference.
static nsIPrincipal *
FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj)
@ -252,7 +257,7 @@ JSExtendedClass SJOWClass = {
// JSClass (JSExtendedClass.base) initialization
{ "XPCSafeJSObjectWrapper",
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED |
JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1),
JSCLASS_HAS_RESERVED_SLOTS(sSJOWSlots),
XPC_SJOW_AddProperty, XPC_SJOW_DelProperty,
XPC_SJOW_GetProperty, XPC_SJOW_SetProperty,
XPC_SJOW_Enumerate, (JSResolveOp)XPC_SJOW_NewResolve,
@ -387,6 +392,40 @@ GetUnsafeObject(JSContext *cx, JSObject *obj)
} // namespace XPCSafeJSObjectWrapper
static JSBool
DummyNative(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
return JS_TRUE;
}
static JSObject *
GetScopeFunction(JSContext *cx, JSObject *outerObj)
{
jsval v;
if (!JS_GetReservedSlot(cx, outerObj, sScopeFunSlot, &v)) {
return nsnull;
}
if (JSVAL_IS_OBJECT(v)) {
return JSVAL_TO_OBJECT(v);
}
JSObject *unsafeObj = GetUnsafeObject(cx, outerObj);
JSFunction *fun = JS_NewFunction(cx, DummyNative, 0, 0,
JS_GetGlobalForObject(cx, unsafeObj),
"SJOWContentBoundary");
if (!fun) {
return nsnull;
}
JSObject *funobj = JS_GetFunctionObject(fun);
if (!JS_SetReservedSlot(cx, outerObj, sScopeFunSlot, OBJECT_TO_JSVAL(funobj))) {
return nsnull;
}
return funobj;
}
// Wrap a JS value in a safe wrapper of a function wrapper if
// needed. Note that rval must point to something rooted when calling
// this function.
@ -601,6 +640,11 @@ XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
return JS_FALSE;
}
JSObject *scopeFun = GetScopeFunction(cx, obj);
if (!scopeFun) {
return JS_FALSE;
}
{
SafeCallGuard guard(cx, FindObjectPrincipals(cx, obj, unsafeObj));
if (!guard.ready()) {
@ -620,8 +664,10 @@ XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
}
JSBool ok = aIsSet
? JS_SetPropertyById(cx, unsafeObj, interned_id, vp)
: JS_GetPropertyById(cx, unsafeObj, interned_id, vp);
? js_SetPropertyByIdWithFakeFrame(cx, unsafeObj, scopeFun,
interned_id, vp)
: js_GetPropertyByIdWithFakeFrame(cx, unsafeObj, scopeFun,
interned_id, vp);
if (!ok) {
return JS_FALSE;
}
@ -820,6 +866,11 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
JSObject *scopeFun = GetScopeFunction(cx, safeObj);
if (!scopeFun) {
return JS_FALSE;
}
{
SafeCallGuard guard(cx, FindObjectPrincipals(cx, safeObj, funToCall));
@ -837,8 +888,9 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
if (!JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(v), OBJECT_TO_JSVAL(funToCall),
argc, argv, rval)) {
if (!js_CallFunctionValueWithFakeFrame(cx, JSVAL_TO_OBJECT(v), scopeFun,
OBJECT_TO_JSVAL(funToCall),
argc, argv, rval)) {
return JS_FALSE;
}
}
@ -897,6 +949,11 @@ XPC_SJOW_Create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
JSObject *scopeFun = GetScopeFunction(cx, callee);
if (!scopeFun) {
return JS_FALSE;
}
{
SafeCallGuard guard(cx, FindObjectPrincipals(cx, callee, unsafeObj));
if (!guard.ready()) {
@ -917,8 +974,9 @@ XPC_SJOW_Create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
return JS_FALSE;
}
if (!JS_CallFunctionValue(cx, JSVAL_TO_OBJECT(v), OBJECT_TO_JSVAL(unsafeObj),
argc, argv, rval)) {
if (!js_CallFunctionValueWithFakeFrame(cx, JSVAL_TO_OBJECT(v), scopeFun,
OBJECT_TO_JSVAL(unsafeObj),
argc, argv, rval)) {
return JS_FALSE;
}
}