mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +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);
|
return ssm->CheckSameOriginPrincipal(subjectPrin, objectPrin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSBool
|
||||||
|
WrapSameOriginProp(JSContext *cx, JSObject *outerObj, jsval *vp);
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
XPC_XOW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||||
jsval *rval)
|
jsval *rval)
|
||||||
{
|
{
|
||||||
JSObject *wrappedObj;
|
JSObject *wrappedObj, *outerObj = obj;
|
||||||
|
|
||||||
obj = GetWrapper(cx, obj);
|
obj = GetWrapper(cx, obj);
|
||||||
if (!obj || (wrappedObj = GetWrappedObject(cx, obj)) == nsnull) {
|
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);
|
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);
|
JSNative native = JS_GetFunctionNative(cx, fun);
|
||||||
NS_ASSERTION(native, "How'd we get here with a scripted function?");
|
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;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
return WrapSameOriginProp(cx, outerObj, rval);
|
||||||
|
}
|
||||||
|
|
||||||
return XPC_XOW_RewrapIfNeeded(cx, obj, 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
|
JSBool
|
||||||
XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
XPC_XOW_WrapFunction(JSContext *cx, JSObject *outerObj, JSObject *funobj,
|
||||||
jsval *rval)
|
jsval *rval)
|
||||||
{
|
{
|
||||||
jsval funobjVal = OBJECT_TO_JSVAL(funobj);
|
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) {
|
if (!native || native == XPC_XOW_FunctionWrapper) {
|
||||||
*rval = funobjVal;
|
*rval = funobjVal;
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSFunction *wrappedFun = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(funobj));
|
|
||||||
NS_ASSERTION(wrappedFun, "We were told this was a function");
|
|
||||||
|
|
||||||
JSFunction *funWrapper =
|
JSFunction *funWrapper =
|
||||||
JS_NewFunction(cx, XPC_XOW_FunctionWrapper,
|
JS_NewFunction(cx, XPC_XOW_FunctionWrapper,
|
||||||
JS_GetFunctionArity(wrappedFun), 0,
|
JS_GetFunctionArity(wrappedFun), 0,
|
||||||
JS_GetGlobalForObject(cx, outerObj),
|
JS_GetGlobalForObject(cx, outerObj),
|
||||||
"Wrapped function");
|
JS_GetFunctionName(wrappedFun));
|
||||||
// XXX JS_GetFunctionName(wrappedFun));
|
|
||||||
if (!funWrapper) {
|
if (!funWrapper) {
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
@ -366,6 +400,7 @@ XPC_XOW_WrapObject(JSContext *cx, JSObject *parent, jsval *vp)
|
|||||||
XPCWrappedNative *wn;
|
XPCWrappedNative *wn;
|
||||||
if (!JSVAL_IS_OBJECT(*vp) ||
|
if (!JSVAL_IS_OBJECT(*vp) ||
|
||||||
!(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
|
!(wrappedObj = JSVAL_TO_OBJECT(*vp)) ||
|
||||||
|
JS_GET_CLASS(cx, wrappedObj) == &sXPC_XOW_JSClass.base ||
|
||||||
!(wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj))) {
|
!(wn = XPCWrappedNative::GetWrappedNativeOfJSObject(cx, wrappedObj))) {
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
@ -515,6 +550,17 @@ XPC_XOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||||||
return JS_TRUE;
|
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);
|
XPCCallContext ccx(JS_CALLER, cx);
|
||||||
if (!ccx.IsValid()) {
|
if (!ccx.IsValid()) {
|
||||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
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
|
return WrapSameOriginProp(cx, obj, vp);
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||||
|
@ -140,58 +140,56 @@ XPCWrapper::NewResolve(JSContext *cx, JSObject *wrapperObj,
|
|||||||
JSObject *innerObj, jsval id, uintN flags,
|
JSObject *innerObj, jsval id, uintN flags,
|
||||||
JSObject **objp, JSBool preserveVal)
|
JSObject **objp, JSBool preserveVal)
|
||||||
{
|
{
|
||||||
jschar *chars = nsnull;
|
|
||||||
size_t length;
|
|
||||||
JSBool hasProp, ok;
|
|
||||||
jsval v = JSVAL_VOID;
|
jsval v = JSVAL_VOID;
|
||||||
|
|
||||||
if (JSVAL_IS_STRING(id)) {
|
jsid interned_id;
|
||||||
JSString *str = JSVAL_TO_STRING(id);
|
if (!::JS_ValueToId(cx, id, &interned_id)) {
|
||||||
|
return JS_FALSE;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok || !hasProp) {
|
JSProperty *prop;
|
||||||
// An error occured, or the property was not found. Return
|
JSObject *innerObjp;
|
||||||
// early. This is safe even in the case of a set operation since
|
if (!OBJ_LOOKUP_PROPERTY(cx, innerObj, interned_id, &innerObjp, &prop)) {
|
||||||
// if the property doesn't exist there's no chance of a setter
|
return JS_FALSE;
|
||||||
// being called or any other code being run as a result of the
|
}
|
||||||
// set.
|
|
||||||
|
|
||||||
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;
|
jsval oldSlotVal;
|
||||||
if (!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldSlotVal) ||
|
if (!::JS_GetReservedSlot(cx, wrapperObj, sResolvingSlot, &oldSlotVal) ||
|
||||||
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
!::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot, JSVAL_TRUE)) {
|
||||||
BOOLEAN_TO_JSVAL(JS_TRUE))) {
|
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chars) {
|
JSBool ok = OBJ_DEFINE_PROPERTY(cx, wrapperObj, interned_id, v, nsnull,
|
||||||
ok = ::JS_DefineUCProperty(cx, wrapperObj, chars, length, v,
|
nsnull, JSPROP_ENUMERATE, nsnull);
|
||||||
nsnull, nsnull, JSPROP_ENUMERATE);
|
|
||||||
} else {
|
|
||||||
ok = ::JS_DefineElement(cx, wrapperObj, JSVAL_TO_INT(id), v,
|
|
||||||
nsnull, nsnull, JSPROP_ENUMERATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ok && (ok = ::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
if (ok && (ok = ::JS_SetReservedSlot(cx, wrapperObj, sResolvingSlot,
|
||||||
oldSlotVal))) {
|
oldSlotVal))) {
|
||||||
|
Loading…
Reference in New Issue
Block a user