Fix compartment mismatches in js/jetpack (bug 624366, r=jst).
authorAndreas Gal <gal@mozilla.com>
Wed, 26 Jan 2011 15:18:51 -0800
changeset 61444 9d8a15c1f22f331c17c3e7706511a32373b60494
parent 61443 b57667518fd004ed97123326b16595aabc166c29
child 61445 b0ae8b5a88a036df4d6596d3a795fba8c3d39f72
push idunknown
push userunknown
push dateunknown
reviewersjst
bugs624366
milestone2.0b10pre
Fix compartment mismatches in js/jetpack (bug 624366, r=jst).
js/jetpack/Handle.h
js/jetpack/JetpackActorCommon.cpp
js/jetpack/JetpackActorCommon.h
js/jetpack/JetpackChild.cpp
js/jetpack/JetpackParent.cpp
--- a/js/jetpack/Handle.h
+++ b/js/jetpack/Handle.h
@@ -159,24 +159,28 @@ private:
       JSAutoRequest ar(mCx);
 
       if (mObj) {
         mObj->setPrivate(NULL);
 
         js::AutoObjectRooter obj(mCx, mObj);
         mObj = NULL;
 
-        JSBool hasOnInvalidate;
-        if (JS_HasProperty(mCx, obj.object(), "onInvalidate",
-                           &hasOnInvalidate) && hasOnInvalidate) {
-          js::AutoValueRooter r(mCx);
-          JSBool ok = JS_CallFunctionName(mCx, obj.object(), "onInvalidate", 0,
-                                          NULL, r.jsval_addr());
-          if (!ok)
-            JS_ReportPendingException(mCx);
+        // If we can't enter the compartment, we won't run onInvalidate().
+        JSAutoEnterCompartment ac;
+        if (ac.enter(mCx, obj.object())) {
+          JSBool hasOnInvalidate;
+          if (JS_HasProperty(mCx, obj.object(), "onInvalidate",
+                             &hasOnInvalidate) && hasOnInvalidate) {
+            js::AutoValueRooter r(mCx);
+            JSBool ok = JS_CallFunctionName(mCx, obj.object(), "onInvalidate", 0,
+                                            NULL, r.jsval_addr());
+            if (!ok)
+              JS_ReportPendingException(mCx);
+          }
         }
 
         // By not nulling out mContext, we prevent ToJSObject from
         // reviving an invalidated/destroyed handle.
       }
 
       // Nulling out mObj effectively unroots the object, but we still
       // need to remove the root, else the JS engine will complain at
--- a/js/jetpack/JetpackActorCommon.cpp
+++ b/js/jetpack/JetpackActorCommon.cpp
@@ -427,21 +427,29 @@ bool
 JetpackActorCommon::RecvMessage(JSContext* cx,
                                 const nsString& messageName,
                                 const InfallibleTArray<Variant>& data,
                                 InfallibleTArray<Variant>* results)
 {
   if (results)
     results->Clear();
 
+  JSObject* implGlobal = JS_GetGlobalObject(cx);
+
+  JSAutoEnterCompartment ac;
+  if (!ac.enter(cx, implGlobal))
+    return false;
+
   RecList* list;
   if (!mReceivers.Get(messageName, &list))
     return true;
+
   nsAutoTArray<jsval, 4> snapshot;
-  list->copyTo(snapshot);
+  if (!list->copyTo(cx, snapshot))
+    return false;
   if (!snapshot.Length())
     return true;
   
   nsAutoTArray<jsval, 4> args;
   PRUint32 argc = data.Length() + 1;
   jsval* argv = args.AppendElements(argc);
   if (!argv)
     return false;
@@ -456,23 +464,17 @@ JetpackActorCommon::RecvMessage(JSContex
   if (!msgNameStr)
     return false;
   argv[0] = STRING_TO_JSVAL(msgNameStr);
 
   for (PRUint32 i = 0; i < data.Length(); ++i)
     if (!jsval_from_Variant(cx, data.ElementAt(i), argv + i + 1))
       return false;
 
-  JSObject* implGlobal = JS_GetGlobalObject(cx);
   js::AutoValueRooter rval(cx);
-
-  JSAutoEnterCompartment ac;
-  if (!ac.enter(cx, implGlobal))
-    return false;
-
   for (PRUint32 i = 0; i < snapshot.Length(); ++i) {
     Variant* vp = results ? results->AppendElement() : NULL;
     rval.set(JSVAL_VOID);
     if (!JS_CallFunctionValue(cx, implGlobal, snapshot[i], argc, argv,
                               rval.jsval_addr())) {
       (void) JS_ReportPendingException(cx);
       if (vp)
         *vp = void_t();
@@ -524,22 +526,27 @@ JetpackActorCommon::RecList::remove(jsva
       prev->down = node->down;
       delete node;
     } else
       prev = node;
     node = prev->down;
   }
 }
 
-void
-JetpackActorCommon::RecList::copyTo(nsTArray<jsval>& dst) const
+bool
+JetpackActorCommon::RecList::copyTo(JSContext *cx, nsTArray<jsval>& dst) const
 {
   dst.Clear();
-  for (RecNode* node = mHead; node; node = node->down)
-    dst.AppendElement(node->value());
+  for (RecNode* node = mHead; node; node = node->down) {
+    jsval v = node->value();
+    if (!JS_WrapValue(cx, &v))
+      return false;
+    dst.AppendElement(v);
+  }
+  return true;
 }
 
 nsresult
 JetpackActorCommon::RegisterReceiver(JSContext* cx,
                                      const nsString& messageName,
                                      jsval receiver)
 {
   if (JS_TypeOfValue(cx, receiver) != JSTYPE_FUNCTION)
--- a/js/jetpack/JetpackActorCommon.h
+++ b/js/jetpack/JetpackActorCommon.h
@@ -125,17 +125,17 @@ private:
       }
       jsval value() { return mHolder; }
     }* mHead;
   public:
     RecList(JSContext* cx) : mCx(cx), mHead(NULL) {}
    ~RecList();
     void add(jsval v);
     void remove(jsval v);
-    void copyTo(nsTArray<jsval>& dst) const;
+    bool copyTo(JSContext *cx, nsTArray<jsval>& dst) const;
   };
 
   nsClassHashtable<nsStringHashKey, RecList> mReceivers;
 
 };
 
 } // namespace jetpack
 } // namespace mozilla
