Bug 869526 - GC: Fix more rooting hazards in xpconnect r=bholley

This commit is contained in:
Jon Coppeard 2013-05-09 10:39:21 +01:00
parent 7921fbf41a
commit cc5d536d60
6 changed files with 105 additions and 101 deletions

View File

@ -1417,10 +1417,12 @@ nsXPCComponents_Results::NewEnumerate(nsIXPConnectWrappedNative *wrapper,
/* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in uint32_t flags, out JSObjectPtr objp); */ /* bool newResolve (in nsIXPConnectWrappedNative wrapper, in JSContextPtr cx, in JSObjectPtr obj, in jsval id, in uint32_t flags, out JSObjectPtr objp); */
NS_IMETHODIMP NS_IMETHODIMP
nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper, nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj, JSContext *cx, JSObject *objArg,
jsid id, uint32_t flags, jsid idArg, uint32_t flags,
JSObject * *objp, bool *_retval) JSObject * *objp, bool *_retval)
{ {
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
JSAutoByteString name; JSAutoByteString name;
if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) { if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
@ -4957,14 +4959,14 @@ JSBool
nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx, nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
XPCWrappedNativeScope* aScope) XPCWrappedNativeScope* aScope)
{ {
JSObject *components = aScope->GetComponentsJSObject(ccx); RootedObject components(ccx, aScope->GetComponentsJSObject(ccx));
if (!components) if (!components)
return false; return false;
JSObject *global = aScope->GetGlobalJSObject(); RootedObject global(ccx, aScope->GetGlobalJSObject());
MOZ_ASSERT(js::IsObjectInContextCompartment(global, ccx)); MOZ_ASSERT(js::IsObjectInContextCompartment(global, ccx));
jsid id = ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS); RootedId id(ccx, ccx.GetRuntime()->GetStringID(XPCJSRuntime::IDX_COMPONENTS));
JSPropertyOp getter = AccessCheck::isChrome(global) ? nullptr JSPropertyOp getter = AccessCheck::isChrome(global) ? nullptr
: &ContentComponentsGetterOp; : &ContentComponentsGetterOp;
return JS_DefinePropertyById(ccx, global, id, js::ObjectValue(*components), return JS_DefinePropertyById(ccx, global, id, js::ObjectValue(*components),

View File

@ -213,11 +213,11 @@ GetMemberInfo(JSObject *obj, jsid memberId, const char **ifaceName)
static void static void
GetMethodInfo(JSContext *cx, jsval *vp, const char **ifaceNamep, jsid *memberIdp) GetMethodInfo(JSContext *cx, jsval *vp, const char **ifaceNamep, jsid *memberIdp)
{ {
JSObject *funobj = JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)); RootedObject funobj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
NS_ASSERTION(JS_ObjectIsFunction(cx, funobj), NS_ASSERTION(JS_ObjectIsFunction(cx, funobj),
"JSNative callee should be Function object"); "JSNative callee should be Function object");
JSString *str = JS_GetFunctionId(JS_GetObjectFunction(funobj)); RootedString str(cx, JS_GetFunctionId(JS_GetObjectFunction(funobj)));
jsid methodId = str ? INTERNED_STRING_TO_JSID(cx, str) : JSID_VOID; RootedId methodId(cx, str ? INTERNED_STRING_TO_JSID(cx, str) : JSID_VOID);
GetMemberInfo(JSVAL_TO_OBJECT(vp[1]), methodId, ifaceNamep); GetMemberInfo(JSVAL_TO_OBJECT(vp[1]), methodId, ifaceNamep);
*memberIdp = methodId; *memberIdp = methodId;
} }
@ -361,8 +361,8 @@ void
xpc_qsThrowBadArg(JSContext *cx, nsresult rv, jsval *vp, unsigned paramnum) xpc_qsThrowBadArg(JSContext *cx, nsresult rv, jsval *vp, unsigned paramnum)
{ {
const char *ifaceName; const char *ifaceName;
jsid memberId; RootedId memberId(cx);
GetMethodInfo(cx, vp, &ifaceName, &memberId); GetMethodInfo(cx, vp, &ifaceName, memberId.address());
ThrowBadArg(cx, rv, ifaceName, memberId, NULL, paramnum); ThrowBadArg(cx, rv, ifaceName, memberId, NULL, paramnum);
} }
@ -381,8 +381,9 @@ xpc_qsThrowBadArgWithDetails(JSContext *cx, nsresult rv, unsigned paramnum,
void void
xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
JSObject *obj, jsid propId) JSObject *obj, jsid propIdArg)
{ {
RootedId propId(cx, propIdArg);
const char *ifaceName; const char *ifaceName;
GetMemberInfo(obj, propId, &ifaceName); GetMemberInfo(obj, propId, &ifaceName);
ThrowBadArg(cx, rv, ifaceName, propId, NULL, 0); ThrowBadArg(cx, rv, ifaceName, propId, NULL, 0);

View File

@ -416,14 +416,7 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
// We ASSUME that the variant implementation can do these conversions... // We ASSUME that the variant implementation can do these conversions...
nsXPTCVariant xpctvar;
nsID iid; nsID iid;
nsAutoString astring;
nsAutoCString cString;
nsUTF8String utf8String;
uint32_t size;
xpctvar.flags = 0;
JSBool success;
NS_ABORT_IF_FALSE(js::IsObjectInContextCompartment(lccx.GetScopeForNewJSObjects(), cx), NS_ABORT_IF_FALSE(js::IsObjectInContextCompartment(lccx.GetScopeForNewJSObjects(), cx),
"bad scope for new JSObjects"); "bad scope for new JSObjects");
@ -440,100 +433,134 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
case nsIDataType::VTYPE_FLOAT: case nsIDataType::VTYPE_FLOAT:
case nsIDataType::VTYPE_DOUBLE: case nsIDataType::VTYPE_DOUBLE:
{ {
// Easy. Handle inline. double d;
if (NS_FAILED(variant->GetAsDouble(&xpctvar.val.d))) if (NS_FAILED(variant->GetAsDouble(&d)))
return false; return false;
*pJSVal = JS_NumberValue(xpctvar.val.d); *pJSVal = JS_NumberValue(d);
return true; return true;
} }
case nsIDataType::VTYPE_BOOL: case nsIDataType::VTYPE_BOOL:
{ {
// Easy. Handle inline. bool b;
if (NS_FAILED(variant->GetAsBool(&xpctvar.val.b))) if (NS_FAILED(variant->GetAsBool(&b)))
return false; return false;
*pJSVal = BOOLEAN_TO_JSVAL(xpctvar.val.b); *pJSVal = BOOLEAN_TO_JSVAL(b);
return true; return true;
} }
case nsIDataType::VTYPE_CHAR: case nsIDataType::VTYPE_CHAR:
if (NS_FAILED(variant->GetAsChar(&xpctvar.val.c))) {
char c;
if (NS_FAILED(variant->GetAsChar(&c)))
return false; return false;
xpctvar.type = (uint8_t)TD_CHAR; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&c, TD_CHAR, &iid, pErr);
break; }
case nsIDataType::VTYPE_WCHAR: case nsIDataType::VTYPE_WCHAR:
if (NS_FAILED(variant->GetAsWChar(&xpctvar.val.wc))) {
PRUnichar wc;
if (NS_FAILED(variant->GetAsWChar(&wc)))
return false; return false;
xpctvar.type = (uint8_t)TD_WCHAR; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&wc, TD_WCHAR, &iid, pErr);
break; }
case nsIDataType::VTYPE_ID: case nsIDataType::VTYPE_ID:
{
if (NS_FAILED(variant->GetAsID(&iid))) if (NS_FAILED(variant->GetAsID(&iid)))
return false; return false;
xpctvar.type = (uint8_t)TD_PNSIID; nsID *v = &iid;
xpctvar.val.p = &iid; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v, TD_PNSIID, &iid, pErr);
break; }
case nsIDataType::VTYPE_ASTRING: case nsIDataType::VTYPE_ASTRING:
{
nsAutoString astring;
if (NS_FAILED(variant->GetAsAString(astring))) if (NS_FAILED(variant->GetAsAString(astring)))
return false; return false;
xpctvar.type = (uint8_t)TD_ASTRING; nsAutoString *v = &astring;
xpctvar.val.p = &astring; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v, TD_ASTRING, &iid, pErr);
break; }
case nsIDataType::VTYPE_DOMSTRING: case nsIDataType::VTYPE_DOMSTRING:
{
nsAutoString astring;
if (NS_FAILED(variant->GetAsAString(astring))) if (NS_FAILED(variant->GetAsAString(astring)))
return false; return false;
xpctvar.type = (uint8_t)TD_DOMSTRING; nsAutoString *v = &astring;
xpctvar.val.p = &astring; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
break; TD_DOMSTRING, &iid, pErr);
}
case nsIDataType::VTYPE_CSTRING: case nsIDataType::VTYPE_CSTRING:
{
nsAutoCString cString;
if (NS_FAILED(variant->GetAsACString(cString))) if (NS_FAILED(variant->GetAsACString(cString)))
return false; return false;
xpctvar.type = (uint8_t)TD_CSTRING; nsAutoCString *v = &cString;
xpctvar.val.p = &cString; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
break; TD_CSTRING, &iid, pErr);
}
case nsIDataType::VTYPE_UTF8STRING: case nsIDataType::VTYPE_UTF8STRING:
{
nsUTF8String utf8String;
if (NS_FAILED(variant->GetAsAUTF8String(utf8String))) if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
return false; return false;
xpctvar.type = (uint8_t)TD_UTF8STRING; nsUTF8String *v = &utf8String;
xpctvar.val.p = &utf8String; return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
break; TD_UTF8STRING, &iid, pErr);
}
case nsIDataType::VTYPE_CHAR_STR: case nsIDataType::VTYPE_CHAR_STR:
if (NS_FAILED(variant->GetAsString((char**)&xpctvar.val.p))) {
char *pc;
if (NS_FAILED(variant->GetAsString(&pc)))
return false; return false;
xpctvar.type = (uint8_t)TD_PSTRING; bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pc,
xpctvar.SetValNeedsCleanup(); TD_PSTRING, &iid, pErr);
break; nsMemory::Free(pc);
return success;
}
case nsIDataType::VTYPE_STRING_SIZE_IS: case nsIDataType::VTYPE_STRING_SIZE_IS:
if (NS_FAILED(variant->GetAsStringWithSize(&size, {
(char**)&xpctvar.val.p))) char *pc;
uint32_t size;
if (NS_FAILED(variant->GetAsStringWithSize(&size, &pc)))
return false; return false;
xpctvar.type = (uint8_t)TD_PSTRING_SIZE_IS; bool success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal, (const void*)&pc,
xpctvar.SetValNeedsCleanup(); TD_PSTRING_SIZE_IS, size, pErr);
break; nsMemory::Free(pc);
return success;
}
case nsIDataType::VTYPE_WCHAR_STR: case nsIDataType::VTYPE_WCHAR_STR:
if (NS_FAILED(variant->GetAsWString((PRUnichar**)&xpctvar.val.p))) {
PRUnichar *pwc;
if (NS_FAILED(variant->GetAsWString(&pwc)))
return false; return false;
xpctvar.type = (uint8_t)TD_PWSTRING; bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pwc,
xpctvar.SetValNeedsCleanup(); TD_PSTRING, &iid, pErr);
break; nsMemory::Free(pwc);
return success;
}
case nsIDataType::VTYPE_WSTRING_SIZE_IS: case nsIDataType::VTYPE_WSTRING_SIZE_IS:
if (NS_FAILED(variant->GetAsWStringWithSize(&size, {
(PRUnichar**)&xpctvar.val.p))) PRUnichar *pwc;
uint32_t size;
if (NS_FAILED(variant->GetAsWStringWithSize(&size, &pwc)))
return false; return false;
xpctvar.type = (uint8_t)TD_PWSTRING_SIZE_IS; bool success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal, (const void*)&pwc,
xpctvar.SetValNeedsCleanup(); TD_PWSTRING_SIZE_IS, size, pErr);
break; nsMemory::Free(pwc);
return success;
}
case nsIDataType::VTYPE_INTERFACE: case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS: case nsIDataType::VTYPE_INTERFACE_IS:
{ {
nsISupports *pi;
nsID* piid; nsID* piid;
if (NS_FAILED(variant->GetAsInterface(&piid, &xpctvar.val.p))) if (NS_FAILED(variant->GetAsInterface(&piid, (void **)&pi)))
return false; return false;
iid = *piid; iid = *piid;
nsMemory::Free((char*)piid); nsMemory::Free((char*)piid);
xpctvar.type = (uint8_t)TD_INTERFACE_IS_TYPE; bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pi,
if (xpctvar.val.p) TD_INTERFACE_IS_TYPE, &iid, pErr);
xpctvar.SetValNeedsCleanup(); if (pi)
break; pi->Release();
return success;
} }
case nsIDataType::VTYPE_ARRAY: case nsIDataType::VTYPE_ARRAY:
{ {
@ -550,7 +577,7 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
// must exit via VARIANT_DONE from here on... // must exit via VARIANT_DONE from here on...
du.mType = nsIDataType::VTYPE_ARRAY; du.mType = nsIDataType::VTYPE_ARRAY;
success = false; bool success = false;
nsXPTType conversionType; nsXPTType conversionType;
uint16_t elementType = du.u.array.mArrayType; uint16_t elementType = du.u.array.mArrayType;
@ -633,32 +660,6 @@ VARIANT_DONE:
NS_ERROR("bad type in variant!"); NS_ERROR("bad type in variant!");
return false; return false;
} }
// If we are here then we need to convert the data in the xpctvar.
if (xpctvar.type.TagPart() == TD_PSTRING_SIZE_IS ||
xpctvar.type.TagPart() == TD_PWSTRING_SIZE_IS) {
success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal,
(const void*)&xpctvar.val,
xpctvar.type,
size, pErr);
} else {
success = XPCConvert::NativeData2JS(lccx, pJSVal,
(const void*)&xpctvar.val,
xpctvar.type,
&iid, pErr);
}
// We may have done something in the above code that requires cleanup.
if (xpctvar.DoesValNeedCleanup()) {
if (type == nsIDataType::VTYPE_INTERFACE ||
type == nsIDataType::VTYPE_INTERFACE_IS)
((nsISupports*)xpctvar.val.p)->Release();
else
nsMemory::Free((char*)xpctvar.val.p);
}
return success;
} }
/***************************************************************************/ /***************************************************************************/

