Primarily fixes to properly handle nsIXPCSecurityManager vetos of
xpconnect activities.

- The code was not propagating security manager vetos of native wrapping up
through xpconnect internals. So, xpconnect was erroneously masking the
security exception with its own 'failed to convert param' exception.
This effects the signatures of nsXPCWrappedNative::GetNewOrUsedWrapper
and nsXPCWrappedJSClass::GetNewOrUsedClass.

- This propagation also helps with the problem that sometimes interfaces
are not set as [scriptable] and we did not make that clear as the source
of xpconnect's failure to convert a param in calling a method. Now this
specific class of exceptions is indicated in the JS exception object when
this happens.

- Added an explicit call to js_ForceGC on shutdown of xpcshell to aid in
avoiding 'false positives' in leak detection

- Return JS_FALSE rather than JS_TRUE when an exception is thrown in
xpcjsid to make the jsengine notices the exception.

- Move #includes that others added in xpcmodule.cpp to xpcprivate.h in
order to maintain the include conventions of this module.

- Avoid throwing an exception if it represents a security manager veto
and the security manager set an exception already.

- Replace uses of nsCOMTypeInfo<> added by scc with NS_GET_IID macros.

- Fixed a methodname misspelling because reviewers care about stuff
like that :)
This commit is contained in:
jband%netscape.com 1999-10-23 07:20:04 +00:00
parent 8d8ce920cb
commit 2353651fe4
14 changed files with 94 additions and 42 deletions

View File

@ -110,6 +110,10 @@
#define NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY GENERATE_XPC_FAILURE(36)
#define NS_ERROR_XPC_CANT_GET_ARRAY_INFO GENERATE_XPC_FAILURE(37)
#define NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING GENERATE_XPC_FAILURE(38)
#define NS_ERROR_XPC_SECURITY_MANAGER_VETO GENERATE_XPC_FAILURE(39)
#define NS_ERROR_XPC_INTERFACE_NOT_SCRIPTABLE GENERATE_XPC_FAILURE(40)
#define NS_ERROR_XPC_INTERFACE_NOT_FROM_NSISUPPORTS GENERATE_XPC_FAILURE(41)
// any new errors here should have an associated entry added in xpc.msg

View File

