зеркало из https://github.com/mozilla/gecko-dev.git
Bug 504021 - Add an API to the script security manager to clamp principals for a given context. r=jst/bzbarsky sr=dveditz
This commit is contained in:
Родитель
c77dd603f8
Коммит
7050590b13
|
@ -41,7 +41,7 @@
|
|||
interface nsIURI;
|
||||
interface nsIChannel;
|
||||
|
||||
[scriptable, uuid(f8e350b9-9f31-451a-8c8f-d10fea26b780)]
|
||||
[scriptable, uuid(c0dbfd5e-b7ae-4c18-8674-82492f35d715)]
|
||||
interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
||||
{
|
||||
///////////////// Security Checks //////////////////
|
||||
|
@ -319,6 +319,29 @@ interface nsIScriptSecurityManager : nsIXPCSecurityManager
|
|||
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipal(in JSContextPtr cx);
|
||||
[noscript,notxpcom] nsIPrincipal getCxSubjectPrincipalAndFrame(in JSContextPtr cx,
|
||||
out JSStackFramePtr fp);
|
||||
|
||||
/**
|
||||
* If no scripted code is running "above" (or called from) fp, then
|
||||
* instead of looking at cx->globalObject, we will return |principal|.
|
||||
* This function only affects |cx|. If someone pushes another context onto
|
||||
* the context stack, then it supercedes this call.
|
||||
* NOTE: If |fp| is non-null popContextPrincipal must be called before fp
|
||||
* has finished executing.
|
||||
*
|
||||
* @param cx The context to clamp.
|
||||
* @param fp The frame pointer to clamp at. May be 'null'.
|
||||
* @param principal The principal to clamp to.
|
||||
*/
|
||||
[noscript] void pushContextPrincipal(in JSContextPtr cx,
|
||||
in JSStackFramePtr fp,
|
||||
in nsIPrincipal principal);
|
||||
|
||||
/**
|
||||
* Removes a clamp set by pushContextPrincipal from cx. This must be
|
||||
* called in a stack-like fashion (e.g., given two contexts |a| and |b|,
|
||||
* it is not legal to do: push(a) push(b) pop(a)).
|
||||
*/
|
||||
[noscript] void popContextPrincipal(in JSContextPtr cx);
|
||||
};
|
||||
|
||||
%{C++
|
||||
|
|
|
@ -486,15 +486,15 @@ private:
|
|||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no script for the
|
||||
// context. Callers MUST pass in a non-null rv here.
|
||||
static nsIPrincipal*
|
||||
nsIPrincipal*
|
||||
GetSubjectPrincipal(JSContext* cx, nsresult* rv);
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no script for the frame.
|
||||
// Callers MUST pass in a non-null rv here.
|
||||
static nsIPrincipal*
|
||||
nsIPrincipal*
|
||||
GetFramePrincipal(JSContext* cx, JSStackFrame* fp, nsresult* rv);
|
||||
|
||||
|
||||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no script. Callers MUST
|
||||
// pass in a non-null rv here.
|
||||
|
@ -514,7 +514,7 @@ private:
|
|||
// Returns null if a principal cannot be found. Note that rv can be NS_OK
|
||||
// when this happens -- this means that there was no script
|
||||
// running. Callers MUST pass in a non-null rv here.
|
||||
static nsIPrincipal*
|
||||
nsIPrincipal*
|
||||
GetPrincipalAndFrame(JSContext *cx,
|
||||
JSStackFrame** frameResult,
|
||||
nsresult* rv);
|
||||
|
@ -601,6 +601,17 @@ private:
|
|||
PrintPolicyDB();
|
||||
#endif
|
||||
|
||||
struct ContextPrincipal {
|
||||
ContextPrincipal(ContextPrincipal *next, JSContext *cx,
|
||||
JSStackFrame *fp, nsIPrincipal *principal)
|
||||
: mNext(next), mCx(cx), mFp(fp), mPrincipal(principal) {}
|
||||
|
||||
ContextPrincipal *mNext;
|
||||
JSContext *mCx;
|
||||
JSStackFrame *mFp;
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
};
|
||||
|
||||
// JS strings we need to clean up on shutdown
|
||||
static jsval sEnabledID;
|
||||
|
||||
|
@ -618,6 +629,7 @@ private:
|
|||
nsCOMPtr<nsISecurityPref> mSecurityPref;
|
||||
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
|
||||
nsCOMPtr<nsIPrincipal> mSystemCertificate;
|
||||
ContextPrincipal *mContextPrincipals;
|
||||
nsInterfaceHashtable<PrincipalKey, nsIPrincipal> mPrincipals;
|
||||
PRPackedBool mIsJavaScriptEnabled;
|
||||
PRPackedBool mIsWritingPrefs;
|
||||
|
|
|
@ -402,6 +402,32 @@ nsScriptSecurityManager::GetCxSubjectPrincipalAndFrame(JSContext *cx, JSStackFra
|
|||
return principal;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::PushContextPrincipal(JSContext *cx,
|
||||
JSStackFrame *fp,
|
||||
nsIPrincipal *principal)
|
||||
{
|
||||
ContextPrincipal *cp = new ContextPrincipal(mContextPrincipals, cx, fp,
|
||||
principal);
|
||||
if (!cp)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mContextPrincipals = cp;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsScriptSecurityManager::PopContextPrincipal(JSContext *cx)
|
||||
{
|
||||
NS_ASSERTION(mContextPrincipals->mCx == cx, "Mismatched push/pop");
|
||||
|
||||
ContextPrincipal *next = mContextPrincipals->mNext;
|
||||
delete mContextPrincipals;
|
||||
mContextPrincipals = next;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Policy Storage //
|
||||
////////////////////
|
||||
|
@ -2196,7 +2222,6 @@ nsScriptSecurityManager::GetFunctionObjectPrincipal(JSContext *cx,
|
|||
return GetScriptPrincipal(cx, script, rv);
|
||||
}
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
||||
JSStackFrame *fp,
|
||||
|
@ -2226,22 +2251,36 @@ nsScriptSecurityManager::GetFramePrincipal(JSContext *cx,
|
|||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
|
||||
JSStackFrame **frameResult,
|
||||
nsresult* rv)
|
||||
{
|
||||
NS_PRECONDITION(rv, "Null out param");
|
||||
NS_PRECONDITION(rv, "Null out param");
|
||||
//-- If there's no principal on the stack, look at the global object
|
||||
// and return the innermost frame for annotations.
|
||||
*rv = NS_OK;
|
||||
|
||||
if (cx)
|
||||
{
|
||||
// Get principals from innermost frame of JavaScript or Java.
|
||||
JSStackFrame *target = nsnull;
|
||||
nsIPrincipal *targetPrincipal = nsnull;
|
||||
for (ContextPrincipal *cp = mContextPrincipals; cp; cp = cp->mNext)
|
||||
{
|
||||
if (cp->mCx == cx)
|
||||
{
|
||||
target = cp->mFp;
|
||||
targetPrincipal = cp->mPrincipal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get principals from innermost JavaScript frame.
|
||||
JSStackFrame *fp = nsnull; // tell JS_FrameIterator to start at innermost
|
||||
for (fp = JS_FrameIterator(cx, &fp); fp; fp = JS_FrameIterator(cx, &fp))
|
||||
{
|
||||
if (fp == target)
|
||||
break;
|
||||
nsIPrincipal* result = GetFramePrincipal(cx, fp, rv);
|
||||
if (result)
|
||||
{
|
||||
|
@ -2251,6 +2290,25 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
|
|||
}
|
||||
}
|
||||
|
||||
// If targetPrincipal is non-null, then it means that someone wants to
|
||||
// clamp the principals on this context to this principal. Note that
|
||||
// fp might not equal target here (fp might be null) because someone
|
||||
// could have set aside the frame chain in the meantime.
|
||||
if (targetPrincipal)
|
||||
{
|
||||
if (fp && fp == target)
|
||||
{
|
||||
*frameResult = fp;
|
||||
}
|
||||
else
|
||||
{
|
||||
JSStackFrame *inner = nsnull;
|
||||
*frameResult = JS_FrameIterator(cx, &inner);
|
||||
}
|
||||
|
||||
return targetPrincipal;
|
||||
}
|
||||
|
||||
nsIScriptContext *scriptContext = GetScriptContext(cx);
|
||||
if (scriptContext)
|
||||
{
|
||||
|
@ -2277,7 +2335,6 @@ nsScriptSecurityManager::GetPrincipalAndFrame(JSContext *cx,
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIPrincipal*
|
||||
nsScriptSecurityManager::GetSubjectPrincipal(JSContext *cx,
|
||||
nsresult* rv)
|
||||
|
@ -3278,6 +3335,7 @@ nsScriptSecurityManager::nsScriptSecurityManager(void)
|
|||
: mOriginToPolicyMap(nsnull),
|
||||
mDefaultPolicy(nsnull),
|
||||
mCapabilities(nsnull),
|
||||
mContextPrincipals(nsnull),
|
||||
mIsJavaScriptEnabled(PR_FALSE),
|
||||
mIsWritingPrefs(PR_FALSE),
|
||||
mPolicyPrefsChanged(PR_TRUE)
|
||||
|
@ -3360,6 +3418,7 @@ jsval nsScriptSecurityManager::sEnabledID = JSVAL_VOID;
|
|||
|
||||
nsScriptSecurityManager::~nsScriptSecurityManager(void)
|
||||
{
|
||||
NS_ASSERTION(!mContextPrincipals, "Leaking mContextPrincipals");
|
||||
delete mOriginToPolicyMap;
|
||||
if(mDefaultPolicy)
|
||||
mDefaultPolicy->Drop();
|
||||
|
|
|
@ -1382,6 +1382,20 @@ FullTrustSecMan::GetSubjectPrincipal(nsIPrincipal **_retval)
|
|||
return *_retval ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* [noscript] void pushContextPrincipal (in JSContextPtr cx, in JSStackFramePtr fp, in nsIPrincipal principal); */
|
||||
NS_IMETHODIMP
|
||||
FullTrustSecMan::PushContextPrincipal(JSContext * cx, JSStackFrame * fp, nsIPrincipal *principal)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] void popContextPrincipal (in JSContextPtr cx); */
|
||||
NS_IMETHODIMP
|
||||
FullTrustSecMan::PopContextPrincipal(JSContext * cx)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* [noscript] nsIPrincipal getSystemPrincipal (); */
|
||||
NS_IMETHODIMP
|
||||
FullTrustSecMan::GetSystemPrincipal(nsIPrincipal **_retval)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "jsscript.h" // for js_ScriptClass
|
||||
#include "XPCWrapper.h"
|
||||
#include "jsregexp.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
|
||||
static JSBool
|
||||
XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
|
||||
|
@ -167,23 +168,47 @@ CanCallerAccess(JSContext *cx, JSObject *unsafeObj)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static JSPrincipals *
|
||||
FindObjectPrincipals(JSContext *cx, JSObject *obj)
|
||||
// Reserved slot indexes on safe wrappers.
|
||||
|
||||
// Boolean value, initialized to false on object creation and true
|
||||
// only while we're resolving a property on the object.
|
||||
#define XPC_SJOW_SLOT_IS_RESOLVING 0
|
||||
|
||||
// Slot for holding on to the principal to use if a principal other
|
||||
// than that of the unsafe object is desired for this wrapper
|
||||
// (nsIPrincipal, strong reference).
|
||||
#define XPC_SJOW_SLOT_PRINCIPAL 1
|
||||
|
||||
|
||||
// Returns a weak reference.
|
||||
static nsIPrincipal *
|
||||
FindObjectPrincipals(JSContext *cx, JSObject *safeObj, JSObject *innerObj)
|
||||
{
|
||||
// Check if we have a cached principal first.
|
||||
jsval v;
|
||||
if (!JS_GetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL, &v)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_VOID(v)) {
|
||||
// Found one! No need to do any more refcounting.
|
||||
return static_cast<nsIPrincipal *>(JSVAL_TO_PRIVATE(v));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> objPrincipal;
|
||||
nsresult rv = FindPrincipals(cx, obj, getter_AddRefs(objPrincipal), nsnull,
|
||||
nsresult rv = FindPrincipals(cx, innerObj, getter_AddRefs(objPrincipal), nsnull,
|
||||
nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
JSPrincipals *jsprin;
|
||||
rv = objPrincipal->GetJSPrincipals(cx, &jsprin);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (!JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_PRINCIPAL,
|
||||
PRIVATE_TO_JSVAL(objPrincipal.get()))) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
return jsprin;
|
||||
// The wrapper owns the principal now.
|
||||
return objPrincipal.forget().get();
|
||||
}
|
||||
|
||||
|
||||
|
@ -217,29 +242,6 @@ static JSBool
|
|||
XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
jsval *rval);
|
||||
|
||||
// Reserved slot indexes on safe wrappers.
|
||||
|
||||
// Boolean value, initialized to false on object creation and true
|
||||
// only while we're resolving a property on the object.
|
||||
#define XPC_SJOW_SLOT_IS_RESOLVING 0
|
||||
|
||||
// Slot for caching a compiled scripted function for property
|
||||
// get/set.
|
||||
#define XPC_SJOW_SLOT_SCRIPTED_GETSET 1
|
||||
|
||||
// Slot for caching a compiled scripted function for function
|
||||
// calling.
|
||||
#define XPC_SJOW_SLOT_SCRIPTED_FUN 2
|
||||
|
||||
// Slot for caching a compiled scripted function for calling
|
||||
// toString().
|
||||
#define XPC_SJOW_SLOT_SCRIPTED_TOSTRING 3
|
||||
|
||||
// Slot for holding on to the principal to use if a principal other
|
||||
// than that of the unsafe object is desired for this wrapper
|
||||
// (nsIPrincipal, strong reference).
|
||||
#define XPC_SJOW_SLOT_PRINCIPAL 4
|
||||
|
||||
|
||||
// Wrap a JS value in a safe wrapper of a function wrapper if
|
||||
// needed. Note that rval must point to something rooted when calling
|
||||
|
@ -266,21 +268,7 @@ WrapJSValue(JSContext *cx, JSObject *obj, jsval val, jsval *rval)
|
|||
// any of the code below.
|
||||
*rval = OBJECT_TO_JSVAL(safeObj);
|
||||
|
||||
// If obj and safeObj are from the same scope, propagate cached
|
||||
// scripted functions to the new safe object.
|
||||
if (JS_GetGlobalForObject(cx, obj) == JS_GetGlobalForObject(cx, safeObj)) {
|
||||
jsval rsval;
|
||||
if (!::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_SCRIPTED_GETSET,
|
||||
&rsval) ||
|
||||
!::JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_SCRIPTED_GETSET,
|
||||
rsval) ||
|
||||
!::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_SCRIPTED_FUN,
|
||||
&rsval) ||
|
||||
!::JS_SetReservedSlot(cx, safeObj, XPC_SJOW_SLOT_SCRIPTED_FUN,
|
||||
rsval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (JS_GetGlobalForObject(cx, obj) != JS_GetGlobalForObject(cx, safeObj)) {
|
||||
// Check to see if the new object we just wrapped is accessible
|
||||
// from the unsafe object we got the new object through. If not,
|
||||
// force the new wrapper to use the principal of the unsafe
|
||||
|
@ -395,81 +383,6 @@ UnwrapJSValue(jsval val)
|
|||
return val;
|
||||
}
|
||||
|
||||
// Get a scripted function for use with the safe wrapper (obj) when
|
||||
// accessing an unsafe object (unsafeObj). If a scripted function
|
||||
// already exists in the reserved slot slotIndex, use it, otherwise
|
||||
// create a new one and cache it in that same slot. The source of the
|
||||
// script is passed in funScript, and the resulting (new or cached)
|
||||
// scripted function is returned through scriptedFunVal.
|
||||
/* Keep GetScriptedFunction prototype in sync with corresponding macro */
|
||||
static JSBool
|
||||
GetScriptedFunction(JSContext *cx, JSObject *obj, JSObject *unsafeObj,
|
||||
uint32 slotIndex, const nsAFlatCString& funScript,
|
||||
jsval *scriptedFunVal, uintN lineno)
|
||||
{
|
||||
if (!::JS_GetReservedSlot(cx, obj, slotIndex, scriptedFunVal)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// If we either have no scripted function in the requested slot yet,
|
||||
// or if the scope of the unsafeObj changed since we compiled the
|
||||
// scripted function, re-compile to make sure the scripted function
|
||||
// is properly scoped etc.
|
||||
if (JSVAL_IS_VOID(*scriptedFunVal) ||
|
||||
JS_GetGlobalForObject(cx, unsafeObj) !=
|
||||
JS_GetGlobalForObject(cx, JSVAL_TO_OBJECT(*scriptedFunVal))) {
|
||||
// Check whether we have a cached principal or not.
|
||||
jsval pv;
|
||||
if (!::JS_GetReservedSlot(cx, obj, XPC_SJOW_SLOT_PRINCIPAL, &pv)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
if (!JSVAL_IS_VOID(pv)) {
|
||||
nsIPrincipal *principal = (nsIPrincipal *)JSVAL_TO_PRIVATE(pv);
|
||||
|
||||
// Found a cached principal, use it rather than looking up the
|
||||
// principal of the unsafe object.
|
||||
principal->GetJSPrincipals(cx, &jsprin);
|
||||
} else {
|
||||
// No cached principal found, look up the principal based on the
|
||||
// unsafe object.
|
||||
jsprin = FindObjectPrincipals(cx, unsafeObj);
|
||||
}
|
||||
|
||||
if (!jsprin) {
|
||||
return ThrowException(NS_ERROR_UNEXPECTED, cx);
|
||||
}
|
||||
|
||||
JSFunction *scriptedFun =
|
||||
::JS_CompileFunctionForPrincipals(cx,
|
||||
JS_GetGlobalForObject(cx, unsafeObj),
|
||||
jsprin, nsnull, 0, nsnull,
|
||||
funScript.get(), funScript.Length(),
|
||||
"XPCSafeJSObjectWrapper.cpp",
|
||||
lineno);
|
||||
|
||||
JSPRINCIPALS_DROP(cx, jsprin);
|
||||
|
||||
if (!scriptedFun) {
|
||||
return ThrowException(NS_ERROR_FAILURE, cx);
|
||||
}
|
||||
|
||||
*scriptedFunVal = OBJECT_TO_JSVAL(::JS_GetFunctionObject(scriptedFun));
|
||||
|
||||
if (*scriptedFunVal == JSVAL_NULL ||
|
||||
!::JS_SetReservedSlot(cx, obj, slotIndex, *scriptedFunVal)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
#define GetScriptedFunction(cx, obj, unsafeObj, slotIndex, funScript, scriptedFunVal) \
|
||||
(GetScriptedFunction)(cx, obj, unsafeObj, slotIndex, funScript, scriptedFunVal, __LINE__)
|
||||
|
||||
static JSBool
|
||||
XPC_SJOW_AddProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
||||
{
|
||||
|
@ -523,22 +436,52 @@ XPC_SJOW_DelProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
return XPCWrapper::DelProperty(cx, unsafeObj, id, vp);
|
||||
}
|
||||
|
||||
static inline JSBool
|
||||
CallWithoutStatics(JSContext *cx, JSObject *obj, jsval fval, uintN argc,
|
||||
jsval *argv, jsval *rval)
|
||||
{
|
||||
NS_STACK_CLASS class SafeCallGuard {
|
||||
public:
|
||||
SafeCallGuard(JSContext *cx, nsIPrincipal *principal)
|
||||
: cx(cx) {
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (ssm) {
|
||||
// Note: We pass null as the target frame pointer because we know that
|
||||
// we're about to set aside the frame chain.
|
||||
nsresult rv = ssm->PushContextPrincipal(cx, nsnull, principal);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Not allowing call because we're out of memory");
|
||||
JS_ReportOutOfMemory(cx);
|
||||
this->cx = nsnull;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
js_SaveAndClearRegExpStatics(cx, &statics, &tvr);
|
||||
fp = JS_SaveFrameChain(cx);
|
||||
options =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
}
|
||||
|
||||
JSBool ready() {
|
||||
return cx != nsnull;
|
||||
}
|
||||
|
||||
~SafeCallGuard() {
|
||||
if (cx) {
|
||||
JS_SetOptions(cx, options);
|
||||
JS_RestoreFrameChain(cx, fp);
|
||||
js_RestoreRegExpStatics(cx, &statics, &tvr);
|
||||
nsIScriptSecurityManager *ssm = XPCWrapper::GetSecurityManager();
|
||||
if (ssm) {
|
||||
ssm->PopContextPrincipal(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
JSContext *cx;
|
||||
JSRegExpStatics statics;
|
||||
JSTempValueRooter tvr;
|
||||
js_SaveAndClearRegExpStatics(cx, &statics, &tvr);
|
||||
JSStackFrame *fp = JS_SaveFrameChain(cx);
|
||||
uint32 options =
|
||||
JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT);
|
||||
JSBool ok = ::JS_CallFunctionValue(cx, obj, fval, argc, argv, rval);
|
||||
JS_SetOptions(cx, options);
|
||||
JS_RestoreFrameChain(cx, fp);
|
||||
js_RestoreRegExpStatics(cx, &statics, &tvr);
|
||||
return ok;
|
||||
}
|
||||
uint32 options;
|
||||
JSStackFrame *fp;
|
||||
};
|
||||
|
||||
static JSBool
|
||||
XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
||||
|
@ -563,35 +506,30 @@ XPC_SJOW_GetOrSetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Function body for wrapping property get/set in a scripted
|
||||
// caller. This scripted function's first argument is the property
|
||||
// to get/set. If the operation is a get operation, the function is
|
||||
// passed one argument. If the operation is a set operation, the
|
||||
// function gets two arguments and the second argument will be the
|
||||
// value to set the property to.
|
||||
NS_NAMED_LITERAL_CSTRING(funScript,
|
||||
"if (arguments.length == 1) return this[arguments[0]];"
|
||||
"return this[arguments[0]] = arguments[1];");
|
||||
{
|
||||
SafeCallGuard guard(cx, FindObjectPrincipals(cx, obj, unsafeObj));
|
||||
if (!guard.ready()) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsval scriptedFunVal;
|
||||
if (!GetScriptedFunction(cx, obj, unsafeObj, XPC_SJOW_SLOT_SCRIPTED_GETSET,
|
||||
funScript, &scriptedFunVal)) {
|
||||
return JS_FALSE;
|
||||
jsid interned_id;
|
||||
if (!JS_ValueToId(cx, id, &interned_id)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (aIsSet) {
|
||||
*vp = UnwrapJSValue(*vp);
|
||||
}
|
||||
|
||||
JSBool ok = aIsSet
|
||||
? JS_SetPropertyById(cx, unsafeObj, interned_id, vp)
|
||||
: JS_GetPropertyById(cx, unsafeObj, interned_id, vp);
|
||||
if (!ok) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Build up our argument array per the comment above.
|
||||
jsval args[2];
|
||||
|
||||
args[0] = id;
|
||||
|
||||
if (aIsSet) {
|
||||
args[1] = UnwrapJSValue(*vp);
|
||||
}
|
||||
|
||||
jsval val;
|
||||
JSBool ok = CallWithoutStatics(cx, unsafeObj, scriptedFunVal,
|
||||
aIsSet ? 2 : 1, args, &val);
|
||||
return ok && WrapJSValue(cx, obj, val, vp);
|
||||
return WrapJSValue(cx, obj, *vp, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -766,7 +704,8 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
callThisObj = unsafeObj;
|
||||
}
|
||||
|
||||
JSObject *funToCall = GetUnsafeObject(JSVAL_TO_OBJECT(argv[-2]));
|
||||
JSObject *safeObj = JSVAL_TO_OBJECT(argv[-2]);
|
||||
JSObject *funToCall = GetUnsafeObject(safeObj);
|
||||
|
||||
if (!funToCall) {
|
||||
// Someone has called XPCSafeJSObjectWrapper.prototype() causing
|
||||
|
@ -782,50 +721,20 @@ XPC_SJOW_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Function body for wrapping calls to functions or callable objects
|
||||
// in a scripted caller. This scripted function's first argument is
|
||||
// a native call wrapper, and the second argument is the unsafe
|
||||
// function to call. All but the first argument are passed to the
|
||||
// call wrapper.
|
||||
NS_NAMED_LITERAL_CSTRING(funScript,
|
||||
"var args = [];"
|
||||
"for (var i = 1; i < arguments.length; i++)"
|
||||
"args.push(arguments[i]);"
|
||||
"return arguments[0].apply(this, args);");
|
||||
{
|
||||
SafeCallGuard guard(cx, FindObjectPrincipals(cx, safeObj, funToCall));
|
||||
|
||||
// Get the scripted function.
|
||||
jsval scriptedFunVal;
|
||||
if (!GetScriptedFunction(cx, obj, unsafeObj, XPC_SJOW_SLOT_SCRIPTED_FUN,
|
||||
funScript, &scriptedFunVal)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
for (uintN i = 0; i < argc; ++i) {
|
||||
argv[i] = UnwrapJSValue(argv[i]);
|
||||
}
|
||||
|
||||
// Build up our argument array per earlier comment.
|
||||
jsval argsBuf[8];
|
||||
jsval *args = argsBuf;
|
||||
|
||||
if (argc > 7) {
|
||||
args = (jsval *)nsMemory::Alloc((argc + 1) * sizeof(jsval *));
|
||||
if (!args) {
|
||||
return ThrowException(NS_ERROR_OUT_OF_MEMORY, cx);
|
||||
if (!JS_CallFunctionValue(cx, callThisObj, OBJECT_TO_JSVAL(funToCall),
|
||||
argc, argv, rval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
args[0] = OBJECT_TO_JSVAL(funToCall);
|
||||
|
||||
for (uintN i = 0; i < argc; ++i) {
|
||||
args[i + 1] = UnwrapJSValue(argv[i]);
|
||||
}
|
||||
|
||||
jsval val;
|
||||
JSBool ok = CallWithoutStatics(cx, callThisObj, scriptedFunVal, argc + 1,
|
||||
args, &val);
|
||||
|
||||
if (args != argsBuf) {
|
||||
nsMemory::Free(args);
|
||||
}
|
||||
|
||||
return ok && WrapJSValue(cx, obj, val, rval);
|
||||
return WrapJSValue(cx, obj, *rval, rval);
|
||||
}
|
||||
|
||||
JSBool
|
||||
|
@ -918,9 +827,19 @@ XPC_SJOW_Create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSBool ok = CallWithoutStatics(cx, obj, OBJECT_TO_JSVAL(callee), argc, argv,
|
||||
rval);
|
||||
return ok && WrapJSValue(cx, callee, *rval, rval);
|
||||
{
|
||||
SafeCallGuard guard(cx, FindObjectPrincipals(cx, callee, unsafeObj));
|
||||
if (!guard.ready()) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (!JS_CallFunctionValue(cx, obj, OBJECT_TO_JSVAL(callee),
|
||||
argc, argv, rval)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return WrapJSValue(cx, callee, *rval, rval);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -1043,19 +962,19 @@ XPC_SJOW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
// Function body for wrapping toString() in a scripted caller.
|
||||
NS_NAMED_LITERAL_CSTRING(funScript, "return '' + this;");
|
||||
{
|
||||
SafeCallGuard guard(cx, FindObjectPrincipals(cx, obj, unsafeObj));
|
||||
if (!guard.ready()) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
jsval scriptedFunVal;
|
||||
if (!GetScriptedFunction(cx, obj, unsafeObj, XPC_SJOW_SLOT_SCRIPTED_TOSTRING,
|
||||
funScript, &scriptedFunVal)) {
|
||||
return JS_FALSE;
|
||||
JSString *str = JS_ValueToString(cx, OBJECT_TO_JSVAL(unsafeObj));
|
||||
if (!str) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
*rval = STRING_TO_JSVAL(str);
|
||||
}
|
||||
|
||||
jsval val;
|
||||
JSBool ok = CallWithoutStatics(cx, unsafeObj, scriptedFunVal, 0, nsnull,
|
||||
&val);
|
||||
return ok && WrapJSValue(cx, obj, val, rval);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -1275,6 +1275,8 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
|||
XPCContext* xpcc;
|
||||
JSContext* cx;
|
||||
JSObject* thisObj;
|
||||
JSBool popPrincipal = JS_FALSE;
|
||||
nsIScriptSecurityManager* ssm = nsnull;
|
||||
|
||||
// Make sure not to set the callee on ccx until after we've gone through
|
||||
// the whole nsIXPCFunctionThisTranslator bit. That code uses ccx to
|
||||
|
@ -1597,8 +1599,6 @@ nsXPCWrappedJSClass::CallMethod(nsXPCWrappedJS* wrapper, uint16 methodIndex,
|
|||
*sp++ = val;
|
||||
}
|
||||
|
||||
|
||||
|
||||
readyToDoTheCall = JS_TRUE;
|
||||
|
||||
pre_call_clean_up:
|
||||
|
@ -1660,6 +1660,31 @@ pre_call_clean_up:
|
|||
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
if(XPCPerThreadData::IsMainThread(ccx))
|
||||
{
|
||||
ssm = XPCWrapper::GetSecurityManager();
|
||||
if(ssm)
|
||||
{
|
||||
nsCOMPtr<nsIPrincipal> objPrincipal;
|
||||
ssm->GetObjectPrincipal(ccx, obj, getter_AddRefs(objPrincipal));
|
||||
if(objPrincipal)
|
||||
{
|
||||
JSStackFrame* fp = nsnull;
|
||||
nsresult rv =
|
||||
ssm->PushContextPrincipal(ccx, JS_FrameIterator(ccx, &fp),
|
||||
objPrincipal);
|
||||
if(NS_FAILED(rv))
|
||||
{
|
||||
JS_ReportOutOfMemory(ccx);
|
||||
retval = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
popPrincipal = JS_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(XPT_MD_IS_GETTER(info->flags))
|
||||
success = JS_GetProperty(cx, obj, name, &result);
|
||||
else if(XPT_MD_IS_SETTER(info->flags))
|
||||
|
@ -1696,7 +1721,10 @@ pre_call_clean_up:
|
|||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
if(popPrincipal)
|
||||
ssm->PopContextPrincipal(ccx);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
PRBool forceReport;
|
||||
if(NS_FAILED(mInfo->IsFunction(&forceReport)))
|
||||
|
|
Загрузка…
Ссылка в новой задаче