--- a/js/jetpack/JetpackChild.cpp
+++ b/js/jetpack/JetpackChild.cpp
@@ -474,20 +474,16 @@ JetpackChild::EvalInSandbox(JSContext* c
 {
   if (argc != 2) {
     JS_ReportError(cx, "evalInSandbox takes two arguments");
     return JS_FALSE;
   }
 
   jsval* argv = JS_ARGV(cx, vp);
 
-  JSString* str = JS_ValueToString(cx, argv[1]);
-  if (!str)
-    return JS_FALSE;
-
   JSObject* obj;
   if (!JSVAL_IS_OBJECT(argv[0]) ||
       !(obj = JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
     JS_ASSERT(JS_FALSE);
     return JS_FALSE;
   }
 
@@ -500,16 +496,23 @@ JetpackChild::EvalInSandbox(JSContext* c
 
   if (&sGlobalClass != JS_GetClass(cx, obj) ||
       obj == JS_GetGlobalObject(cx)) {
     JS_ReportError(cx, "The first argument to evalInSandbox must be a global object created using createSandbox.");
     JS_ASSERT(JS_FALSE);
     return JS_FALSE;
   }
 
+  if (!JS_WrapValue(cx, &argv[1]))
+    return JS_FALSE;
+
+  JSString* str = JS_ValueToString(cx, argv[1]);
+  if (!str)
+    return JS_FALSE;
+
   size_t length;
   const jschar* chars = JS_GetStringCharsAndLength(cx, str, &length);
   if (!chars)
       return JS_FALSE;
 
   js::AutoValueRooter ignored(cx);
   return JS_EvaluateUCScript(cx, obj, chars, length, "", 1, ignored.jsval_addr());
 }
--- a/js/jetpack/JetpackParent.cpp
+++ b/js/jetpack/JetpackParent.cpp
@@ -100,19 +100,22 @@ JetpackParent::SendMessage(const nsAStri
   NS_ENSURE_TRUE(data.SetCapacity(argc), NS_ERROR_OUT_OF_MEMORY);
 
   JSAutoRequest request(cx);
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(cx, JS_GetGlobalObject(cx)))
     return false;
 
-  for (PRUint32 i = 1; i < argc; ++i)
-    if (!jsval_to_Variant(cx, argv[i], data.AppendElement()))
+  for (PRUint32 i = 1; i < argc; ++i) {
+    if (!JS_WrapValue(cx, &argv[i]) ||
+        !jsval_to_Variant(cx, argv[i], data.AppendElement())) {
       return NS_ERROR_INVALID_ARG;
+    }
+  }
 
   InfallibleTArray<Variant> dataForSend;
   dataForSend.SwapElements(data);
   if (!SendSendMessage(nsString(aMessageName), dataForSend))
     return NS_ERROR_FAILURE;
 
   return NS_OK;
 }