Merge after backing out changeset 58c5864cb9c6 (Bug 518991)
authorDaniel Holbert <dholbert@cs.stanford.edu>
Wed, 30 Sep 2009 23:42:50 -0700
changeset 33321 591c244bbb01f49efef986b58c67199fa40cf7b5
parent 33319 3914654341be2fc7bd067bbcecc4f127ae277aef (current diff)
parent 33320 fb9d4a6b8330adff5022ccdaeb52285f3d95a693 (diff)
child 33322 3086d034113d793f479e34a1951f0e77f63478d8
push id9432
push userdholbert@mozilla.com
push dateThu, 01 Oct 2009 06:43:45 +0000
treeherdermozilla-central@591c244bbb01 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs518991
milestone1.9.3a1pre
Merge after backing out changeset 58c5864cb9c6 (Bug 518991)
--- a/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
+++ b/js/src/xpconnect/src/XPCChromeObjectWrapper.cpp
@@ -43,177 +43,16 @@
 #include "jscntxt.h"  // For JSAutoTempValueRooter.
 #include "jsobj.h"
 #include "XPCNativeWrapper.h"
 #include "XPCWrapper.h"
 
 // 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);
 
 static JSBool
 XPC_COW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
 
 static JSBool
 XPC_COW_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
@@ -243,17 +82,17 @@ XPC_COW_Iterator(JSContext *cx, JSObject
 
 static JSObject *
 XPC_COW_WrappedObject(JSContext *cx, JSObject *obj);
 
 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,
     XPC_COW_Convert,     JS_FinalizeStub,
     nsnull,              XPC_COW_CheckAccess,
     nsnull,              nsnull,
     nsnull,              nsnull,
     nsnull,              nsnull
@@ -345,19 +184,20 @@ XPC_COW_FunctionWrapper(JSContext *cx, J
     wrappedObj = GetWrappedObject(cx, wrappedObj);
     if (!wrappedObj) {
       return ThrowException(NS_ERROR_ILLEGAL_VALUE, cx);
     }
   } else {
     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;
   }
 
   for (uintN i = 0; i < argc; ++i) {
     if (!XPC_COW_RewrapForChrome(cx, obj, &argv[i])) {
       return JS_FALSE;
     }
   }
@@ -525,38 +365,28 @@ XPC_COW_GetOrSetProperty(JSContext *cx, 
 
   AUTO_MARK_JSVAL(ccx, vp);
 
   JSObject *wrappedObj = GetWrappedObject(cx, obj);
   if (!wrappedObj) {
     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;
   }
 
   JSBool ok = isSet
               ? JS_SetPropertyById(cx, wrappedObj, interned_id, vp)
               : JS_GetPropertyById(cx, wrappedObj, interned_id, vp);
   if (!ok) {
     return JS_FALSE;
@@ -591,45 +421,33 @@ XPC_COW_Enumerate(JSContext *cx, JSObjec
   if (!ccx.IsValid()) {
     return ThrowException(NS_ERROR_FAILURE, cx);
   }
 
   return XPCWrapper::Enumerate(cx, obj, wrappedObj);
 }
 
 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);
 
   JSObject *wrappedObj = GetWrappedObject(cx, obj);
   if (!wrappedObj) {
     // No wrappedObj means that this is probably the prototype.
     *objp = nsnull;
     return JS_TRUE;
   }
 
   XPCCallContext ccx(JS_CALLER, cx);
   if (!ccx.IsValid()) {
     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);
 }
 
 static JSBool
 XPC_COW_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
 {
   // Don't do any work to convert to object.
   if (type == JSTYPE_OBJECT) {
@@ -745,25 +563,16 @@ XPC_COW_WrapObject(JSContext *cx, JSObje
 {
   JSObject *wrapperObj =
     JS_NewObjectWithGivenProto(cx, &sXPC_COW_JSClass.base, NULL, parent);
   if (!wrapperObj) {
     return JS_FALSE;
   }
 
   *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;
   }
 
   return JS_TRUE;
 }
--- a/js/src/xpconnect/src/xpcinlines.h
+++ b/js/src/xpconnect/src/xpcinlines.h
@@ -752,27 +752,21 @@ xpc_SameScope(XPCWrappedNativeScope *obj
        NS_FAILED(objectprincipal->Equals(xpcprincipal, sameOrigin)))
     {
         *sameOrigin = JS_FALSE;
     }
 
     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
 JSBool ThrowBadParam(nsresult rv, uintN paramNum, XPCCallContext& ccx)
 {
     XPCThrower::ThrowBadParam(rv, paramNum, ccx);
     return JS_FALSE;
 }
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -57,18 +57,17 @@ const char* XPCJSRuntime::mStrings[] = {
     "wrappedJSObject",      // IDX_WRAPPED_JSOBJECT
     "Object",               // IDX_OBJECT
     "Function",             // IDX_FUNCTION
     "prototype",            // IDX_PROTOTYPE
     "createInstance",       // IDX_CREATE_INSTANCE
     "item",                 // IDX_ITEM
     "__proto__",            // IDX_PROTO
     "__iterator__",         // IDX_ITERATOR
-    "__parent__",           // IDX_PARENT
-    "__exposedProps__"      // IDX_EXPOSEDPROPS
+    "__parent__"            // IDX_PARENT
 };
 
 /***************************************************************************/
 
 // data holder class for the enumerator callback below
 struct JSDyingJSObjectData
 {
     JSContext* cx;
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -699,17 +699,16 @@ public:
         IDX_OBJECT                  ,
         IDX_FUNCTION                ,
         IDX_PROTOTYPE               ,
         IDX_CREATE_INSTANCE         ,
         IDX_ITEM                    ,
         IDX_PROTO                   ,
         IDX_ITERATOR                ,
         IDX_PARENT                  ,
-        IDX_EXPOSEDPROPS            ,
         IDX_TOTAL_COUNT // just a count of the above
     };
 
     jsid GetStringID(uintN index) const
     {
         NS_ASSERTION(index < IDX_TOTAL_COUNT, "index out of range");
         return mStrIDs[index];
     }
@@ -4294,19 +4293,16 @@ xpc_EvalInSandbox(JSContext *cx, JSObjec
 #endif /* !XPCONNECT_STANDALONE */
 
 /***************************************************************************/
 // Inlined utilities.
 
 inline JSBool
 xpc_ForcePropertyResolve(JSContext* cx, JSObject* obj, jsval idval);
 
-inline jsid
-GetRTIdByIndex(JSContext *cx, uintN index);
-
 inline jsval
 GetRTStringByIndex(JSContext *cx, uintN index);
 
 // Wrapper for JS_NewObject to mark the new object as system when parent is
 // also a system object.
 inline JSObject*
 xpc_NewSystemInheritingJSObject(JSContext *cx, JSClass *clasp, JSObject *proto,
                                 JSObject *parent);