Bug 876805. Fix unsafe reference gc hazards in dom/ code. r=smaug

This commit is contained in:
Boris Zbarsky 2013-05-29 16:16:04 -04:00
parent 1c76a8045c
commit e1d7ebf663
20 changed files with 74 additions and 62 deletions

View File

@ -2387,7 +2387,8 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
rv = aStream->Write32(mLangVersion);
if (NS_FAILED(rv)) return rv;
// And delegate the writing to the nsIScriptContext
rv = context->Serialize(aStream, mScriptObject);
rv = context->Serialize(aStream,
JS::Handle<JSScript*>::fromMarkedLocation(&mScriptObject));
if (NS_FAILED(rv)) return rv;
return NS_OK;

View File

@ -1437,8 +1437,9 @@ Navigator::EnsureMessagesManager()
NS_ENSURE_TRUE(gpi, NS_ERROR_FAILURE);
// We don't do anything with the return value.
JS::Value prop_val = JSVAL_VOID;
rv = gpi->Init(window, &prop_val);
AutoJSContext cx;
JS::Rooted<JS::Value> prop_val(cx);
rv = gpi->Init(window, prop_val.address());
NS_ENSURE_SUCCESS(rv, rv);
mMessagesManager = messageManager.forget();

View File

@ -1081,9 +1081,9 @@ WrapNativeParent(JSContext *cx, JS::Handle<JSObject*> scope, nsISupports *native
JS::Rooted<JSObject*> obj(cx, nativeWrapperCache->GetWrapper());
if (obj) {
#ifdef DEBUG
jsval debugVal;
JS::Rooted<JS::Value> debugVal(cx);
nsresult rv = WrapNative(cx, scope, native, nativeWrapperCache, false,
&debugVal);
debugVal.address());
NS_ASSERTION(NS_SUCCEEDED(rv) && JSVAL_TO_OBJECT(debugVal) == obj,
"Unexpected object in nsWrapperCache");
#endif
@ -2534,8 +2534,8 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
}
#ifdef DEBUG
JSObject *proto2;
JS_GetPrototype(cx, proto, &proto2);
JS::Rooted<JSObject*> proto2(cx);
JS_GetPrototype(cx, proto, proto2.address());
NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass,
"Hmm, somebody did something evil?");
#endif
@ -3002,7 +3002,7 @@ nsWindowSH::InstallGlobalScopePolluter(JSContext *cx, JS::Handle<JSObject*> obj)
struct ResolveGlobalNameClosure
{
JSContext* cx;
JSObject* obj;
JS::Handle<JSObject*> obj;
bool* retval;
};
@ -3011,10 +3011,10 @@ ResolveGlobalName(const nsAString& aName, void* aClosure)
{
ResolveGlobalNameClosure* closure =
static_cast<ResolveGlobalNameClosure*>(aClosure);
JS::Value dummy;
JS::Rooted<JS::Value> dummy(closure->cx);
bool ok = JS_LookupUCProperty(closure->cx, closure->obj,
aName.BeginReading(), aName.Length(),
&dummy);
dummy.address());
if (!ok) {
*closure->retval = false;
return PL_DHASH_STOP;
@ -3152,8 +3152,9 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
rooter.changeLength(i + 1);
}
JS::Value frval;
bool ret = JS_CallFunctionValue(cx, thisObject, funval, argc, argv, &frval);
JS::Rooted<JS::Value> frval(cx);
bool ret = JS_CallFunctionValue(cx, thisObject, funval, argc, argv,
frval.address());
if (!ret) {
return NS_ERROR_FAILURE;
@ -4813,10 +4814,10 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
}
if (proto) {
JS::Rooted<JSObject*> pobj(cx);
jsval val;
JS::Rooted<JS::Value> val(cx);
if (!::JS_LookupPropertyWithFlagsById(cx, proto, id, flags,
pobj.address(), &val)) {
pobj.address(), val.address())) {
*_retval = JS_FALSE;
return NS_OK;

View File

@ -186,7 +186,7 @@ public:
virtual void ScriptEvaluated(bool aTerminated) = 0;
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
JSScript* aScriptObject) = 0;
JS::Handle<JSScript*> aScriptObject) = 0;
/* Deserialize a script from a stream.
*/

View File