@ -663,6 +663,7 @@ main(int argc, char **argv)
xpc->AbandonJSContext(jscontext);
NS_RELEASE(xpc);
js_ForceGC(jscontext);
JS_DestroyContext(jscontext);
if (!rtsvc) {
/* no runtime service, so we have to handle shutdown */

View File

@ -253,7 +253,7 @@ nsXPConnect::GetJSThrower(nsXPConnect* xpc /*= nsnull */)
// static
JSBool
nsXPConnect::IsISupportsDescendent(nsIInterfaceInfo* info)
nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info)
{
if(!info)
return JS_FALSE;
@ -356,7 +356,8 @@ nsXPConnect::InitJSContextWithNewWrappedGlobal(JSContext* aJSContext,
if(!mContextMap->Find(aJSContext) &&
nsnull != (xpcc = NewContext(aJSContext, nsnull, JS_FALSE)))
{
wrapper = nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc, aCOMObj, aIID);
wrapper = nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc, aCOMObj,
aIID, nsnull);
if(wrapper)
{
if(JS_InitStandardClasses(aJSContext, wrapper->GetJSObject()) &&
@ -478,7 +479,8 @@ nsXPConnect::WrapNative(JSContext* aJSContext,
if(xpcc)
{
nsXPCWrappedNative* wrapper =
nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc, aCOMObj, aIID);
nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc, aCOMObj,
aIID, nsnull);
if(wrapper)
{
*aWrapper = wrapper;

View File

@ -75,6 +75,9 @@ XPC_MSG_DEF(NS_ERROR_XPC_CANT_CONVERT_OBJECT_TO_ARRAY , "Can not convert JavaS
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY , "JavaScript Array does not have as many elements as indicated by size argument")
XPC_MSG_DEF(NS_ERROR_XPC_CANT_GET_ARRAY_INFO , "Can not find array information")
XPC_MSG_DEF(NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING , "JavaScript String does not have as many characters as indicated by size argument")
XPC_MSG_DEF(NS_ERROR_XPC_SECURITY_MANAGER_VETO , "Security Manager vetoed action")
XPC_MSG_DEF(NS_ERROR_XPC_INTERFACE_NOT_SCRIPTABLE , "Failed to build a wrapper because the interface that was not declared [scriptable]")
XPC_MSG_DEF(NS_ERROR_XPC_INTERFACE_NOT_FROM_NSISUPPORTS , "Failed to build a wrapper because the interface does not inherit from nsISupports")
/* common global codes (from nsError.h) */

View File

@ -195,7 +195,7 @@ nsXPCInterfaces::FillCache(JSContext *cx, JSObject *obj,
}
rv = is_Interface->
QueryInterface(nsCOMTypeInfo<nsIInterfaceInfo>::GetIID(),
QueryInterface(NS_GET_IID(nsIInterfaceInfo),
(void **)&Interface);
if(!NS_FAILED(rv))

View File

@ -359,7 +359,7 @@ XPCConvert::NativeData2JS(JSContext* cx, jsval* d, const void* s,
!(xpcc = nsXPConnect::GetContext(cx)) ||
!(wrapper =
nsXPCWrappedNative::GetNewOrUsedWrapper(xpcc,
iface, *iid)))
iface, *iid, pErr)))
{
return JS_FALSE;
}

View File

@ -640,7 +640,7 @@ CIDCreateInstance::Call(JSContext *cx, JSObject *obj,
// the security manager vetoed. It should have set an exception.
nsAllocator::Free(cid);
*rval = JSVAL_NULL;
*retval = JS_TRUE;
*retval = JS_FALSE;
return NS_OK;
}
}
@ -841,7 +841,7 @@ CIDGetService::Call(JSContext *cx, JSObject *obj,
// the security manager vetoed. It should have set an exception.
nsAllocator::Free(cid);
*rval = JSVAL_NULL;
*retval = JS_TRUE;
*retval = JS_FALSE;
return NS_OK;
}
}

View File

@ -34,9 +34,7 @@
/* Module level methods. */
#include "nsCOMPtr.h"
#include "xpcprivate.h"
#include "nsIModule.h"
/***************************************************************************/

View File

@ -53,6 +53,8 @@
#include "nsIXPCScriptable.h"
#include "nsIXPCSecurityManager.h"
#include "nsIJSRuntimeService.h"
#include "nsCOMPtr.h"
#include "nsIModule.h"
#include "xptcall.h"
#include "jsapi.h"
#include "jshash.h"
@ -167,7 +169,7 @@ public:
static nsIInterfaceInfoManager* GetInterfaceInfoManager(nsXPConnect* xpc = nsnull);
static XPCContext* GetContext(JSContext* cx, nsXPConnect* xpc = nsnull);
static XPCJSThrower* GetJSThrower(nsXPConnect* xpc = nsnull);
static JSBool IsISupportsDescendent(nsIInterfaceInfo* info);
static JSBool IsISupportsDescendant(nsIInterfaceInfo* info);
static nsIJSContextStack* GetContextStack(nsXPConnect* xpc = nsnull);
JSContext2XPCContextMap* GetContextMap() {return mContextMap;}
@ -623,7 +625,8 @@ class nsXPCWrappedNativeClass : public nsIXPCWrappedNativeClass
NS_IMETHOD DebugDump(int depth);
public:
static nsXPCWrappedNativeClass* GetNewOrUsedClass(XPCContext* xpcc,
REFNSIID aIID);
REFNSIID aIID,
nsresult* pErr);
REFNSIID GetIID() const {return mIID;}
const char* GetInterfaceName();
@ -784,7 +787,8 @@ class nsXPCWrappedNative : public nsIXPConnectWrappedNative
public:
static nsXPCWrappedNative* GetNewOrUsedWrapper(XPCContext* xpcc,
nsISupports* aObj,
REFNSIID aIID);
REFNSIID aIID,
nsresult* pErr);
nsISupports* GetNative() const {return mObj;}
JSObject* GetJSObject() const {return mJSObj;}
nsXPCWrappedNativeClass* GetClass() const {return mClass;}

View File

@ -197,6 +197,11 @@ void
XPCJSThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
{
JSBool success = JS_FALSE;
/* no need to set an expection if the security manager already has */
if(rv == NS_ERROR_XPC_SECURITY_MANAGER_VETO && JS_IsExceptionPending(cx))
return;
nsIXPCException* e = nsXPCException::NewException(sz, rv, nsnull, nsnull);
if(e)

View File

@ -160,7 +160,7 @@ nsXPCWrappedJS::GetNewOrUsedWrapper(XPCContext* xpcc,
// just a root wrapper
nsXPCWrappedJSClass* rootClazz;
rootClazz = nsXPCWrappedJSClass::GetNewOrUsedClass(
xpcc, nsCOMTypeInfo<nsISupports>::GetIID());
xpcc, NS_GET_IID(nsISupports));
if(!rootClazz)
goto return_wrapper;
@ -261,7 +261,7 @@ nsXPCWrappedJS::~nsXPCWrappedJS()
nsXPCWrappedJS*
nsXPCWrappedJS::Find(REFNSIID aIID)
{
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
if(aIID.Equals(NS_GET_IID(nsISupports)))
return mRoot;
nsXPCWrappedJS* cur = mRoot;

View File

@ -69,7 +69,7 @@ nsXPCWrappedJSClass::GetNewOrUsedClass(XPCContext* xpcc,
nsIInterfaceInfo* info;
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info)))
{
if(nsXPConnect::IsISupportsDescendent(info))
if(nsXPConnect::IsISupportsDescendant(info))
{
clazz = new nsXPCWrappedJSClass(xpcc, aIID, info);
if(!clazz->mDescriptors)
@ -294,7 +294,8 @@ nsXPCWrappedJSClass::DelegatedQueryInterface(nsXPCWrappedJS* self,
JSObject*
nsXPCWrappedJSClass::GetRootJSObject(JSObject* aJSObj)
{
JSObject* result = CallQueryInterfaceOnJSObject(aJSObj, nsCOMTypeInfo<nsISupports>::GetIID());
JSObject* result = CallQueryInterfaceOnJSObject(aJSObj,
NS_GET_IID(nsISupports));
return result ? result : aJSObj;
}

View File

@ -91,11 +91,14 @@ nsXPCWrappedNative::JSObjectFinalized(JSContext *cx, JSObject *obj)
Release();
}
#define SET_ERROR_CODE(_y) if(pErr) *pErr = _y
// static
nsXPCWrappedNative*
nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
nsISupports* aObj,
REFNSIID aIID)
REFNSIID aIID,
nsresult* pErr)
{
Native2WrappedNativeMap* map;
nsISupports* rootObj = nsnull;
@ -107,6 +110,8 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
NS_PRECONDITION(xpcc, "bad param");
NS_PRECONDITION(aObj, "bad param");
SET_ERROR_CODE(NS_ERROR_FAILURE);
map = xpcc->GetWrappedNativeMap();
if(!map)
{
@ -116,7 +121,8 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
// always find the native root
if(NS_FAILED(aObj->QueryInterface(nsCOMTypeInfo<nsISupports>::GetIID(), (void**)&rootObj)))
if(NS_FAILED(aObj->QueryInterface(NS_GET_IID(nsISupports),
(void**)&rootObj)))
goto return_wrapper;
// look for the root wrapper
@ -148,12 +154,13 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
NS_OK != sm->CanCreateWrapper(xpcc->GetJSContext(), aIID, realObj))
{
// the security manager vetoed. It should have set an exception.
SET_ERROR_CODE(NS_ERROR_XPC_SECURITY_MANAGER_VETO);
goto return_wrapper;
}
// need to make a wrapper
clazz = nsXPCWrappedNativeClass::GetNewOrUsedClass(xpcc, aIID);
clazz = nsXPCWrappedNativeClass::GetNewOrUsedClass(xpcc, aIID, pErr);
if(!clazz)
goto return_wrapper;
@ -181,7 +188,7 @@ nsXPCWrappedNative::GetNewOrUsedWrapper(XPCContext* xpcc,
// just a root wrapper
nsXPCWrappedNativeClass* rootClazz;
rootClazz = nsXPCWrappedNativeClass::GetNewOrUsedClass(
xpcc, nsCOMTypeInfo<nsISupports>::GetIID());
xpcc, NS_GET_IID(nsISupports), pErr);
if(!rootClazz)
goto return_wrapper;
@ -230,6 +237,9 @@ return_wrapper:
NS_RELEASE(realObj);
if(clazz)
NS_RELEASE(clazz);
if(wrapper)
SET_ERROR_CODE(NS_OK);
return wrapper;
}
@ -354,7 +364,7 @@ nsXPCWrappedNative::~nsXPCWrappedNative()
nsXPCWrappedNative*
nsXPCWrappedNative::Find(REFNSIID aIID)
{
if(aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()))
if(aIID.Equals(NS_GET_IID(nsISupports)))
return mRoot;
nsXPCWrappedNative* cur = mRoot;

