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); */
NS_IMETHODIMP
nsXPCComponents_Results::NewResolve(nsIXPConnectWrappedNative *wrapper,
JSContext * cx, JSObject * obj,
jsid id, uint32_t flags,
JSContext *cx, JSObject *objArg,
jsid idArg, uint32_t flags,
JSObject * *objp, bool *_retval)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
JSAutoByteString name;
if (JSID_IS_STRING(id) && name.encodeLatin1(cx, JSID_TO_STRING(id))) {
@ -4957,14 +4959,14 @@ JSBool
nsXPCComponents::AttachComponentsObject(XPCCallContext& ccx,
XPCWrappedNativeScope* aScope)
{
JSObject *components = aScope->GetComponentsJSObject(ccx);
RootedObject components(ccx, aScope->GetComponentsJSObject(ccx));
if (!components)
return false;
JSObject *global = aScope->GetGlobalJSObject();
RootedObject global(ccx, aScope->GetGlobalJSObject());
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
: &ContentComponentsGetterOp;
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
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),
"JSNative callee should be Function object");
JSString *str = JS_GetFunctionId(JS_GetObjectFunction(funobj));
jsid methodId = str ? INTERNED_STRING_TO_JSID(cx, str) : JSID_VOID;
RootedString str(cx, JS_GetFunctionId(JS_GetObjectFunction(funobj)));
RootedId methodId(cx, str ? INTERNED_STRING_TO_JSID(cx, str) : JSID_VOID);
GetMemberInfo(JSVAL_TO_OBJECT(vp[1]), methodId, ifaceNamep);
*memberIdp = methodId;
}
@ -361,8 +361,8 @@ void
xpc_qsThrowBadArg(JSContext *cx, nsresult rv, jsval *vp, unsigned paramnum)
{
const char *ifaceName;
jsid memberId;
GetMethodInfo(cx, vp, &ifaceName, &memberId);
RootedId memberId(cx);
GetMethodInfo(cx, vp, &ifaceName, memberId.address());
ThrowBadArg(cx, rv, ifaceName, memberId, NULL, paramnum);
}
@ -381,8 +381,9 @@ xpc_qsThrowBadArgWithDetails(JSContext *cx, nsresult rv, unsigned paramnum,
void
xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
JSObject *obj, jsid propId)
JSObject *obj, jsid propIdArg)
{
RootedId propId(cx, propIdArg);
const char *ifaceName;
GetMemberInfo(obj, propId, &ifaceName);
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...
nsXPTCVariant xpctvar;
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),
"bad scope for new JSObjects");
@ -440,100 +433,134 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
case nsIDataType::VTYPE_FLOAT:
case nsIDataType::VTYPE_DOUBLE:
{
// Easy. Handle inline.
if (NS_FAILED(variant->GetAsDouble(&xpctvar.val.d)))
double d;
if (NS_FAILED(variant->GetAsDouble(&d)))
return false;
*pJSVal = JS_NumberValue(xpctvar.val.d);
*pJSVal = JS_NumberValue(d);
return true;
}
case nsIDataType::VTYPE_BOOL:
{
// Easy. Handle inline.
if (NS_FAILED(variant->GetAsBool(&xpctvar.val.b)))
bool b;
if (NS_FAILED(variant->GetAsBool(&b)))
return false;
*pJSVal = BOOLEAN_TO_JSVAL(xpctvar.val.b);
*pJSVal = BOOLEAN_TO_JSVAL(b);
return true;
}
case nsIDataType::VTYPE_CHAR:
if (NS_FAILED(variant->GetAsChar(&xpctvar.val.c)))
{
char c;
if (NS_FAILED(variant->GetAsChar(&c)))
return false;
xpctvar.type = (uint8_t)TD_CHAR;
break;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&c, TD_CHAR, &iid, pErr);
}
case nsIDataType::VTYPE_WCHAR:
if (NS_FAILED(variant->GetAsWChar(&xpctvar.val.wc)))
{
PRUnichar wc;
if (NS_FAILED(variant->GetAsWChar(&wc)))
return false;
xpctvar.type = (uint8_t)TD_WCHAR;
break;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&wc, TD_WCHAR, &iid, pErr);
}
case nsIDataType::VTYPE_ID:
{
if (NS_FAILED(variant->GetAsID(&iid)))
return false;
xpctvar.type = (uint8_t)TD_PNSIID;
xpctvar.val.p = &iid;
break;
nsID *v = &iid;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v, TD_PNSIID, &iid, pErr);
}
case nsIDataType::VTYPE_ASTRING:
{
nsAutoString astring;
if (NS_FAILED(variant->GetAsAString(astring)))
return false;
xpctvar.type = (uint8_t)TD_ASTRING;
xpctvar.val.p = &astring;
break;
nsAutoString *v = &astring;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v, TD_ASTRING, &iid, pErr);
}
case nsIDataType::VTYPE_DOMSTRING:
{
nsAutoString astring;
if (NS_FAILED(variant->GetAsAString(astring)))
return false;
xpctvar.type = (uint8_t)TD_DOMSTRING;
xpctvar.val.p = &astring;
break;
nsAutoString *v = &astring;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
TD_DOMSTRING, &iid, pErr);
}
case nsIDataType::VTYPE_CSTRING:
{
nsAutoCString cString;
if (NS_FAILED(variant->GetAsACString(cString)))
return false;
xpctvar.type = (uint8_t)TD_CSTRING;
xpctvar.val.p = &cString;
break;
nsAutoCString *v = &cString;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
TD_CSTRING, &iid, pErr);
}
case nsIDataType::VTYPE_UTF8STRING:
{
nsUTF8String utf8String;
if (NS_FAILED(variant->GetAsAUTF8String(utf8String)))
return false;
xpctvar.type = (uint8_t)TD_UTF8STRING;
xpctvar.val.p = &utf8String;
break;
nsUTF8String *v = &utf8String;
return XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&v,
TD_UTF8STRING, &iid, pErr);
}
case nsIDataType::VTYPE_CHAR_STR:
if (NS_FAILED(variant->GetAsString((char**)&xpctvar.val.p)))
{
char *pc;
if (NS_FAILED(variant->GetAsString(&pc)))
return false;
xpctvar.type = (uint8_t)TD_PSTRING;
xpctvar.SetValNeedsCleanup();
break;
bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pc,
TD_PSTRING, &iid, pErr);
nsMemory::Free(pc);
return success;
}
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;
xpctvar.type = (uint8_t)TD_PSTRING_SIZE_IS;
xpctvar.SetValNeedsCleanup();
break;
bool success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal, (const void*)&pc,
TD_PSTRING_SIZE_IS, size, pErr);
nsMemory::Free(pc);
return success;
}
case nsIDataType::VTYPE_WCHAR_STR:
if (NS_FAILED(variant->GetAsWString((PRUnichar**)&xpctvar.val.p)))
{
PRUnichar *pwc;
if (NS_FAILED(variant->GetAsWString(&pwc)))
return false;
xpctvar.type = (uint8_t)TD_PWSTRING;
xpctvar.SetValNeedsCleanup();
break;
bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pwc,
TD_PSTRING, &iid, pErr);
nsMemory::Free(pwc);
return success;
}
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;
xpctvar.type = (uint8_t)TD_PWSTRING_SIZE_IS;
xpctvar.SetValNeedsCleanup();
break;
bool success = XPCConvert::NativeStringWithSize2JS(cx, pJSVal, (const void*)&pwc,
TD_PWSTRING_SIZE_IS, size, pErr);
nsMemory::Free(pwc);
return success;
}
case nsIDataType::VTYPE_INTERFACE:
case nsIDataType::VTYPE_INTERFACE_IS:
{
nsISupports *pi;
nsID* piid;
if (NS_FAILED(variant->GetAsInterface(&piid, &xpctvar.val.p)))
if (NS_FAILED(variant->GetAsInterface(&piid, (void **)&pi)))
return false;
iid = *piid;
nsMemory::Free((char*)piid);
xpctvar.type = (uint8_t)TD_INTERFACE_IS_TYPE;
if (xpctvar.val.p)
xpctvar.SetValNeedsCleanup();
break;
bool success = XPCConvert::NativeData2JS(lccx, pJSVal, (const void*)&pi,
TD_INTERFACE_IS_TYPE, &iid, pErr);
if (pi)
pi->Release();
return success;
}
case nsIDataType::VTYPE_ARRAY:
{
@ -550,7 +577,7 @@ XPCVariant::VariantDataToJS(XPCLazyCallContext& lccx,
// must exit via VARIANT_DONE from here on...
du.mType = nsIDataType::VTYPE_ARRAY;
success = false;
bool success = false;
nsXPTType conversionType;
uint16_t elementType = du.u.array.mArrayType;
@ -633,32 +660,6 @@ VARIANT_DONE:
NS_ERROR("bad type in variant!");
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.
RootedObject flat(cx, GetFlatJSObject());
JSObject *wrapper = GetWrapper();
RootedObject wrapper(cx, GetWrapper());
// If we already have a wrapper, it must be what we want.
if (wrapper)

View File

@ -2031,7 +2031,7 @@ xpc_ActivateDebugMode()
JSContext*
nsXPConnect::GetCurrentJSContext()
{
JSContext *cx = XPCJSRuntime::Get()->GetJSContextStack()->Peek();
JSContext *cx = GetRuntime()->GetJSContextStack()->Peek();
return xpc_UnmarkGrayContext(cx);
}
@ -2039,7 +2039,7 @@ nsXPConnect::GetCurrentJSContext()
JSContext*
nsXPConnect::GetSafeJSContext()
{
return XPCJSRuntime::Get()->GetJSContextStack()->GetSafeJSContext();
return GetRuntime()->GetJSContextStack()->GetSafeJSContext();
}
namespace xpc {
@ -2373,14 +2373,14 @@ nsXPConnect::SetDebugModeWhenPossible(bool mode, bool allowSyncDisable)
NS_IMETHODIMP
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)
return NS_ERROR_OUT_OF_MEMORY;
unsigned attrs = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
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))
return NS_ERROR_OUT_OF_MEMORY;

View File

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