From 428ab775c462fc4b334abb687bd4fd0dcc51924c Mon Sep 17 00:00:00 2001 From: "jst@mozilla.org" Date: Thu, 9 Aug 2007 15:22:26 -0700 Subject: [PATCH] Attempting to fix bug 354380. Add safe guard against prematurely deleted scriptable plugin objects. r=mrbkap@gmail.com, sr=jonas@sicking.cc --- modules/plugin/base/src/ns4xPlugin.cpp | 2 + modules/plugin/base/src/nsJSNPRuntime.cpp | 46 +++++++++++++++++++++++ modules/plugin/base/src/nsJSNPRuntime.h | 1 + 3 files changed, 49 insertions(+) diff --git a/modules/plugin/base/src/ns4xPlugin.cpp b/modules/plugin/base/src/ns4xPlugin.cpp index 1149315e4ba1..64adeb9e839d 100644 --- a/modules/plugin/base/src/ns4xPlugin.cpp +++ b/modules/plugin/base/src/ns4xPlugin.cpp @@ -1566,6 +1566,8 @@ _releaseobject(NPObject* npobj) int32_t refCnt = PR_AtomicDecrement((PRInt32*)&npobj->referenceCount); if (refCnt == 0) { + nsNPObjWrapper::OnDestroy(npobj); + if (npobj->_class && npobj->_class->deallocate) { npobj->_class->deallocate(npobj); } else { diff --git a/modules/plugin/base/src/nsJSNPRuntime.cpp b/modules/plugin/base/src/nsJSNPRuntime.cpp index 89aefe109848..ab8ddc3bbd22 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -1449,6 +1449,52 @@ public: }; +// An NPObject is going away, make sure we null out the JS object's +// private data in case this is an NPObject that came from a plugin +// and it's destroyed prematurely. + +// static +void +nsNPObjWrapper::OnDestroy(NPObject *npobj) +{ + if (!npobj) { + return; + } + + if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) { + // npobj is one of our own, no private data to clean up here. + + return; + } + + if (!sNPObjWrappers.ops) { + // No hash yet (or any more), no used wrappers available. + + return; + } + + NPObjWrapperHashEntry *entry = + NS_STATIC_CAST(NPObjWrapperHashEntry *, + PL_DHashTableOperate(&sNPObjWrappers, npobj, + PL_DHASH_LOOKUP)); + + if (PL_DHASH_ENTRY_IS_BUSY(entry) && entry->mJSObj) { + // Found a live NPObject wrapper, null out its JSObjects' private + // data. + + JSContext *cx = GetJSContext(entry->mNpp); + + if (cx) { + ::JS_SetPrivate(cx, entry->mJSObj, nsnull); + } + + // Remove the npobj from the hash now that it went away. + PL_DHashTableRawRemove(&sNPObjWrappers, entry); + + OnWrapperDestroyed(); + } +} + // Look up or create a JSObject that wraps the NPObject npobj. // static diff --git a/modules/plugin/base/src/nsJSNPRuntime.h b/modules/plugin/base/src/nsJSNPRuntime.h index 2715e39df7e9..ac1f47e49952 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.h +++ b/modules/plugin/base/src/nsJSNPRuntime.h @@ -98,6 +98,7 @@ public: class nsNPObjWrapper { public: + static void OnDestroy(NPObject *npobj); static JSObject *GetNewOrUsed(NPP npp, JSContext *cx, NPObject *npobj); };