mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Fixing bug 202994. Make sure the proper security check is done when converting the result of a JS expression in a javascript: URL to a string. r=mstoltz@netscape.com, sr=brendan@mozilla.org, a=asa@mozilla.org
This commit is contained in:
parent
148c24f654
commit
72ec343461
@ -2047,7 +2047,7 @@ nsScriptSecurityManager::SavePrincipal(nsIPrincipal* aToSave)
|
||||
///////////////// Capabilities API /////////////////////
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
|
||||
PRBool *result)
|
||||
PRBool *result)
|
||||
{
|
||||
nsresult rv;
|
||||
JSStackFrame *fp = nsnull;
|
||||
@ -2097,9 +2097,12 @@ nsScriptSecurityManager::IsCapabilityEnabled(const char *capability,
|
||||
|
||||
if (!previousPrincipal)
|
||||
{
|
||||
// No principals on the stack, all native code. Allow execution.
|
||||
*result = PR_TRUE;
|
||||
// No principals on the stack, all native code. Allow
|
||||
// execution if the subject principal is the system principal.
|
||||
|
||||
return SubjectPrincipalIsSystem(result);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -617,6 +617,61 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
||||
|
||||
}
|
||||
|
||||
// Helper function to convert a jsval to an nsAString, and set
|
||||
// exception flags if the conversion fails.
|
||||
static nsresult
|
||||
JSValueToAString(JSContext *cx, jsval val, nsAString *result,
|
||||
PRBool *isUndefined)
|
||||
{
|
||||
if (isUndefined) {
|
||||
*isUndefined = JSVAL_IS_VOID(val);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSString* jsstring = ::JS_ValueToString(cx, val);
|
||||
if (jsstring) {
|
||||
result->Assign(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
::JS_GetStringChars(jsstring)),
|
||||
::JS_GetStringLength(jsstring));
|
||||
} else {
|
||||
result->Truncate();
|
||||
|
||||
// We failed to convert val to a string. We're either OOM, or the
|
||||
// security manager denied access to .toString(), or somesuch, on
|
||||
// an object. Treat this case as if the result were undefined.
|
||||
|
||||
if (isUndefined) {
|
||||
*isUndefined = PR_TRUE;
|
||||
}
|
||||
|
||||
if (!::JS_IsExceptionPending(cx)) {
|
||||
// JS_ValueToString() returned null w/o an exception
|
||||
// pending. That means we're OOM.
|
||||
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// We've got a pending exception. Tell XPConnect's current native
|
||||
// call context (if any) about this exception so that it doesn't
|
||||
// keep going as if nothing happened.
|
||||
|
||||
nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID()));
|
||||
|
||||
if (xpc) {
|
||||
nsCOMPtr<nsIXPCNativeCallContext> nccx;
|
||||
xpc->GetCurrentNativeCallContext(getter_AddRefs(nccx));
|
||||
if (nccx) {
|
||||
nccx->SetExceptionWasThrown(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::EvaluateString(const nsAString& aScript,
|
||||
void *aScopeObject,
|
||||
@ -720,18 +775,7 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
||||
|
||||
// If all went well, convert val to a string (XXXbe unless undefined?).
|
||||
if (ok) {
|
||||
if (aIsUndefined) {
|
||||
*aIsUndefined = JSVAL_IS_VOID(val);
|
||||
}
|
||||
|
||||
JSString* jsstring = ::JS_ValueToString(mContext, val);
|
||||
if (jsstring) {
|
||||
aRetValue.Assign(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
::JS_GetStringChars(jsstring)),
|
||||
::JS_GetStringLength(jsstring));
|
||||
} else {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
rv = JSValueToAString(mContext, val, &aRetValue, aIsUndefined);
|
||||
}
|
||||
else {
|
||||
if (aIsUndefined) {
|
||||
@ -869,20 +913,8 @@ nsJSContext::ExecuteScript(void* aScriptObject,
|
||||
|
||||
if (ok) {
|
||||
// If all went well, convert val to a string (XXXbe unless undefined?).
|
||||
if (aIsUndefined) {
|
||||
*aIsUndefined = JSVAL_IS_VOID(val);
|
||||
}
|
||||
|
||||
if (aRetValue) {
|
||||
JSString* jsstring = ::JS_ValueToString(mContext, val);
|
||||
if (jsstring) {
|
||||
aRetValue->Assign(NS_REINTERPRET_CAST(const PRUnichar*,
|
||||
::JS_GetStringChars(jsstring)),
|
||||
::JS_GetStringLength(jsstring));
|
||||
} else {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
|
||||
} else {
|
||||
if (aIsUndefined) {
|
||||
*aIsUndefined = PR_TRUE;
|
||||
|
@ -233,8 +233,8 @@ nsDOMSOFactory::Observe(nsISupports *aSubject,
|
||||
#ifdef MOZ_XUL
|
||||
// Flush the XUL cache since it holds JS roots, and we're about to
|
||||
// start the final GC.
|
||||
static NS_DEFINE_CID(kXULPrototypeCacheCID, NS_XULPROTOTYPECACHE_CID);
|
||||
nsCOMPtr<nsIXULPrototypeCache> cache(do_GetService(kXULPrototypeCacheCID));
|
||||
nsCOMPtr<nsIXULPrototypeCache> cache =
|
||||
do_GetService("@mozilla.org/xul/xul-prototype-cache;1");
|
||||
|
||||
if (cache)
|
||||
cache->Flush();
|
||||
|
@ -66,6 +66,7 @@
|
||||
#include "nsXPIDLString.h"
|
||||
#include "prprf.h"
|
||||
#include "nsEscape.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
|
||||
static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
|
||||
static NS_DEFINE_CID(kWindowMediatorCID, NS_WINDOWMEDIATOR_CID);
|
||||
@ -157,6 +158,8 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSObject *globalJSObject = global->GetGlobalJSObject();
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWindow(do_QueryInterface(global, &rv));
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -174,7 +177,6 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
||||
// if necessary. So, basically, this call ensures that a document gets
|
||||
// created -- if necessary.
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
|
||||
rv = domWindow->GetDocument(getter_AddRefs(doc));
|
||||
NS_ASSERTION(doc, "No DOMDocument!");
|
||||
if (NS_FAILED(rv)) {
|
||||
@ -188,6 +190,31 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
||||
|
||||
if (!scriptContext) return NS_ERROR_FAILURE;
|
||||
|
||||
// Grab a context to evaluate the javascript: URL on. If the
|
||||
// evaluation of a javascript: URL is caused by some running
|
||||
// script, use the context of the running script. If no JS is
|
||||
// running, use the context of the window where the javascript:
|
||||
// URL is being evaluated.
|
||||
nsCOMPtr<nsIScriptContext> evalContext;
|
||||
|
||||
nsCOMPtr<nsIJSContextStack> stack =
|
||||
do_GetService("@mozilla.org/js/xpc/ContextStack;1");
|
||||
if (stack) {
|
||||
JSContext *cx;
|
||||
if (NS_SUCCEEDED(stack->Peek(&cx)) && cx &&
|
||||
(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
|
||||
nsISupports *supports =
|
||||
NS_STATIC_CAST(nsISupports*, ::JS_GetContextPrivate(cx));
|
||||
|
||||
evalContext = do_QueryInterface(supports);
|
||||
}
|
||||
}
|
||||
|
||||
if (!evalContext) {
|
||||
// No JS on the stack, use the window's context.
|
||||
evalContext = scriptContext;
|
||||
}
|
||||
|
||||
// Unescape the script
|
||||
NS_UnescapeURL(script);
|
||||
|
||||
@ -221,7 +248,7 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
||||
nsCOMPtr<nsIPrincipal> objectPrincipal;
|
||||
rv = securityManager->GetObjectPrincipal(
|
||||
(JSContext*)scriptContext->GetNativeContext(),
|
||||
global->GetGlobalJSObject(),
|
||||
globalJSObject,
|
||||
getter_AddRefs(objectPrincipal));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -267,17 +294,15 @@ nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel)
|
||||
// Finally, we have everything needed to evaluate the expression.
|
||||
nsString result;
|
||||
PRBool bIsUndefined;
|
||||
{
|
||||
NS_ConvertUTF8toUCS2 scriptString(script);
|
||||
rv = scriptContext->EvaluateString(scriptString,
|
||||
nsnull, // obj
|
||||
principal,
|
||||
url.get(), // url
|
||||
1, // line no
|
||||
nsnull,
|
||||
result,
|
||||
&bIsUndefined);
|
||||
}
|
||||
|
||||
rv = evalContext->EvaluateString(NS_ConvertUTF8toUCS2(script),
|
||||
globalJSObject, // obj
|
||||
principal,
|
||||
url.get(), // url
|
||||
1, // line no
|
||||
nsnull,
|
||||
result,
|
||||
&bIsUndefined);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = NS_ERROR_MALFORMED_URI;
|
||||
|
Loading…
Reference in New Issue
Block a user