Bug 780831 - Guard against plugin code leaking refs in the JNI local ref table. r=snorp

This commit is contained in:
Kartikaya Gupta 2012-12-13 00:32:17 -05:00
Родитель 2db3b4a113
Коммит 036e2a1541
4 изменённых файлов: 26 добавлений и 13 удалений

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/PluginPRLibrary.h"
#include "nsPluginSafety.h"
// Some plugins on Windows, notably Quake Live, implement NP_Initialize using
// cdecl instead of the documented stdcall. In order to work around this,
// we force the caller to use a frame pointer.
@ -39,6 +40,8 @@ PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
if (!env)
return NS_ERROR_FAILURE;
mozilla::AutoLocalJNIFrame jniFrame(env);
if (mNP_Initialize) {
*error = mNP_Initialize(bFuncs, pFuncs, env);
} else {
@ -194,6 +197,8 @@ PluginPRLibrary::NPP_New(NPMIMEType pluginType, NPP instance,
{
if (!mNPP_New)
return NS_ERROR_FAILURE;
MAIN_THREAD_JNI_REF_GUARD;
*error = mNPP_New(pluginType, instance, mode, argc, argn, argv, saved);
return NS_OK;
}
@ -206,6 +211,7 @@ PluginPRLibrary::NPP_ClearSiteData(const char* site, uint64_t flags,
return NS_ERROR_NOT_AVAILABLE;
}
MAIN_THREAD_JNI_REF_GUARD;
NPError result = mNPP_ClearSiteData(site, flags, maxAge);
switch (result) {
@ -229,6 +235,7 @@ PluginPRLibrary::NPP_GetSitesWithData(InfallibleTArray<nsCString>& result)
result.Clear();
MAIN_THREAD_JNI_REF_GUARD;
char** sites = mNPP_GetSitesWithData();
if (!sites) {
return NS_OK;

Просмотреть файл

@ -519,19 +519,6 @@ nsNPAPIPluginInstance::Start()
// before returning. If the plugin returns failure, we'll clear it out below.
mRunning = RUNNING;
#if MOZ_WIDGET_ANDROID
// Flash creates some local JNI references during initialization (NPP_New). It does not
// remove these references later, so essentially they are leaked. AutoLocalJNIFrame
// prevents this by pushing a JNI frame. As a result, all local references created
// by Flash are contained in this frame. AutoLocalJNIFrame pops the frame once we
// go out of scope and the local references are deleted, preventing the leak.
JNIEnv* env = AndroidBridge::GetJNIEnv();
if (!env)
return NS_ERROR_FAILURE;
mozilla::AutoLocalJNIFrame frame(env);
#endif
nsresult newResult = library->NPP_New((char*)mimetype, &mNPP, (uint16_t)mode, count, (char**)names, (char**)values, NULL, &error);
mInPluginInitCall = oldVal;
@ -690,6 +677,7 @@ nsresult nsNPAPIPluginInstance::HandleEvent(void* event, int16_t* result)
#if defined(XP_WIN) || defined(XP_OS2)
NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event), this);
#else
MAIN_THREAD_JNI_REF_GUARD;
tmpResult = (*pluginFunctions->event)(&mNPP, event);
#endif
NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,
@ -1403,6 +1391,9 @@ PluginTimerCallback(nsITimer *aTimer, void *aClosure)
NPP npp = t->npp;
uint32_t id = t->id;
PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsNPAPIPluginInstance running plugin timer callback this=%p\n", npp->ndata));
MAIN_THREAD_JNI_REF_GUARD;
(*(t->callback))(npp, id);
// Make sure we still have an instance and the timer is still alive

Просмотреть файл

@ -863,6 +863,7 @@ nsNPAPIPluginStreamListener::HandleRedirectNotification(nsIChannel *oldChannel,
#if defined(XP_WIN) || defined(XP_OS2)
NS_TRY_SAFE_CALL_VOID((*pluginFunctions->urlredirectnotify)(npp, spec.get(), static_cast<int32_t>(status), mNPStreamWrapper->mNPStream.notifyData), mInst);
#else
MAIN_THREAD_JNI_REF_GUARD;
(*pluginFunctions->urlredirectnotify)(npp, spec.get(), static_cast<int32_t>(status), mNPStreamWrapper->mNPStream.notifyData);
#endif
return true;

Просмотреть файл

@ -10,6 +10,16 @@
#include "nsPluginHost.h"
#include <prinrval.h>
// On Android, we need to guard against plugin code leaking entries in the local
// JNI ref table. See https://bugzilla.mozilla.org/show_bug.cgi?id=780831#c21
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#define MAIN_THREAD_JNI_REF_GUARD mozilla::AutoLocalJNIFrame jniFrame
#else
#define MAIN_THREAD_JNI_REF_GUARD
#endif
#if defined(XP_WIN)
#define CALL_SAFETY_ON
#endif
@ -32,6 +42,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
MAIN_THREAD_JNI_REF_GUARD; \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
ret = fun; \
@ -55,6 +66,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
MAIN_THREAD_JNI_REF_GUARD; \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
if(gSkipPluginSafeCalls) \
fun; \
@ -79,6 +91,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
PR_BEGIN_MACRO \
MAIN_THREAD_JNI_REF_GUARD; \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
ret = fun; \
NS_NotifyPluginCall(startTime); \
@ -86,6 +99,7 @@ PR_END_MACRO
#define NS_TRY_SAFE_CALL_VOID(fun, pluginInst) \
PR_BEGIN_MACRO \
MAIN_THREAD_JNI_REF_GUARD; \
PRIntervalTime startTime = NS_NotifyBeginPluginCall(); \
fun; \
NS_NotifyPluginCall(startTime); \