Bug 969410 - Do not expose non-tenured addresses in JS_GetObjectId; r=sfink
authorTerrence Cole <terrence@mozilla.com>
Thu, 20 Feb 2014 13:38:57 -0800
changeset 170330 8f879284bd82d73cdb4222ea1d84b9ed1535ffc6
parent 170329 1f1bb2f2f868dae9381d6e998efc8b49d33cf982
child 170331 f019a781ef44b273154c28ffcf1a329cb4c78a58
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewerssfink
bugs969410
milestone30.0a1
Bug 969410 - Do not expose non-tenured addresses in JS_GetObjectId; r=sfink
dom/xbl/nsXBLBinding.cpp
js/public/Id.h
js/src/jsapi.cpp
js/src/jsapi.h
--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -949,17 +949,17 @@ nsXBLBinding::DoInitJSClass(JSContext *c
       return NS_ERROR_FAILURE;
     }
     if (parent_proto) {
       // We need to create a unique classname based on aClassName and
       // id.  Append a space (an invalid URI character) to ensure that
       // we don't have accidental collisions with the case when parent_proto is
       // null and aClassName ends in some bizarre numbers (yeah, it's unlikely).
       JS::Rooted<jsid> parent_proto_id(cx);
-      if (!::JS_GetObjectId(cx, parent_proto, parent_proto_id.address())) {
+      if (!::JS_GetObjectId(cx, parent_proto, &parent_proto_id)) {
         // Probably OOM
         return NS_ERROR_OUT_OF_MEMORY;
       }
 
       // One space, maybe "0x", at most 16 chars (on a 64-bit system) of long,
       // and a null-terminator (which PR_snprintf ensures is there even if the
       // string representation of what we're printing does not fit in the buffer
       // provided).
--- a/js/public/Id.h
+++ b/js/public/Id.h
@@ -16,19 +16,20 @@
 // such as in JS_NextProperty. Embeddings must not pass JSID_VOID into JSAPI
 // entry points expecting a jsid and do not need to handle JSID_VOID in hooks
 // receiving a jsid except when explicitly noted in the API contract.
 //
 // A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or
 // JS_IdToValue must be used instead.
 
 #include "mozilla/NullPtr.h"
- 
+
 #include "jstypes.h"
 
+#include "js/HeapAPI.h"
 #include "js/RootingAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
 struct jsid
 {
     size_t asBits;
     bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
@@ -111,16 +112,17 @@ JSID_TO_OBJECT(jsid id)
 }
 
 static MOZ_ALWAYS_INLINE jsid
 OBJECT_TO_JSID(JSObject *obj)
 {
     jsid id;
     MOZ_ASSERT(obj != nullptr);
     MOZ_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0);
+    JS_ASSERT(!js::gc::IsInsideNursery(js::gc::GetGCThingRuntime(obj), obj));
     JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT);
     return id;
 }
 
 static MOZ_ALWAYS_INLINE bool
 JSID_IS_GCTHING(jsid id)
 {
     return JSID_IS_STRING(id) || JSID_IS_OBJECT(id);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2414,21 +2414,30 @@ JS_GetConstructor(JSContext *cx, HandleO
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
                              proto->getClass()->name);
         return nullptr;
     }
     return &cval.toObject();
 }
 
 JS_PUBLIC_API(bool)
-JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp)
+JS_GetObjectId(JSContext *cx, HandleObject obj, MutableHandleId idp)
 {
     AssertHeapIsIdle(cx);
     assertSameCompartment(cx, obj);
-    *idp = OBJECT_TO_JSID(obj);
+
+#ifdef JSGC_GENERATIONAL
+    // Ensure that the object is tenured before returning it.
+    if (IsInsideNursery(cx->runtime(), obj)) {
+        MinorGC(cx, JS::gcreason::EVICT_NURSERY);
+        MOZ_ASSERT(!IsInsideNursery(cx->runtime(), obj));
+    }
+#endif
+
+    idp.set(OBJECT_TO_JSID(obj));
     return true;
 }
 
 namespace {
 
 class AutoHoldZone
 {
   public:
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2550,17 +2550,17 @@ extern JS_PUBLIC_API(JSObject *)
 JS_GetConstructor(JSContext *cx, JS::Handle<JSObject*> proto);
 
 /*
  * Get a unique identifier for obj, good for the lifetime of obj (even if it
  * is moved by a copying GC).  Return false on failure (likely out of memory),
  * and true with *idp containing the unique id on success.
  */
 extern JS_PUBLIC_API(bool)
-JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp);
+JS_GetObjectId(JSContext *cx, JS::HandleObject obj, JS::MutableHandleId idp);
 
 namespace JS {
 
 enum ZoneSpecifier {
     FreshZone = 0,
     SystemZone = 1
 };