From 7b8f6fcef267c99527732c541fc2d97f94fb977b Mon Sep 17 00:00:00 2001 From: "brendan%mozilla.org" Date: Wed, 20 Jul 2005 03:35:40 +0000 Subject: [PATCH] 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). --- js/src/jsapi.c | 7 ++ js/src/jsapi.h | 8 ++ js/src/xpconnect/src/xpccomponents.cpp | 106 ++++++++++++++----------- 3 files changed, 74 insertions(+), 47 deletions(-) diff --git a/js/src/jsapi.c b/js/src/jsapi.c index 209b1ecc7c9..e5b27d1f5f7 100644 --- a/js/src/jsapi.c +++ b/js/src/jsapi.c @@ -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) diff --git a/js/src/jsapi.h b/js/src/jsapi.h index cb78d801f0c..1f590d4326b 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -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 /* diff --git a/js/src/xpconnect/src/xpccomponents.cpp b/js/src/xpconnect/src/xpccomponents.cpp index 051b03c0e1c..3e3aba7bc50 100644 --- a/js/src/xpconnect/src/xpccomponents.cpp +++ b/js/src/xpconnect/src/xpccomponents.cpp @@ -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 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 nsid = + nsCOMPtr 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 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 nsid = + nsCOMPtr 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 compMgr; - if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || + nsCOMPtr 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 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 compMgr; - if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || + nsCOMPtr 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 compMgr; - if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || + nsCOMPtr compMgr; + if(NS_FAILED(NS_GetComponentRegistrar(getter_AddRefs(compMgr))) || !compMgr || NS_FAILED(compMgr->IsCIDRegistered(id, ®istered))) return PR_FALSE; @@ -1666,7 +1666,7 @@ nsXPCComponents_Constructor::CallOrConstruct(nsIXPConnectWrappedNative *wrapper, { nsCOMPtr 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 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 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 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 principal; - nsCOMPtr secman = + nsCOMPtr 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 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 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;