mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Don't wrap everything that comes out of a wrapped function, if that function is same-origin. bug 390946, r+sr+a=jst
This commit is contained in:
parent
8c0b0586f3
commit
8dc6a0e55f
@ -264,11 +264,14 @@ IsWrapperSameOrigin(JSContext *cx, JSObject *wrappedObj)
|
||||
return ssm->CheckSameOriginPrincipal(subjectPrin, objectPrin);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp);
|
||||
|
||||
static JSBool
|
||||
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval)
|
||||
{
|
||||
JSObject *wrappedObj;
|
||||
JSObject *wrappedObj, *outerObj = obj;
|
||||
|
||||
obj = GetWrapper(cx, obj);
|
||||
if (!obj || (wrappedObj = GetWrappedObject(cx, obj)) == nsnull) {
|
||||
@ -286,6 +289,11 @@ XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
|
||||
}
|
||||
|
||||
nsresult rv = IsWrapperSameOrigin(cx, JSVAL_TO_OBJECT(funToCall));
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_DOM_PROP_ACCESS_DENIED) {
|
||||
return ThrowException(rv, cx);
|
||||
}
|
||||
|
||||
JSNative native = JS_GetFunctionNative(cx, fun);
|
||||
NS_ASSERTION(native, "How'd we get here with a scripted function?");
|
||||
|
||||
@ -299,29 +307,55 @@ XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return WrapSameOriginProp(cx, outerObj, rval);
|
||||
}
|
||||
|
||||
return XPC_XOW_RewrapIfNeeded(cx, obj, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp)
|
||||
{
|
||||
// Don't call XPC_XOW_RewrapIfNeeded for same origin properties. We only
|
||||
// need to wrap window, document and location.
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSObject *wrappedObj = JSVAL_TO_OBJECT(*vp);
|
||||
const char *name = JS_GET_CLASS(cx, wrappedObj)->name;
|
||||
if (XPC_XOW_ClassNeedsXOW(name)) {
|
||||
return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, outerObj), vp);
|
||||
}
|
||||
|
||||
if (JS_ObjectIsFunction(cx, wrappedObj) &&
|
||||
JS_GetFunctionNative(cx, reinterpret_cast<JSFunction *>
|
||||
(JS_GetPrivate(cx, wrappedObj))) ==
|
||||
XPCWrapper::sEvalNative) {
|
||||
return XPC_XOW_WrapFunction(cx, outerObj, wrappedObj, vp);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool
|
||||
XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||
jsval *rval)
|
||||
{
|
||||
jsval funobjVal = OBJECT_TO_JSVAL(funobj);
|
||||
JSNative native = JS_GetFunctionNative(cx, JS_ValueToFunction(cx, funobjVal));
|
||||
JSFunction *wrappedFun = reinterpret_cast<JSFunction *>(JS_GetPrivate(cx, funobj));
|
||||
JSNative native = JS_GetFunctionNative(cx, wrappedFun);
|
||||
if (!native || native == XPC_XOW_FunctionWrapper) {
|
||||
*rval = funobjVal;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSFunction *wrappedFun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj));
|
||||
NS_ASSERTION(wrappedFun, "We were told this was a function");
|
||||
|
||||
JSFunction *funWrapper =
|
||||
JS_NewFunction(cx, XPC_XOW_FunctionWrapper,
|
||||
JS_GetFunctionArity(wrappedFun), 0,
|
||||
JS_GetGlobalForObject(cx, outerObj),
|
||||
"Wrapped function");
|
||||
// XXX JS_GetFunctionName(wrappedFun));
|
||||
JS_GetFunctionName(wrappedFun));
|
||||
if (!funWrapper) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
@ -366,6 +400,7 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp)
|
||||
XPCWrappedNative *wn;
|
||||
if (!JSVAL_IS_OBJECT(*vp) ||
|
||||
!(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
|
||||
JS_GET_CLASS(cx, wrappedObj) == &sXPC_XOW_JSClass.base ||
|
||||
!(wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj))) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
@ -515,6 +550,17 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
// Don't do anything if we already resolved to a wrapped function in
|
||||
// NewResolve. In practice, this means that this is a wrapped eval
|
||||
// function.
|
||||
jsval v = *vp;
|
||||
if (!JSVAL_IS_PRIMITIVE(v) &&
|
||||
JS_ObjectIsFunction(cx, JSVAL_TO_OBJECT(v)) &&
|
||||
JS_GetFunctionNative(cx, JS_ValueToFunction(cx, v)) ==
|
||||
XPC_XOW_FunctionWrapper) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
XPCCallContext ccx(JS_CALLER, cx);
|
||||
if (!ccx.IsValid()) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
@ -609,25 +655,7 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
}
|
||||
}
|
||||
|
||||
// Don't call XPC_XOW_RewrapIfNeeded for same origin properties. We only
|
||||
// need to wrap window, document and location.
|
||||
if (JSVAL_IS_PRIMITIVE(*vp)) {
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
wrappedObj = JSVAL_TO_OBJECT(*vp);
|
||||
if (JS_ObjectIsFunction(cx, wrappedObj) &&
|
||||
JS_GetFunctionNative(cx, JS_ValueToFunction(cx, *vp)) ==
|
||||
XPCWrapper::sEvalNative) {
|
||||
return XPC_XOW_WrapFunction(cx, obj, wrappedObj, vp);
|
||||
}
|
||||
|
||||
const char *name = JS_GET_CLASS(cx, wrappedObj)->name;
|
||||
if (XPC_XOW_ClassNeedsXOW(name)) {
|
||||
return XPC_XOW_WrapObject(cx, JS_GetGlobalForObject(cx, obj), vp);
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
return WrapSameOriginProp(cx, obj, vp);
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
|
@ -140,58 +140,56 @@ XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
||||
JSObject *innerObj, jsval id, uintN flags,
|
||||
JSObject **objp, JSBool preserveVal)
|
||||
{
|
||||
jschar *chars = nsnull;
|
||||
size_t length;
|
||||
JSBool hasProp, ok;
|
||||
jsval v = JSVAL_VOID;
|
||||
|
||||
if (JSVAL_IS_STRING(id)) {
|
||||
JSString *str = JSVAL_TO_STRING(id);
|
||||
|
||||
chars = ::JS_GetStringChars(str);
|
||||
length = ::JS_GetStringLength(str);
|
||||
|
||||
ok = ::JS_HasUCProperty(cx, innerObj, chars, length, &hasProp);
|
||||
if (preserveVal && ok && hasProp) {
|
||||
ok = ::JS_LookupUCProperty(cx, innerObj, chars, length, &v);
|
||||
}
|
||||
} else if (JSVAL_IS_INT(id)) {
|
||||
ok = ::JS_HasElement(cx, innerObj, JSVAL_TO_INT(id), &hasProp);
|
||||
if (preserveVal && ok && hasProp) {
|
||||
ok = ::JS_LookupElement(cx, innerObj, JSVAL_TO_INT(id), &v);
|
||||
}
|
||||
} else {
|
||||
// FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=381662
|
||||
// A non-string and non-int id is being resolved. We don't deal
|
||||
// with those yet, return early.
|
||||
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx);
|
||||
jsid interned_id;
|
||||
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!ok || !hasProp) {
|
||||
// An error occured, or the property was not found. Return
|
||||
// early. This is safe even in the case of a set operation since
|
||||
// if the property doesn't exist there's no chance of a setter
|
||||
// being called or any other code being run as a result of the
|
||||
// set.
|
||||
JSProperty *prop;
|
||||
JSObject *innerObjp;
|
||||
if (!OBJ_LOOKUP_PROPERTY(cx, innerObj, interned_id, &innerObjp, &prop)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
return ok;
|
||||
if (!prop) {
|
||||
// Nothing to define.
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
JSBool isXOW = (JS_GET_CLASS(cx, wrapperObj) == &sXPC_XOW_JSClass.base);
|
||||
if (preserveVal || isXOW) {
|
||||
JSScopeProperty *sprop = reinterpret_cast<JSScopeProperty *>(prop);
|
||||
if (SPROP_HAS_VALID_SLOT(sprop, OBJ_SCOPE(innerObjp))) {
|
||||
v = OBJ_GET_SLOT(cx, innerObjp, sprop->slot);
|
||||
}
|
||||
}
|
||||
|
||||
OBJ_DROP_PROPERTY(cx, innerObjp, prop);
|
||||
|
||||
// Hack alert: we only do this for same-origin calls on XOWs: we want
|
||||
// to preserve 'eval' function wrapper on the wrapper object itself
|
||||
// to preserve eval's identity.
|
||||
if (!preserveVal && isXOW && !JSVAL_IS_PRIMITIVE(v)) {
|
||||
JSObject *obj = JSVAL_TO_OBJECT(v);
|
||||
if (JS_ObjectIsFunction(cx, obj)) {
|
||||
JSFunction *fun = reinterpret_cast<JSFunction *>(JS_GetPrivate(cx, obj));
|
||||
if (JS_GetFunctionNative(cx, fun) == sEvalNative &&
|
||||
!WrapFunction(cx, wrapperObj, obj, &v, JS_FALSE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsval oldSlotVal;
|
||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldSlotVal) ||
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
||||
BOOLEAN_TO_JSVAL(JS_TRUE))) {
|
||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, JSVAL_TRUE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
ok = ::JS_DefineUCProperty(cx, wrapperObj, chars, length, v,
|
||||
nsnull, nsnull, JSPROP_ENUMERATE);
|
||||
} else {
|
||||
ok = ::JS_DefineElement(cx, wrapperObj, JSVAL_TO_INT(id), v,
|
||||
nsnull, nsnull, JSPROP_ENUMERATE);
|
||||
}
|
||||
JSBool ok = OBJ_DEFINE_PROPERTY(cx, wrapperObj, interned_id, v, nsnull,
|
||||
nsnull, JSPROP_ENUMERATE, nsnull);
|
||||
|
||||
if (ok && (ok = ::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
||||
oldSlotVal))) {
|
||||
|
Loading…
Reference in New Issue
Block a user