diff --git a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp index 92566e6a4d0..e4e188e79c6 100644 --- a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp +++ b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp @@ -48,167 +48,6 @@ // This file implements a wrapper around trusted objects that allows them to // be safely injected into untrusted code. -namespace { - -const PRUint32 sPropIsReadable = 0x1; -const PRUint32 sPropIsWritable = 0x2; - -const PRUint32 sExposedPropsSlot = XPCWrapper::sNumSlots; - -class AutoIdArray { -public: - AutoIdArray(JSContext *cx, JSIdArray *ida) : cx(cx), ida(ida) { - } - - ~AutoIdArray() { - if (ida) { - JS_DestroyIdArray(cx, ida); - } - } - - JSIdArray *array() { - return ida; - } - -private: - JSContext *cx; - JSIdArray *ida; -}; - -JSBool -GetExposedProperties(JSContext *cx, JSObject *obj, jsval *rval) -{ - jsid exposedPropsId = GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS); - - JSBool found = JS_FALSE; - if (!JS_HasPropertyById(cx, obj, exposedPropsId, &found)) - return JS_FALSE; - if (!found) { - *rval = JSVAL_VOID; - return JS_TRUE; - } - - *rval = JSVAL_NULL; - jsval exposedProps; - if (!JS_LookupPropertyById(cx, obj, exposedPropsId, &exposedProps)) - return JS_FALSE; - - if (JSVAL_IS_VOID(exposedProps) || JSVAL_IS_NULL(exposedProps)) - return JS_TRUE; - - if (!JSVAL_IS_OBJECT(exposedProps)) { - JS_ReportError(cx, - "__exposedProps__ must be undefined, null, or an Object"); - return JS_FALSE; - } - - obj = JSVAL_TO_OBJECT(exposedProps); - - AutoIdArray guard(cx, JS_Enumerate(cx, obj)); - JSIdArray *props = guard.array(); - if (!props) - return JS_FALSE; - - if (props->length == 0) - return JS_TRUE; - - JSObject *info = JS_NewObjectWithGivenProto(cx, NULL, NULL, obj); - if (!info) - return JS_FALSE; - *rval = OBJECT_TO_JSVAL(info); - - for (int i = 0; i < props->length; i++) { - jsid propId = props->vector[i]; - - jsval propVal; - if (!JS_LookupPropertyById(cx, obj, propId, &propVal)) - return JS_FALSE; - - if (!JSVAL_IS_STRING(propVal)) { - JS_ReportError(cx, "property must be a string"); - return JS_FALSE; - } - - JSString *str = JSVAL_TO_STRING(propVal); - const jschar *chars = JS_GetStringChars(str); - size_t length = JS_GetStringLength(str); - int32 propPerms = 0; - for (size_t i = 0; i < length; ++i) { - switch (chars[i]) { - case 'r': - if (propPerms & sPropIsReadable) { - JS_ReportError(cx, "duplicate 'readable' property flag"); - return JS_FALSE; - } - propPerms |= sPropIsReadable; - break; - - case 'w': - if (propPerms & sPropIsWritable) { - JS_ReportError(cx, "duplicate 'writable' property flag"); - return JS_FALSE; - } - propPerms |= sPropIsWritable; - break; - - default: - JS_ReportError(cx, "properties can only be readable or read and writable"); - return JS_FALSE; - } - } - - if (propPerms == 0) { - JS_ReportError(cx, "specified properties must have a permission bit set"); - return JS_FALSE; - } - - if (!JS_DefinePropertyById(cx, info, propId, INT_TO_JSVAL(propPerms), - NULL, NULL, - JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) { - return JS_FALSE; - } - } - - return JS_TRUE; -} - -JSBool -CanTouchProperty(JSContext *cx, JSObject *wrapperObj, jsid id, JSBool isSet, - JSBool *allowedp) -{ - jsval exposedProps; - if (!JS_GetReservedSlot(cx, wrapperObj, sExposedPropsSlot, &exposedProps)) { - return JS_FALSE; - } - - if (JSVAL_IS_PRIMITIVE(exposedProps)) { - // TODO For now, if the object doesn't ask for security, provide full - // access. In the future, we want to default to false here. - // NB: We differentiate between void (no __exposedProps__ property at all) - // and null (__exposedProps__ exists but didn't specify any properties) - // here. - *allowedp = JSVAL_IS_VOID(exposedProps); - return JS_TRUE; - } - - JSObject *hash = JSVAL_TO_OBJECT(exposedProps); - - jsval allowedval; - if (!JS_LookupPropertyById(cx, hash, id, &allowedval)) { - return JS_FALSE; - } - - const PRUint32 wanted = isSet ? sPropIsWritable : sPropIsReadable; - - // We test JSVAL_IS_INT to protect against unknown ids. - *allowedp = JSVAL_IS_INT(allowedval) && - (JSVAL_TO_INT(allowedval) & wanted) != 0; - - return JS_TRUE; -} - -} - static JSBool XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp); @@ -248,7 +87,7 @@ JSExtendedClass sXPC_COW_JSClass = { // JSClass (JSExtendedClass.base) initialization { "ChromeObjectWrapper", JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | - JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots + 1), + JSCLASS_HAS_RESERVED_SLOTS(XPCWrapper::sNumSlots), XPC_COW_AddProperty, XPC_COW_DelProperty, XPC_COW_GetProperty, XPC_COW_SetProperty, XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve, @@ -350,9 +189,10 @@ XPC_COW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, wrappedObj = obj; } + JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]); jsval funToCall; - if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), - XPCWrapper::eWrappedFunctionSlot, &funToCall)) { + if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot, + &funToCall)) { return JS_FALSE; } @@ -530,28 +370,18 @@ XPC_COW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp, return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx); } - jsid interned_id; - if (!JS_ValueToId(cx, id, &interned_id)) { - return JS_FALSE; - } - - if (interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTO) || - interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PARENT) || - interned_id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_EXPOSEDPROPS)) { + if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PROTO) || + id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PARENT)) { // No getting or setting __proto__ or __parent__ on my object. return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message } - JSBool canTouch; - if (!CanTouchProperty(cx, obj, interned_id, isSet, &canTouch)) { + if (!XPC_COW_RewrapForChrome(cx, obj, vp)) { return JS_FALSE; } - if (!canTouch) { - return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx); - } - - if (!XPC_COW_RewrapForChrome(cx, obj, vp)) { + jsid interned_id; + if (!JS_ValueToId(cx, id, &interned_id)) { return JS_FALSE; } @@ -596,7 +426,7 @@ XPC_COW_Enumerate(JSContext *cx, JSObject *obj) } static JSBool -XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, +XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp) { obj = GetWrapper(obj); @@ -613,18 +443,6 @@ XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags, return ThrowException(NS_ERROR_FAILURE, cx); } - jsid id; - JSBool canTouch; - if (!JS_ValueToId(cx, idval, &id) && - !CanTouchProperty(cx, obj, id, (flags & JSRESOLVE_ASSIGNING) != 0, - &canTouch)) { - return JS_FALSE; - } - - if (!canTouch) { - return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx); - } - return XPCWrapper::NewResolve(cx, obj, JS_TRUE, wrappedObj, id, flags, objp); } @@ -750,18 +568,9 @@ XPC_COW_WrapObject(JSContext *cx, JSObject *parent, jsval v, jsval *vp) } *vp = OBJECT_TO_JSVAL(wrapperObj); - - jsval exposedProps = JSVAL_VOID; - JSAutoTempValueRooter tvr(cx, 1, &exposedProps); - - if (!GetExposedProperties(cx, JSVAL_TO_OBJECT(v), &exposedProps)) { - return JS_FALSE; - } - if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) || !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot, - JSVAL_ZERO) || - !JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) { + JSVAL_ZERO)) { return JS_FALSE; } diff --git a/js/src/xpconnect/src/xpcinlines.h b/js/src/xpconnect/src/xpcinlines.h index ddfc76641ef..07afd2eae2d 100644 --- a/js/src/xpconnect/src/xpcinlines.h +++ b/js/src/xpconnect/src/xpcinlines.h @@ -757,17 +757,11 @@ xpc_SameScope(XPCWrappedNativeScope *objectscope, XPCWrappedNativeScope *xpcscop return JS_FALSE; } -inline jsid -GetRTIdByIndex(JSContext *cx, uintN index) -{ - XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance(); - return rt->GetStringID(index); -} - inline jsval GetRTStringByIndex(JSContext *cx, uintN index) { - return ID_TO_VALUE(GetRTIdByIndex(cx, index)); + XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance(); + return ID_TO_VALUE(rt->GetStringID(index)); } inline diff --git a/js/src/xpconnect/src/xpcjsruntime.cpp b/js/src/xpconnect/src/xpcjsruntime.cpp index 005e1f02614..8f49d8ab71b 100644 --- a/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/js/src/xpconnect/src/xpcjsruntime.cpp @@ -62,8 +62,7 @@ const char* XPCJSRuntime::mStrings[] = { "item", // IDX_ITEM "__proto__", // IDX_PROTO "__iterator__", // IDX_ITERATOR - "__parent__", // IDX_PARENT - "__exposedProps__" // IDX_EXPOSEDPROPS + "__parent__" // IDX_PARENT }; /***************************************************************************/ diff --git a/js/src/xpconnect/src/xpcprivate.h b/js/src/xpconnect/src/xpcprivate.h index 2cccb7324d1..6636cee429f 100644 --- a/js/src/xpconnect/src/xpcprivate.h +++ b/js/src/xpconnect/src/xpcprivate.h @@ -704,7 +704,6 @@ public: IDX_PROTO , IDX_ITERATOR , IDX_PARENT , - IDX_EXPOSEDPROPS , IDX_TOTAL_COUNT // just a count of the above }; @@ -4299,9 +4298,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source, inline JSBool xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsval idval); -inline jsid -GetRTIdByIndex(JSContext *cx, uintN index); - inline jsval GetRTStringByIndex(JSContext *cx, uintN index);