Bug 763225. Take a bit more care about our compartments in SetJSEventListenerToJsval. r=smaug,bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 14 Jun 2012 13:22:34 -0400
changeset 96702 5674051c17d7fc5b0d1d188594a762895173f434
parent 96701 e079dfd1285ea037041ad306202d08dff2692512
child 96703 542d031d6c3ffe3c11c34feca827a8891000f576
push id10670
push userbzbarsky@mozilla.com
push dateThu, 14 Jun 2012 17:23:45 +0000
treeherdermozilla-inbound@5674051c17d7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, bholley
bugs763225
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 763225. Take a bit more care about our compartments in SetJSEventListenerToJsval. r=smaug,bholley
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -1029,16 +1029,29 @@ nsEventListenerManager::SetJSEventListen
 {
   JSObject *handler;
   if (JSVAL_IS_PRIMITIVE(v) ||
       !JS_ObjectIsCallable(cx, handler = JSVAL_TO_OBJECT(v))) {
     RemoveScriptEventListener(aEventName);
     return NS_OK;
   }
 
+  // Now ensure that we're working in the compartment of aScope from now on.
+  JSAutoEnterCompartment ac;
+  if (!ac.enter(cx, aScope)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // Rewrap the handler into the new compartment, if needed.
+  jsval tempVal = v;
+  if (!JS_WrapValue(cx, &tempVal)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  handler = &tempVal.toObject();
+
   // We might not have a script context, e.g. if we're setting a listener
   // on a dead Window.
   nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(cx, aScope);
   NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
   JSObject *scope = ::JS_GetGlobalForObject(cx, aScope);
   // Untrusted events are always permitted for non-chrome script
   // handlers.
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -254,17 +254,19 @@ protected:
   bool IsDeviceType(PRUint32 aType);
   void EnableDevice(PRUint32 aType);
   void DisableDevice(PRUint32 aType);
 
 public:
   /**
    * Set the "inline" event listener for aEventName to |v|.  This
    * might actually remove the event listener, depending on the value
-   * of |v|.
+   * of |v|.  Note that on entry to this function cx and aScope might
+   * not be in the same compartment, though cx and v are guaranteed to
+   * be in the same compartment.
    */
   nsresult SetJSEventListenerToJsval(nsIAtom *aEventName, JSContext *cx,
                                      JSObject *aScope, const jsval &v);
   /**
    * Get the value of the "inline" event listener for aEventName.
    * This may cause lazy compilation if the listener is uncompiled.
    */
   void GetJSEventListener(nsIAtom *aEventName, jsval *vp);