test for bug 550026 r=karlt+cjones

This commit is contained in:
Chris Jones ext:(%20and%20Karl%20Tomlinson%20%3Ckarlt%2B%40karlt.net%3E) 2010-03-08 09:17:57 +13:00
Родитель 3cbb7db096
Коммит 5cbf4d155d
6 изменённых файлов: 154 добавлений и 7 удалений

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

@ -116,6 +116,7 @@ endif
ifeq (gtk2,$(MOZ_WIDGET_TOOLKIT))
_MOCHITEST_FILES += \
test_copyText.html \
test_crash_nested_loop.html \
$(NULL)
endif

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

@ -0,0 +1,40 @@
<head>
<title>Plugin crashing in nested loop</title>
<script type="application/javascript" src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<body>
<iframe id="iframe1" src="crashing_subpage.html" width="600" height="600"></iframe>
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var iframe = document.getElementById('iframe1');
window.frameLoaded = function frameLoaded_toCrash() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var prefs = Components.classes['@mozilla.org/preferences-service;1']
.getService(Components.interfaces.nsIPrefBranch);
if (!prefs.getBoolPref('dom.ipc.plugins.enabled')) {
ok(true, "Skipping this test when IPC plugins are not enabled.");
SimpleTest.finish();
return;
}
var p = iframe.contentDocument.getElementById('plugin1');
try {
p.crashInNestedLoop();
ok(false, "p.crashInNestedLoop() should throw an exception");
}
catch (e) {
ok(true, "p.crashInNestedLoop() should throw an exception");
}
// this test is for bug 550026, which is inherently
// nondeterministic. if we hit that bug, the browser process
// would have crashed by now. if not, we'll pass "spuriously"
SimpleTest.finish();
}
</script>

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

