зеркало из https://github.com/mozilla/pjs.git
Backed out changeset 58c5864cb9c6 (Bug 518991) due to linux orange (test failure in test_bug408328.html & 9240-byte leak)
This commit is contained in:
Родитель
de381c6f49
Коммит
a5f65092e3
|
@ -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);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче