Backed out changeset 58c5864cb9c6 (Bug 518991) due to linux orange (test failure in test_bug408328.html & 9240-byte leak)

This commit is contained in:
Daniel Holbert 2009-09-30 23:42:27 -07:00
Родитель de381c6f49
Коммит a5f65092e3
4 изменённых файлов: 14 добавлений и 216 удалений

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

@ -48,167 +48,6 @@
// This file implements a wrapper around trusted objects that allows them to // This file implements a wrapper around trusted objects that allows them to
// be safely injected into untrusted code. // 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 static JSBool
XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp); XPC_COW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
@ -248,7 +87,7 @@ JSExtendedClass sXPC_COW_JSClass = {
// JSClass (JSExtendedClass.base) initialization // JSClass (JSExtendedClass.base) initialization
{ "ChromeObjectWrapper", { "ChromeObjectWrapper",
JSCLASS_NEW_RESOLVE | JSCLASS_IS_EXTENDED | 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_AddProperty, XPC_COW_DelProperty,
XPC_COW_GetProperty, XPC_COW_SetProperty, XPC_COW_GetProperty, XPC_COW_SetProperty,
XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve, XPC_COW_Enumerate, (JSResolveOp)XPC_COW_NewResolve,
@ -350,9 +189,10 @@ XPC_COW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
wrappedObj = obj; wrappedObj = obj;
} }
JSObject *funObj = JSVAL_TO_OBJECT(argv[-2]);
jsval funToCall; jsval funToCall;
if (!JS_GetReservedSlot(cx, JSVAL_TO_OBJECT(argv[-2]), if (!JS_GetReservedSlot(cx, funObj, XPCWrapper::eWrappedFunctionSlot,
XPCWrapper::eWrappedFunctionSlot, &funToCall)) { &funToCall)) {
return JS_FALSE; 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); return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
} }
jsid interned_id; if (id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PROTO) ||
if (!JS_ValueToId(cx, id, &interned_id)) { id == GetRTStringByIndex(cx, XPCJSRuntime::IDX_PARENT)) {
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)) {
// No getting or setting __proto__ or __parent__ on my object. // No getting or setting __proto__ or __parent__ on my object.
return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message return ThrowException(NS_ERROR_INVALID_ARG, cx); // XXX better error message
} }
JSBool canTouch; if (!XPC_COW_RewrapForChrome(cx, obj, vp)) {
if (!CanTouchProperty(cx, obj, interned_id, isSet, &canTouch)) {
return JS_FALSE; return JS_FALSE;
} }
if (!canTouch) { jsid interned_id;
return ThrowException(NS_ERROR_XPC_SECURITY_MANAGER_VETO, cx); if (!JS_ValueToId(cx, id, &interned_id)) {
}
if (!XPC_COW_RewrapForChrome(cx, obj, vp)) {
return JS_FALSE; return JS_FALSE;
} }
@ -596,7 +426,7 @@ XPC_COW_Enumerate(JSContext *cx, JSObject *obj)
} }
static JSBool 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) JSObject **objp)
{ {
obj = GetWrapper(obj); obj = GetWrapper(obj);
@ -613,18 +443,6 @@ XPC_COW_NewResolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
return ThrowException(NS_ERROR_FAILURE, cx); 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); 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); *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) || if (!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sWrappedObjSlot, v) ||
!JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot, !JS_SetReservedSlot(cx, wrapperObj, XPCWrapper::sFlagsSlot,
JSVAL_ZERO) || JSVAL_ZERO)) {
!JS_SetReservedSlot(cx, wrapperObj, sExposedPropsSlot, exposedProps)) {
return JS_FALSE; return JS_FALSE;
} }

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

@ -757,17 +757,11 @@ xpc_SameScope(XPCWrappedNativeScope *objectscope, XPCWrappedNativeScope *xpcscop
return JS_FALSE; return JS_FALSE;
} }
inline jsid
GetRTIdByIndex(JSContext *cx, uintN index)
{
XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
return rt->GetStringID(index);
}
inline jsval inline jsval
GetRTStringByIndex(JSContext *cx, uintN index) GetRTStringByIndex(JSContext *cx, uintN index)
{ {
return ID_TO_VALUE(GetRTIdByIndex(cx, index)); XPCJSRuntime *rt = nsXPConnect::GetRuntimeInstance();
return ID_TO_VALUE(rt->GetStringID(index));
} }
inline inline

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

@ -62,8 +62,7 @@ const char* XPCJSRuntime::mStrings[] = {
"item", // IDX_ITEM "item", // IDX_ITEM
"__proto__", // IDX_PROTO "__proto__", // IDX_PROTO
"__iterator__", // IDX_ITERATOR "__iterator__", // IDX_ITERATOR
"__parent__", // IDX_PARENT "__parent__" // IDX_PARENT
"__exposedProps__" // IDX_EXPOSEDPROPS
}; };
/***************************************************************************/ /***************************************************************************/

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

@ -704,7 +704,6 @@ public:
IDX_PROTO , IDX_PROTO ,
IDX_ITERATOR , IDX_ITERATOR ,
IDX_PARENT , IDX_PARENT ,
IDX_EXPOSEDPROPS ,
IDX_TOTAL_COUNT // just a count of the above IDX_TOTAL_COUNT // just a count of the above
}; };
@ -4299,9 +4298,6 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
inline JSBool inline JSBool
xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsval idval); xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsval idval);
inline jsid
GetRTIdByIndex(JSContext *cx, uintN index);
inline jsval inline jsval
GetRTStringByIndex(JSContext *cx, uintN index); GetRTStringByIndex(JSContext *cx, uintN index);