@ -60,6 +60,8 @@
#define PLUGIN_VERSION "1.0.0.0"
#define ARRAY_LENGTH(a) (sizeof(a)/sizeof(a[0]))
#define STATIC_ASSERT(condition) \
extern void np_static_assert(int arg[(condition) ? 1 : -1])
//
// Intentional crash
@ -67,7 +69,7 @@
int gCrashCount = 0;
static void
void
NoteIntentionalCrash()
{
char* bloatLog = getenv("XPCOM_MEM_BLOAT_LOG");
@ -87,11 +89,9 @@ NoteIntentionalCrash()
}
}
static void
void
IntentionalCrash()
{
NoteIntentionalCrash();
int *pi = NULL;
*pi = 55; // Crash dereferencing null pointer
++gCrashCount;
@ -156,6 +156,7 @@ static bool checkGCRace(NPObject* npobj, const NPVariant* args, uint32_t argCoun
static bool hangPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool callOnDestroy(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static bool crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result);
static const NPUTF8* sPluginMethodIdentifierNames[] = {
"npnEvaluateTest",
@ -197,9 +198,10 @@ static const NPUTF8* sPluginMethodIdentifierNames[] = {
"hang",
"getClipboardText",
"callOnDestroy",
"crashInNestedLoop",
};
static NPIdentifier sPluginMethodIdentifiers[ARRAY_LENGTH(sPluginMethodIdentifierNames)];
static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMethodIdentifierNames)] = {
static const ScriptableFunction sPluginMethodFunctions[] = {
npnEvaluateTest,
npnInvokeTest,
npnInvokeDefaultTest,
@ -239,8 +241,12 @@ static const ScriptableFunction sPluginMethodFunctions[ARRAY_LENGTH(sPluginMetho
hangPlugin,
getClipboardText,
callOnDestroy,
crashPluginInNestedLoop,
};
STATIC_ASSERT(ARRAY_LENGTH(sPluginMethodIdentifierNames) ==
ARRAY_LENGTH(sPluginMethodFunctions));
struct URLNotifyData
{
const char* cookie;
@ -705,6 +711,7 @@ NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char*
instanceData->npnNewStream = true;
}
if (strcmp(argn[i], "newcrash") == 0) {
NoteIntentionalCrash();
IntentionalCrash();
}
}
@ -787,8 +794,10 @@ NPP_Destroy(NPP instance, NPSavedData** save)
printf("NPP_Destroy\n");
InstanceData* instanceData = (InstanceData*)(instance->pdata);
if (instanceData->crashOnDestroy)
if (instanceData->crashOnDestroy) {
NoteIntentionalCrash();
IntentionalCrash();
}
if (instanceData->callOnDestroy) {
NPVariant result;
@ -2145,6 +2154,7 @@ streamTest(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant*
static bool
crashPlugin(NPObject* npobj, const NPVariant* args, uint32_t argCount, NPVariant* result)
{
NoteIntentionalCrash();
IntentionalCrash();
VOID_TO_NPVARIANT(*result);
return true;
@ -2631,12 +2641,29 @@ getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
return true;
}
bool
crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args,
uint32_t argCount, NPVariant* result)
{
NPP npp = static_cast<TestNPObject*>(npobj)->npp;
InstanceData* id = static_cast<InstanceData*>(npp->pdata);
return pluginCrashInNestedLoop(id);
}
#else
bool
getClipboardText(NPObject* npobj, const NPVariant* args, uint32_t argCount,
NPVariant* result)
{
/// XXX Not implemented!
// XXX Not implemented!
return false;
}
bool
crashPluginInNestedLoop(NPObject* npobj, const NPVariant* args,
uint32_t argCount, NPVariant* result)
{
// XXX Not implemented!
return false;
}
#endif

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

@ -127,4 +127,7 @@ typedef struct InstanceData {
void notifyDidPaint(InstanceData* instanceData);
void NoteIntentionalCrash();
void IntentionalCrash();
#endif // nptest_h_

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

@ -35,12 +35,15 @@
#include "nptest_platform.h"
#include "npapi.h"
#include <pthread.h>
#include <gdk/gdk.h>
#ifdef MOZ_X11
#include <gdk/gdkx.h>
#include <X11/extensions/shape.h>
#endif
#include <glib.h>
#include <gtk/gtk.h>
#include <unistd.h>
using namespace std;
@ -635,3 +638,68 @@ pluginGetClipboardText(InstanceData* instanceData)
return retText;
}
//-----------------------------------------------------------------------------
// NB: this test is quite gross in that it's not only
// nondeterministic, but dependent on the guts of the nested glib
// event loop handling code in PluginModule. We first sleep long
// enough to make sure that the "detection timer" will be pending when
// we enter the nested glib loop, then similarly for the "process browser
// events" timer. Then we "schedule" the crasher thread to run at about the
// same time we expect that the PluginModule "process browser events" task
// will run. If all goes well, the plugin process will crash and generate the
// XPCOM "plugin crashed" task, and the browser will run that task while still
// in the "process some events" loop.
static void*
CrasherThread(void* data)
{
// Give the parent thread a chance to send the message.
usleep(200);
IntentionalCrash();
// not reached
return(NULL);
}
bool
pluginCrashInNestedLoop(InstanceData* instanceData)
{
// wait at least long enough for nested loop detector task to be pending ...
sleep(1);
// Run the nested loop detector. Other events are not expected.
if (!g_main_context_iteration(NULL, TRUE)) {
g_warning("DetectNestedEventLoop did not fire");
return true; // trigger a test failure
}
// wait at least long enough for the "process browser events" task to be
// pending ...
sleep(1);
// we'll be crashing soon, note that fact now to avoid messing with
// timing too much
NoteIntentionalCrash();
// schedule the crasher thread ...
pthread_t crasherThread;
if (0 != pthread_create(&crasherThread, NULL, CrasherThread, NULL)) {
g_warning("Failed to create thread");
return true; // trigger a test failure
}
// .. and hope the time it takes to spawn means that it crashes at about the
// same time as the "process browser events" task that should run next is
// being processed in the parent. Other events are not expected.
if (g_main_context_iteration(NULL, TRUE)) {
g_warning("Should have crashed in ProcessBrowserEvents");
} else {
g_warning("ProcessBrowserEvents did not fire");
}
// if we get here without crashing, then we'll trigger a test failure
return true;
}

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

@ -126,4 +126,12 @@ void pluginDoInternalConsistencyCheck(InstanceData* instanceData, std::string& e
*/
std::string pluginGetClipboardText(InstanceData* instanceData);
/**
* Crash while in a nested event loop. The goal is to catch the
* browser processing the XPCOM event generated from the plugin's
* crash while other plugin code is still on the stack.
* See https://bugzilla.mozilla.org/show_bug.cgi?id=550026.
*/
bool pluginCrashInNestedLoop(InstanceData* instanceData);
#endif // nptest_platform_h_