View File

@ -2058,7 +2058,7 @@ XPCWrappedNative::GetSameCompartmentSecurityWrapper(JSContext *cx)
{ {
// Grab the current state of affairs. // Grab the current state of affairs.
RootedObject flat(cx, GetFlatJSObject()); RootedObject flat(cx, GetFlatJSObject());
JSObject *wrapper = GetWrapper(); RootedObject wrapper(cx, GetWrapper());
// If we already have a wrapper, it must be what we want. // If we already have a wrapper, it must be what we want.
if (wrapper) if (wrapper)

View File

@ -2031,7 +2031,7 @@ xpc_ActivateDebugMode()
JSContext* JSContext*
nsXPConnect::GetCurrentJSContext() nsXPConnect::GetCurrentJSContext()
{ {
JSContext *cx = XPCJSRuntime::Get()->GetJSContextStack()->Peek(); JSContext *cx = GetRuntime()->GetJSContextStack()->Peek();
return xpc_UnmarkGrayContext(cx); return xpc_UnmarkGrayContext(cx);
} }
@ -2039,7 +2039,7 @@ nsXPConnect::GetCurrentJSContext()
JSContext* JSContext*
nsXPConnect::GetSafeJSContext() nsXPConnect::GetSafeJSContext()
{ {
return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContext(); return GetRuntime()->GetJSContextStack()->GetSafeJSContext();
} }
namespace xpc { namespace xpc {
@ -2373,14 +2373,14 @@ nsXPConnect::SetDebugModeWhenPossible(bool mode, bool allowSyncDisable)
NS_IMETHODIMP NS_IMETHODIMP
nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval) nsXPConnect::GetTelemetryValue(JSContext *cx, jsval *rval)
{ {
JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
if (!obj) if (!obj)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT; unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
size_t i = JS_SetProtoCalled(cx); size_t i = JS_SetProtoCalled(cx);
jsval v = DOUBLE_TO_JSVAL(i); RootedValue v(cx, DOUBLE_TO_JSVAL(i));
if (!JS_DefineProperty(cx, obj, "setProto", v, NULL, NULL, attrs)) if (!JS_DefineProperty(cx, obj, "setProto", v, NULL, NULL, attrs))
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;

View File

@ -283,7 +283,7 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
#ifdef DEBUG #ifdef DEBUG
static void static void
DEBUG_CheckUnwrapSafety(JSObject *obj, js::Wrapper *handler, DEBUG_CheckUnwrapSafety(HandleObject obj, js::Wrapper *handler,
JSCompartment *origin, JSCompartment *target) JSCompartment *origin, JSCompartment *target)
{ {
if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) { if (AccessCheck::isChrome(target) || xpc::IsUniversalXPConnectEnabled(target)) {