@ -1395,8 +1395,8 @@ nsJSContext::ExecuteScript(JSScript* aScriptObject_,
// The result of evaluation, used only if there were no errors. This need
// not be a GC root currently, provided we run the GC only from the
// operation callback or from ScriptEvaluated.
JS::Value val;
if (!JS_ExecuteScript(mContext, aScopeObject, aScriptObject, &val)) {
JS::Rooted<JS::Value> val(mContext);
if (!JS_ExecuteScript(mContext, aScopeObject, aScriptObject, val.address())) {
ReportPendingException();
}
--mExecuteDepth;
@ -1517,7 +1517,8 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget,
// serialization
nsresult
nsJSContext::Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject)
nsJSContext::Serialize(nsIObjectOutputStream* aStream,
JS::Handle<JSScript*> aScriptObject)
{
if (!aScriptObject)
return NS_ERROR_FAILURE;

View File

@ -90,7 +90,8 @@ public:
virtual void WillInitializeContext();
virtual void DidInitializeContext();
virtual nsresult Serialize(nsIObjectOutputStream* aStream, JSScript* aScriptObject);
virtual nsresult Serialize(nsIObjectOutputStream* aStream,
JS::Handle<JSScript*> aScriptObject);
virtual nsresult Deserialize(nsIObjectInputStream* aStream,
JS::MutableHandle<JSScript*> aResult);

View File

@ -1635,14 +1635,13 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
return;
}
JS::Value val;
val.setObject(*mGlobalJSObject);
JS::Rooted<JS::Value> val(aCx, JS::ObjectValue(*mGlobalJSObject));
// Switch this to UnwrapDOMObjectToISupports once our global objects are
// using new bindings.
nsresult rv = xpc_qsUnwrapArg<nsISupports>(aCx, val, &mGlobalObject,
static_cast<nsISupports**>(getter_AddRefs(mGlobalObjectRef)),
&val);
val.address());
if (NS_FAILED(rv)) {
mGlobalObject = nullptr;
Throw<true>(aCx, NS_ERROR_XPC_BAD_CONVERT_JS);

View File

@ -3524,7 +3524,7 @@ for (uint32_t i = 0; i < length; ++i) {
template = (
"if (%s) {\n"
" ${declName}.SetNull();\n"
"} else if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
"} else if (!ValueToPrimitive<%s, %s>(cx, ${valHandle}, &%s)) {\n"
"%s\n"
"}" % (nullCondition, typeName, conversionBehavior,
writeLoc, exceptionCodeIndented.define()))
@ -3534,7 +3534,7 @@ for (uint32_t i = 0; i < length; ++i) {
writeLoc = "${declName}"
readLoc = writeLoc
template = (
"if (!ValueToPrimitive<%s, %s>(cx, ${val}, &%s)) {\n"
"if (!ValueToPrimitive<%s, %s>(cx, ${valHandle}, &%s)) {\n"
"%s\n"
"}" % (typeName, conversionBehavior, writeLoc,
exceptionCodeIndented.define()))
@ -5377,9 +5377,9 @@ class CGStaticSetter(CGAbstractStaticBindingMethod):
nativeName = CGSpecializedSetter.makeNativeName(self.descriptor,
self.attr)
argv = CGGeneric("""JS::Value* argv = JS_ARGV(cx, vp);
JS::Value undef = JS::UndefinedValue();
JS::Rooted<JS::Value> undef(cx, JS::UndefinedValue());
if (argc == 0) {
argv = &undef;
argv = undef.address();
}""")
call = CGSetterCall(self.attr.type, nativeName, self.descriptor,
self.attr)

View File

@ -91,7 +91,8 @@ struct DisallowedConversion {
typedef int intermediateType;
private:
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
MOZ_NOT_REACHED("This should never be instantiated!");
return false;
}
@ -128,7 +129,8 @@ struct PrimitiveConversionTraits_smallInt {
// corresponding unsigned type.
typedef int32_t jstype;
typedef int32_t intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
return JS::ToInt32(cx, v, retval);
}
};
@ -157,7 +159,8 @@ template<>
struct PrimitiveConversionTraits<int64_t, eDefault> {
typedef int64_t jstype;
typedef int64_t intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
return JS::ToInt64(cx, v, retval);
}
};
@ -166,7 +169,8 @@ template<>
struct PrimitiveConversionTraits<uint64_t, eDefault> {
typedef uint64_t jstype;
typedef uint64_t intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
return JS::ToUint64(cx, v, retval);
}
};
@ -206,7 +210,8 @@ struct PrimitiveConversionTraits_ToCheckedIntHelper {
typedef T jstype;
typedef T intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
double intermediate;
if (!JS::ToNumber(cx, v, &intermediate)) {
return false;
@ -303,7 +308,8 @@ template<>
struct PrimitiveConversionTraits<bool, eDefault> {
typedef JSBool jstype;
typedef bool intermediateType;
static inline bool converter(JSContext* /* unused */, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* /* unused */, JS::Handle<JS::Value> v,
jstype* retval) {
*retval = JS::ToBoolean(v);
return true;
}
@ -319,7 +325,8 @@ struct PrimitiveConversionTraits<double, B> : public DisallowedConversion<double
struct PrimitiveConversionTraits_float {
typedef double jstype;
typedef double intermediateType;
static inline bool converter(JSContext* cx, JS::Value v, jstype* retval) {
static inline bool converter(JSContext* cx, JS::Handle<JS::Value> v,
jstype* retval) {
return JS::ToNumber(cx, v, retval);
}
};
@ -333,7 +340,7 @@ struct PrimitiveConversionTraits<double, eDefault> : PrimitiveConversionTraits_f
template<typename T, ConversionBehavior B>
bool ValueToPrimitive(JSContext* cx, JS::Value v, T* retval)
bool ValueToPrimitive(JSContext* cx, JS::Handle<JS::Value> v, T* retval)
{
typename PrimitiveConversionTraits<T, B>::jstype t;
if (!PrimitiveConversionTraits<T, B>::converter(cx, v, &t))

View File

@ -44,9 +44,9 @@ ParseZoomRatioItemAndAdd(JSContext* aCx, JS::Handle<JSObject*> aArray,
d /= 100;
#endif
JS::Value v = JS_NumberValue(d);
JS::Rooted<JS::Value> v(aCx, JS_NumberValue(d));
if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
if (!JS_SetElement(aCx, aArray, aIndex, v.address())) {
return NS_ERROR_FAILURE;
}
@ -68,8 +68,8 @@ ParseStringItemAndAdd(JSContext* aCx, JS::Handle<JSObject*> aArray,
return NS_ERROR_OUT_OF_MEMORY;
}
JS::Value v = STRING_TO_JSVAL(s);
if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
JS::Rooted<JS::Value> v(aCx, STRING_TO_JSVAL(s));
if (!JS_SetElement(aCx, aArray, aIndex, v.address())) {
return NS_ERROR_FAILURE;
}
@ -102,8 +102,8 @@ ParseDimensionItemAndAdd(JSContext* aCx, JS::Handle<JSObject*> aArray,
return NS_ERROR_FAILURE;
}
JS::Value v = OBJECT_TO_JSVAL(o);
if (!JS_SetElement(aCx, aArray, aIndex, &v)) {
JS::Rooted<JS::Value> v(aCx, OBJECT_TO_JSVAL(o));
if (!JS_SetElement(aCx, aArray, aIndex, v.address())) {
return NS_ERROR_FAILURE;
}

View File

@ -195,9 +195,9 @@ ArchiveRequest::GetFilenamesResult(JSContext* aCx,
JSString* str = JS_NewUCStringCopyZ(aCx, filename.get());
NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
JS::Value item = STRING_TO_JSVAL(str);
JS::Rooted<JS::Value> item(aCx, STRING_TO_JSVAL(str));
if (NS_FAILED(rv) || !JS_SetElement(aCx, array, i, &item)) {
if (NS_FAILED(rv) || !JS_SetElement(aCx, array, i, item.address())) {
return NS_ERROR_FAILURE;
}
}

View File

@ -898,7 +898,7 @@ IDBObjectStore::AppendIndexUpdateInfo(
bool aUnique,
bool aMultiEntry,
JSContext* aCx,
jsval aVal,
JS::Handle<JS::Value> aVal,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray)
{
nsresult rv;

View File

@ -67,7 +67,7 @@ public:
bool aUnique,
bool aMultiEntry,
JSContext* aCx,
jsval aObject,
JS::Handle<JS::Value> aObject,
nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
static nsresult

View File

@ -135,11 +135,11 @@ MobileMessageCallback::NotifyMessageDeleted(bool *aDeleted, uint32_t aSize)
NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
JS::Rooted<JSObject*> deleteArrayObj(cx, JS_NewArrayObject(cx, aSize, NULL));
JS::Value jsValTrue = BOOLEAN_TO_JSVAL(1);
JS::Value jsValFalse = BOOLEAN_TO_JSVAL(0);
JS::Rooted<JS::Value> jsValTrue(cx, JS::BooleanValue(true));
JS::Rooted<JS::Value> jsValFalse(cx, JS::BooleanValue(false));
for (uint32_t i = 0; i < aSize; i++) {
JS_SetElement(cx, deleteArrayObj, i,
aDeleted[i] ? &jsValTrue : &jsValFalse);
aDeleted[i] ? jsValTrue.address() : jsValFalse.address());
}
JS::Rooted<JS::Value> deleteArrayVal(cx, JS::ObjectValue(*deleteArrayObj));

View File

@ -177,7 +177,8 @@ nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
mozilla::Maybe<JSAutoCompartment> ac;
if (value->isObject()) {
ac.construct(cx, &value->toObject());
JS::Rooted<JSObject*> obj(cx, &value->toObject());
ac.construct(cx, obj);
}
nsJSONWriter writer;

View File

@ -633,8 +633,8 @@ bool SetStringProperty(JSContext *cx, JS::Handle<JSObject*> aObject, const char
}
JSString* strValue = JS_NewUCStringCopyZ(cx, aValue.get());
NS_ENSURE_TRUE(strValue, false);
JS::Value valValue = STRING_TO_JSVAL(strValue);
return JS_SetProperty(cx, aObject, aProperty, &valValue);
JS::Rooted<JS::Value> valValue(cx, STRING_TO_JSVAL(strValue));
return JS_SetProperty(cx, aObject, aProperty, valValue.address());
}
/**
@ -706,15 +706,15 @@ bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
return false;
}
JS::Value valVersion = STRING_TO_JSVAL(strVersion);
if (!JS_SetProperty(cx, objSys, "Name", &valVersion)) {
JS::Rooted<JS::Value> valVersion(cx, STRING_TO_JSVAL(strVersion));
if (!JS_SetProperty(cx, objSys, "Name", valVersion.address())) {
return false;
}
}
#if defined(DEBUG)
JS::Value valDebug = JSVAL_TRUE;
if (!JS_SetProperty(cx, objSys, "DEBUG", &valDebug)) {
JS::Rooted<JS::Value> valDebug(cx, JSVAL_TRUE);
if (!JS_SetProperty(cx, objSys, "DEBUG", valDebug.address())) {
return false;
}
#endif

View File

@ -420,9 +420,9 @@ EventListenerManager::DispatchEvent(JSContext* aCx, const EventTarget& aTarget,
}
jsval argv[] = { OBJECT_TO_JSVAL(aEvent) };
jsval rval = JSVAL_VOID;
JS::Rooted<JS::Value> rval(aCx);
if (!JS_CallFunctionValue(aCx, thisObj, listenerVal, ArrayLength(argv),
argv, &rval)) {
argv, rval.address())) {
if (!JS_ReportPendingException(aCx)) {
aRv.Throw(NS_ERROR_FAILURE);
return false;

View File

@ -1525,7 +1525,7 @@ WorkerRunnable::Dispatch(JSContext* aCx)
JSAutoRequest ar(aCx);
JSObject* global = JS_GetGlobalForScopeChain(aCx);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForScopeChain(aCx));
Maybe<JSAutoCompartment> ac;
if (global) {

View File

@ -453,8 +453,8 @@ private:
return false;
}
jsval dummy;
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
JS::Rooted<JS::Value> dummy(aCx);
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", dummy.address())) {
return false;
}
@ -495,8 +495,8 @@ private:
return false;
}
jsval dummy;
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", &dummy)) {
JS::Rooted<JS::Value> dummy(aCx);
if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "v", dummy.address())) {
return false;
}

View File

@ -357,7 +357,7 @@ CheckJSCharInCharRange(jschar c)
#endif
template<typename T>
bool ConvertToPrimitive(JSContext *cx, const JS::Value& v, T *retval)
bool ConvertToPrimitive(JSContext *cx, HandleValue v, T *retval)
{
return ValueToPrimitive<T, eDefault>(cx, v, retval);
}