View File

@ -47,10 +47,13 @@ extern "C" JS_IMPORT_DATA(JSObjectOps) js_ObjectOps;
NS_IMPL_ISUPPORTS1(nsXPCWrappedNativeClass, nsIXPCWrappedNativeClass)
#define SET_ERROR_CODE(_y) if(pErr) *pErr = _y
// static
nsXPCWrappedNativeClass*
nsXPCWrappedNativeClass::GetNewOrUsedClass(XPCContext* xpcc,
REFNSIID aIID)
REFNSIID aIID,
nsresult* pErr)
{
IID2WrappedNativeClassMap* map;
nsXPCWrappedNativeClass* clazz = nsnull;
@ -60,32 +63,53 @@ nsXPCWrappedNativeClass::GetNewOrUsedClass(XPCContext* xpcc,
map = xpcc->GetWrappedNativeClassMap();
NS_ASSERTION(map,"bad map");
SET_ERROR_CODE(NS_OK);
clazz = map->Find(aIID);
if(clazz)
{
NS_ADDREF(clazz);
return clazz;
}
else
nsCOMPtr<nsIInterfaceInfoManager> iimgr;
if(!(iimgr = nsXPConnect::GetInterfaceInfoManager()))
{
nsIInterfaceInfoManager* iimgr;
if(nsnull != (iimgr = nsXPConnect::GetInterfaceInfoManager()))
{
nsIInterfaceInfo* info;
if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, &info)))
{
PRBool canScript;
if(NS_SUCCEEDED(info->IsScriptable(&canScript)) &&
canScript &&
nsXPConnect::IsISupportsDescendent(info))
{
clazz = new nsXPCWrappedNativeClass(xpcc, aIID, info);
if(-1 == clazz->mMemberCount) // -1 means 'failed to init'
NS_RELEASE(clazz); // nsnulls out 'clazz'
}
NS_RELEASE(info);
}
NS_RELEASE(iimgr);
}
SET_ERROR_CODE(NS_ERROR_FAILURE);
return nsnull;
}
nsCOMPtr<nsIInterfaceInfo> info;
if(NS_FAILED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
{
SET_ERROR_CODE(NS_ERROR_XPC_CANT_GET_INTERFACE_INFO);
return nsnull;
}
PRBool canScript;
if(NS_FAILED(info->IsScriptable(&canScript)))
{
SET_ERROR_CODE(NS_ERROR_FAILURE);
return nsnull;
}
if(!canScript)
{
SET_ERROR_CODE(NS_ERROR_XPC_INTERFACE_NOT_SCRIPTABLE);
return nsnull;
}
if(!nsXPConnect::IsISupportsDescendant(info))
{
SET_ERROR_CODE(NS_ERROR_XPC_INTERFACE_NOT_FROM_NSISUPPORTS);
return nsnull;
}
clazz = new nsXPCWrappedNativeClass(xpcc, aIID, info);
if(-1 == clazz->mMemberCount) // -1 means 'failed to init'
{
SET_ERROR_CODE(NS_ERROR_FAILURE);
NS_RELEASE(clazz); // nsnulls out 'clazz'
}
return clazz;
}