Bug 1287335 - Properly handle failure to unwrap cross-compartment wrappers in Promise-related DebuggerObject accessors. r=fitzgen
authorTill Schneidereit <till@tillschneidereit.net>
Wed, 20 Jul 2016 04:58:00 -0400
changeset 345944 8ad0c8d5de33527f66ff9d42aab4ed6ab55feecc
parent 345943 37cf5b8d779f9b49da983bc5582b813ea13f189d
child 345945 efb4af0a5b7550d9d2efbb126df62c75a3082be2
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1287335
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1287335 - Properly handle failure to unwrap cross-compartment wrappers in Promise-related DebuggerObject accessors. r=fitzgen
js/src/vm/Debugger.cpp
js/src/vm/Debugger.h
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -8001,26 +8001,34 @@ DebuggerObject::checkThis(JSContext* cx,
         return false;                                                         \
     Debugger* dbg = Debugger::fromChildJSObject(obj);                         \
     obj = (JSObject*) obj->as<NativeObject>().getPrivate();                   \
     MOZ_ASSERT(obj)
 
 #define THIS_DEBUGOBJECT_PROMISE(cx, argc, vp, fnname, args, obj)                   \
    THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, fnname, args, obj);                      \
    obj = CheckedUnwrap(obj);                                                        \
+   if (!obj) {                                                                      \
+       JS_ReportError(cx, "Permission denied to access object");                    \
+       return false;                                                                \
+   }                                                                                \
    if (!obj->is<PromiseObject>()) {                                                 \
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,  \
                             "Debugger", "Promise", obj->getClass()->name);          \
        return false;                                                                \
    }                                                                                \
    Rooted<PromiseObject*> promise(cx, &obj->as<PromiseObject>());
 
 #define THIS_DEBUGOBJECT_OWNER_PROMISE(cx, argc, vp, fnname, args, dbg, obj)        \
    THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, fnname, args, dbg, obj);           \
    obj = CheckedUnwrap(obj);                                                        \
+   if (!obj) {                                                                      \
+       JS_ReportError(cx, "Permission denied to access object");                    \
+       return false;                                                                \
+   }                                                                                \
    if (!obj->is<PromiseObject>()) {                                                 \
        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,  \
                             "Debugger", "Promise", obj->getClass()->name);          \
        return false;                                                                \
    }                                                                                \
    Rooted<PromiseObject*> promise(cx, &obj->as<PromiseObject>());
 
 /* static */ bool
@@ -8324,17 +8332,21 @@ DebuggerObject::errorMessageNameGetter(J
 }
 
 #ifdef SPIDERMONKEY_PROMISE
 /* static */ bool
 DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT(cx, argc, vp, "get isPromise", args, object)
 
-    args.rval().setBoolean(object->isPromise());
+    bool result;
+    if (!DebuggerObject::isPromise(cx, object, result))
+      return false;
+
+    args.rval().setBoolean(result);
     return true;
 }
 
 /* static */ bool
 DebuggerObject::promiseStateGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     THIS_DEBUGOBJECT_OWNER_PROMISE(cx, argc, vp, "get promiseState", args, dbg, refobj);
 
@@ -9003,24 +9015,32 @@ DebuggerObject::isArrowFunction() const
 }
 
 bool
 DebuggerObject::isGlobal() const
 {
     return referent()->is<GlobalObject>();
 }
 
-bool
-DebuggerObject::isPromise() const
-{
-    JSObject* obj = referent();
-    if (IsCrossCompartmentWrapper(obj))
-        obj = CheckedUnwrap(obj);
-
-    return obj->is<PromiseObject>();
+/* static */ bool
+DebuggerObject::isPromise(JSContext* cx, Handle<DebuggerObject*> object,
+                          bool& result)
+{
+    JSObject* referent = object->referent();
+    if (IsCrossCompartmentWrapper(referent)) {
+        referent = CheckedUnwrap(referent);
+
+        if (!referent) {
+            JS_ReportError(cx, "Permission denied to access object");
+            return false;
+        }
+      }
+
+    result = referent->is<PromiseObject>();
+    return true;
 }
 
 /* static */ bool
 DebuggerObject::getClassName(JSContext* cx, Handle<DebuggerObject*> object,
                              MutableHandleString result)
 {
     RootedObject referent(cx, object->referent());
 
@@ -10105,17 +10125,17 @@ DebuggerEnvironment::getNames(JSContext*
             return false;
     }
 
     for (size_t i = 0; i < ids.length(); ++i) {
         jsid id = ids[i];
         if (JSID_IS_ATOM(id) && IsIdentifier(JSID_TO_ATOM(id))) {
             if (!result.append(id))
                 return false;
-        } 
+        }
     }
 
     return true;
 }
 
 /* static */ bool
 DebuggerEnvironment::find(JSContext* cx, Handle<DebuggerEnvironment*> environment, HandleId id,
                           MutableHandle<DebuggerEnvironment*> result)
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -1237,25 +1237,26 @@ class DebuggerObject : public NativeObje
                                              HandleObject bindings, const EvalOptions& options,
                                              MutableHandleValue result);
     static MOZ_MUST_USE bool makeDebuggeeValue(JSContext* cx, Handle<DebuggerObject*> object,
                                                HandleValue value, MutableHandleValue result);
     static MOZ_MUST_USE bool unsafeDereference(JSContext* cx, Handle<DebuggerObject*> object,
                                                MutableHandleObject result);
     static MOZ_MUST_USE bool unwrap(JSContext* cx, Handle<DebuggerObject*> object,
                                     MutableHandle<DebuggerObject*> result);
+    static MOZ_MUST_USE bool isPromise(JSContext* cx, Handle<DebuggerObject*> object,
+                                       bool& result);
 
     // Infallible properties
     bool isCallable() const;
     bool isFunction() const;
     bool isDebuggeeFunction() const;
     bool isBoundFunction() const;
     bool isArrowFunction() const;
     bool isGlobal() const;
-    bool isPromise() const;
     JSAtom* name() const;
     JSAtom* displayName() const;
 
   private:
     enum {
         OWNER_SLOT
     };