Fix Components.utils.evalInSandbox bugs: 1) GC'ing after even eval blows performance, no need; 2) borrowing the calling cx's error reporter doesn't work, we must turn uncaught exception errors back into thrown exceptions on the calling cx (301353, r+sr+a=shaver).

This commit is contained in:
brendan%mozilla.org 2005-07-20 03:35:40 +00:00
Родитель 2a1e999a12
Коммит 7b8f6fcef2
3 изменённых файлов: 74 добавлений и 47 удалений

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

@ -4474,6 +4474,13 @@ JS_ErrorFromException(JSContext *cx, jsval v)
#endif
}
JS_PUBLIC_API(JSBool)
JS_ThrowReportedError(JSContext *cx, const char *message,
JSErrorReport *reportp)
{
js_ErrorToException(cx, message, reportp);
}
#ifdef JS_THREADSAFE
JS_PUBLIC_API(jsword)
JS_GetContextThread(JSContext *cx)

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

@ -1902,6 +1902,14 @@ JS_DropExceptionState(JSContext *cx, JSExceptionState *state);
extern JS_PUBLIC_API(JSErrorReport *)
JS_ErrorFromException(JSContext *cx, jsval v);
/*
* Given a reported error's message and JSErrorReport struct pointer, throw
* the corresponding exception on cx.
*/
extern JS_PUBLIC_API(JSBool)
JS_ThrowReportedError(JSContext *cx, const char *message,
JSErrorReport *reportp);
#ifdef JS_THREADSAFE
/*

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

@ -82,13 +82,13 @@ char* xpc_CloneAllAccess()
char * xpc_CheckAccessList(const PRUnichar* wideName, const char* list[])
{
nsCAutoString asciiName;
nsCAutoString asciiName;
CopyUTF16toUTF8(nsDependentString(wideName), asciiName);
for(const char** p = list; *p; p++)
if(!strcmp(*p, asciiName.get()))
return xpc_CloneAllAccess();
return nsnull;
}
#endif
@ -154,7 +154,7 @@ nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
{
case JSENUMERATE_INIT:
{
if(!mManager ||
if(!mManager ||
NS_FAILED(mManager->EnumerateInterfaces(&e)) || !e ||
NS_FAILED(e->First()))
@ -173,7 +173,7 @@ nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
nsCOMPtr<nsISupports> isup;
e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
while(1)
{
if(NS_ENUMERATOR_FALSE == e->IsDone() &&
@ -187,7 +187,7 @@ nsXPCComponents_Interfaces::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
const char* name;
PRBool scriptable;
if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
!scriptable)
{
continue;
@ -235,7 +235,7 @@ nsXPCComponents_Interfaces::NewResolve(nsIXPConnectWrappedNative *wrapper,
if(!info)
return NS_OK;
nsCOMPtr<nsIJSIID> nsid =
nsCOMPtr<nsIJSIID> nsid =
dont_AddRef(NS_STATIC_CAST(nsIJSIID*, nsJSIID::NewID(info)));
if(nsid)
@ -383,7 +383,7 @@ nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
{
case JSENUMERATE_INIT:
{
if(!mManager ||
if(!mManager ||
NS_FAILED(mManager->EnumerateInterfaces(&e)) || !e ||
NS_FAILED(e->First()))
@ -402,7 +402,7 @@ nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
nsCOMPtr<nsISupports> isup;
e = (nsIEnumerator*) JSVAL_TO_PRIVATE(*statep);
while(1)
{
if(NS_ENUMERATOR_FALSE == e->IsDone() &&
@ -417,7 +417,7 @@ nsXPCComponents_InterfacesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
JSString* jsstr;
PRBool scriptable;
if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
if(NS_SUCCEEDED(iface->IsScriptable(&scriptable)) &&
!scriptable)
{
continue;
@ -475,7 +475,7 @@ name)).get()))
if(!info)
return NS_OK;
nsCOMPtr<nsIJSIID> nsid =
nsCOMPtr<nsIJSIID> nsid =
dont_AddRef(NS_STATIC_CAST(nsIJSIID*, nsJSIID::NewID(info)));
if (!nsid)
@ -610,8 +610,8 @@ nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
{
case JSENUMERATE_INIT:
{
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
NS_FAILED(compMgr->EnumerateContractIDs(&e)) || !e )
{
*statep = JSVAL_NULL;
@ -628,7 +628,7 @@ nsXPCComponents_Classes::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
nsCOMPtr<nsISupports> isup;
PRBool hasMore;
e = (nsISimpleEnumerator*) JSVAL_TO_PRIVATE(*statep);
if(NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup)
{
@ -766,8 +766,8 @@ nsXPCComponents_ClassesByID::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
{
case JSENUMERATE_INIT:
{
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
NS_FAILED(compMgr->EnumerateCIDs(&e)) || !e )
{
*statep = JSVAL_NULL;
@ -825,8 +825,8 @@ IsRegisteredCLSID(const char* str)
if(!id.Parse(str))
return PR_FALSE;
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
nsCOMPtr<nsIComponentRegistrar> compMgr;
if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr ||
NS_FAILED(compMgr->IsCIDRegistered(id, &registered)))
return PR_FALSE;
@ -1666,7 +1666,7 @@ nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper,
{
nsCOMPtr<nsIInterfaceInfo> info;
xpc->GetInfoForIID(&NS_GET_IID(nsISupports), getter_AddRefs(info));
if(info)
{
cInterfaceID =
@ -1817,7 +1817,7 @@ nsXPCComponents_Utils::LookupMethod()
// to this object - though we don't verify that it is to this exact method)
nsCOMPtr<nsISupports> callee;
cc->GetCallee(getter_AddRefs(callee));
if(!callee || callee.get() !=
if(!callee || callee.get() !=
NS_STATIC_CAST(const nsISupports*,
NS_STATIC_CAST(const nsIXPCComponents_Utils*,this)))
return NS_ERROR_FAILURE;
@ -1879,7 +1879,7 @@ nsXPCComponents_Utils::LookupMethod()
XPCNativeMember* member = inner_cc.GetMember();
if(!member || member->IsConstant())
return NS_ERROR_XPC_BAD_CONVERT_JS;
// it would a be a big surprise if there is a member without an interface :)
XPCNativeInterface* iface = inner_cc.GetInterface();
if(!iface)
@ -1890,8 +1890,8 @@ nsXPCComponents_Utils::LookupMethod()
if(!member->GetValue(inner_cc, iface, &funval))
return NS_ERROR_XPC_BAD_CONVERT_JS;
// clone a function we can use for this object
JSObject* funobj = xpc_CloneJSFunction(inner_cc, JSVAL_TO_OBJECT(funval),
// clone a function we can use for this object
JSObject* funobj = xpc_CloneJSFunction(inner_cc, JSVAL_TO_OBJECT(funval),
wrapper->GetFlatJSObject());
if(!funobj)
return NS_ERROR_XPC_BAD_CONVERT_JS;
@ -1932,7 +1932,7 @@ nsXPCComponents_Utils::ReportError()
// to this object - though we don't verify that it is to this exact method)
nsCOMPtr<nsISupports> callee;
cc->GetCallee(getter_AddRefs(callee));
if(!callee || callee.get() !=
if(!callee || callee.get() !=
NS_STATIC_CAST(const nsISupports*,
NS_STATIC_CAST(const nsIXPCComponents_Utils*,this))) {
NS_ERROR("reportError() must only be called from JS!");
@ -2032,7 +2032,7 @@ SandboxDump(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
JSString *str;
if (!argc)
return JS_TRUE;
str = JS_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
@ -2083,6 +2083,18 @@ static JSFunctionSpec SandboxFunctions[] = {
#endif /* !XPCONNECT_STANDALONE */
/*
* Throw an exception on caller_cx that is made from message and report,
* which were reported as uncaught on cx.
*/
static void
SandboxErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
{
JSContext *caller_cx = NS_STATIC_CAST(JSContext*, JS_GetContextPrivate(cx));
JS_ThrowReportedError(caller_cx, message, report);
}
/* void evalInSandbox(in AString source, in AUTF8String codebase); */
NS_IMETHODIMP
nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
@ -2092,7 +2104,7 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
return NS_ERROR_NOT_AVAILABLE;
#else
nsresult rv;
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));
if(NS_FAILED(rv))
return rv;
@ -2145,10 +2157,10 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
JS_ReportError(cx, "Can't create URL for evalInSandbox");
return rv;
}
JSPrincipals *jsPrincipals;
nsCOMPtr<nsIPrincipal> principal;
nsCOMPtr<nsIScriptSecurityManager> secman =
nsCOMPtr<nsIScriptSecurityManager> secman =
do_GetService(kScriptSecurityManagerContractID);
if(!secman ||
NS_FAILED(secman->GetCodebasePrincipal(iURL,
@ -2159,7 +2171,7 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
JS_ReportError(cx, "Can't get principals for evalInSandbox");
return NS_ERROR_FAILURE;
}
JSContext *sandcx = JS_NewContext(JS_GetRuntime(cx), 1024);
if(!sandcx) {
JS_ReportError(cx, "Can't prepare context for evalInSandbox");
@ -2174,7 +2186,7 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
JSPRINCIPALS_DROP(cx, jsPrincipals);
return NS_ERROR_OUT_OF_MEMORY;
}
rv = xpc->InitClasses(sandcx, sandbox);
if (NS_SUCCEEDED(rv) &&
!JS_DefineFunctions(sandcx, sandbox, SandboxFunctions)) {
@ -2184,21 +2196,21 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
JS_DestroyContext(sandcx);
JSPRINCIPALS_DROP(cx, jsPrincipals);
return rv;
}
}
}
}
JS_SetGlobalObject(sandcx, sandbox);
// There's no JS_GetErrorReporter, so we fake it
JSErrorReporter borrowedReporter = JS_SetErrorReporter(cx, nsnull);
JS_SetErrorReporter(sandcx, borrowedReporter);
JS_SetErrorReporter(cx, borrowedReporter);
if(!JS_EvaluateUCScriptForPrincipals(sandcx, sandbox, jsPrincipals,
NS_REINTERPRET_CAST(const jschar *,
PromiseFlatString(source).get()),
source.Length(),
PromiseFlatUTF8String(codebase).get(),
1, rval)) {
// Capture uncaught exceptions reported as errors on sandcx and
// re-throw them on cx.
JS_SetContextPrivate(sandcx, cx);
JS_SetErrorReporter(sandcx, SandboxErrorReporter);
if (!JS_EvaluateUCScriptForPrincipals(sandcx, sandbox, jsPrincipals,
NS_REINTERPRET_CAST(const jschar *,
PromiseFlatString(source).get()),
source.Length(),
PromiseFlatUTF8String(codebase).get(),
1, rval)) {
rv = NS_ERROR_FAILURE;
}
@ -2206,8 +2218,8 @@ nsXPCComponents_Utils::EvalInSandbox(const nsAString &source,
*rval = OBJECT_TO_JSVAL(sandbox);
cc->SetReturnValueWasSet(PR_TRUE);
}
JS_DestroyContext(sandcx);
JS_DestroyContextNoGC(sandcx);
JSPRINCIPALS_DROP(cx, jsPrincipals);
return rv;
#endif /* !XPCONNECT_STANDALONE */
@ -2287,7 +2299,7 @@ nsXPCComponents::~nsXPCComponents()
ClearMembers();
}
void
void
nsXPCComponents::ClearMembers()
{
NS_IF_RELEASE(mInterfaces);
@ -2506,7 +2518,7 @@ NS_IMETHODIMP nsXPCComponents::LookupMethod()
nsresult rv;
nsCOMPtr<nsIXPCComponents_Utils> utils;
NS_WARNING("Components.lookupMethod deprecated, use Components.utils.lookupMethod");
NS_WARNING("Components.lookupMethod deprecated, use Components.utils.lookupMethod");
rv = GetUtils(getter_AddRefs(utils));
if (NS_FAILED(rv))
return rv;
@ -2520,7 +2532,7 @@ NS_IMETHODIMP nsXPCComponents::ReportError()
nsresult rv;
nsCOMPtr<nsIXPCComponents_Utils> utils;
NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
NS_WARNING("Components.reportError deprecated, use Components.utils.reportError");
rv = GetUtils(getter_AddRefs(utils));
if (NS_FAILED(rv))
return rv;