Fixing bug 486269. Prevent plugins from being destroyed while calling into them. r=joshmoz@gmail.com, sr=bzbarsky@mit.edu
authorJohnny Stenback <jst@mozilla.com>
Tue, 07 Apr 2009 14:14:23 -0700
changeset 24260 677ab64c4e9d4242bdf26df4f0ece6da2416c5bf
parent 24259 a897e9525f7ef4eb58dc9fa346b13f55e05e9fe6
child 24261 42e302abf6753756bb330a9b141fb20cc4459e19
push id1107
push userjst@mozilla.com
push dateTue, 07 Apr 2009 21:14:40 +0000
reviewersjoshmoz, bzbarsky
bugs486269
milestone1.9.1b4pre
Fixing bug 486269. Prevent plugins from being destroyed while calling into them. r=joshmoz@gmail.com, sr=bzbarsky@mit.edu
modules/plugin/base/src/nsJSNPRuntime.cpp
--- a/modules/plugin/base/src/nsJSNPRuntime.cpp
+++ b/modules/plugin/base/src/nsJSNPRuntime.cpp
@@ -1143,16 +1143,18 @@ NPObjWrapper_AddProperty(JSContext *cx, 
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(LookupNPP(npobj));
+
   // We must permit methods here since JS_DefineUCFunction() will add
   // the function as a property
   if (!npobj->_class->hasProperty(npobj, (NPIdentifier)id) &&
       !npobj->_class->hasMethod(npobj, (NPIdentifier)id)) {
     ThrowJSException(cx, "Trying to add unsupported property on scriptable "
                      "plugin object!");
 
     return JS_FALSE;
@@ -1168,16 +1170,18 @@ NPObjWrapper_DelProperty(JSContext *cx, 
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->removeProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(LookupNPP(npobj));
+
   if (!npobj->_class->hasProperty(npobj, (NPIdentifier)id))
     return JS_TRUE;
 
   if (!npobj->_class->removeProperty(npobj, (NPIdentifier)id))
     *vp = JSVAL_FALSE;
 
   return ReportExceptionIfPending(cx);
 }
@@ -1189,33 +1193,35 @@ NPObjWrapper_SetProperty(JSContext *cx, 
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->setProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
   }
 
-  if (!npobj->_class->hasProperty(npobj, (NPIdentifier)id)) {
-    ThrowJSException(cx, "Trying to set unsupported property on scriptable "
-                     "plugin object!");
-
-    return JS_FALSE;
-  }
-
   // Find out what plugin (NPP) is the owner of the object we're
   // manipulating, and make it own any JSObject wrappers created here.
   NPP npp = LookupNPP(npobj);
 
   if (!npp) {
     ThrowJSException(cx, "No NPP found for NPObject!");
 
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(npp);
+
+  if (!npobj->_class->hasProperty(npobj, (NPIdentifier)id)) {
+    ThrowJSException(cx, "Trying to set unsupported property on scriptable "
+                     "plugin object!");
+
+    return JS_FALSE;
+  }
+
   NPVariant npv;
   if (!JSValToNPVariant(npp, cx, *vp, &npv)) {
     ThrowJSException(cx, "Error converting jsval to NPVariant!");
 
     return JS_FALSE;
   }
 
   JSBool ok = npobj->_class->setProperty(npobj, (NPIdentifier)id, &npv);
@@ -1240,30 +1246,29 @@ NPObjWrapper_GetProperty(JSContext *cx, 
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod || !npobj->_class->getProperty) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
   }
 
+  // Find out what plugin (NPP) is the owner of the object we're
+  // manipulating, and make it own any JSObject wrappers created here.
+  NPP npp = LookupNPP(npobj);
+  if (!npp) {
+    ThrowJSException(cx, "No NPP found for NPObject!");
+
+    return JS_FALSE;
+  }
+
+  PluginDestructionGuard pdg(npp);
+
   PRBool hasProperty = npobj->_class->hasProperty(npobj, (NPIdentifier)id);
   PRBool hasMethod = npobj->_class->hasMethod(npobj, (NPIdentifier)id);
-  NPP npp = nsnull;
-  if (hasProperty) {
-    // Find out what plugin (NPP) is the owner of the object we're
-    // manipulating, and make it own any JSObject wrappers created
-    // here.
-    npp = LookupNPP(npobj);
-    if (!npp) {
-      ThrowJSException(cx, "No NPP found for NPObject!");
-
-      return JS_FALSE;
-    }
-  }
 
   // To support ambiguous members, we return NPObject Member class here.
   if (hasProperty && hasMethod)
     return CreateNPObjectMember(npp, cx, obj, npobj, id, vp);
 
   if (hasProperty) {
     NPVariant npv;
     VOID_TO_NPVARIANT(npv);
@@ -1313,16 +1318,18 @@ CallNPMethodInternal(JSContext *cx, JSOb
   NPP npp = LookupNPP(npobj);
 
   if (!npp) {
     ThrowJSException(cx, "Error finding NPP for NPObject!");
 
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(npp);
+
   NPVariant npargs_buf[8];
   NPVariant *npargs = npargs_buf;
 
   if (argc > (sizeof(npargs_buf) / sizeof(NPVariant))) {
     // Our stack buffer isn't large enough to hold all arguments,
     // malloc a buffer.
     npargs = (NPVariant *)PR_Malloc(argc * sizeof(NPVariant));
 
@@ -1440,16 +1447,18 @@ NPObjWrapper_newEnumerate(JSContext *cx,
   uint32_t length;
   NPObjectEnumerateState *state;
 
   if (!npobj || !npobj->_class) {
     ThrowJSException(cx, "Bad NPObject as private data!");
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(LookupNPP(npobj));
+
   NS_ASSERTION(statep, "Must have a statep to enumerate!");
 
   switch(enum_op) {
   case JSENUMERATE_INIT:
     state = new NPObjectEnumerateState();
     if (!state) {
       ThrowJSException(cx, "Memory allocation failed for "
                        "NPObjectEnumerateState!");
@@ -1510,16 +1519,18 @@ NPObjWrapper_NewResolve(JSContext *cx, J
 
   if (!npobj || !npobj->_class || !npobj->_class->hasProperty ||
       !npobj->_class->hasMethod) {
     ThrowJSException(cx, "Bad NPObject as private data!");
 
     return JS_FALSE;
   }
 
+  PluginDestructionGuard pdg(LookupNPP(npobj));
+
   if (npobj->_class->hasProperty(npobj, (NPIdentifier)id)) {
     JSBool ok;
 
     if (JSVAL_IS_STRING(id)) {
       JSString *str = JSVAL_TO_STRING(id);
 
       ok = ::JS_DefineUCProperty(cx, obj, ::JS_GetStringChars(str),
                                  ::JS_GetStringLength(str), JSVAL_VOID, nsnull,