Bug 845862 - Transitively apply waivers for accessor descriptors. r=mrbkap
☠☠ backed out by e60919ded783 ☠ ☠
authorBobby Holley <bobbyholley@gmail.com>
Tue, 02 Apr 2013 18:51:19 -0700
changeset 127128 6c6ab0e54917
parent 127127 63453515a870
child 127129 97d16e7beb27
push id117
push usertomi.aarnio@nokia.com
push dateWed, 03 Apr 2013 12:07:07 +0000
reviewersmrbkap
bugs845862
milestone23.0a1
Bug 845862 - Transitively apply waivers for accessor descriptors. r=mrbkap
js/xpconnect/tests/unit/test_bug845862.js
js/xpconnect/tests/unit/xpcshell.ini
js/xpconnect/wrappers/WaiveXrayWrapper.cpp
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/unit/test_bug845862.js
@@ -0,0 +1,13 @@
+const Cu = Components.utils;
+
+function run_test() {
+  // We rely on the crazy "wantXrays:false also causes values return from the
+  // sandbox to be waived" behavior, because it's the simplest way to get
+  // waivers out of the sandbox (which has no native objects). :-(
+  var sb = new Cu.Sandbox('http://www.example.com', {wantXrays: false});
+  Cu.evalInSandbox("this.foo = {}; Object.defineProperty(foo, 'bar', {get: function() {return {};}});", sb);
+  do_check_true(sb.foo != XPCNativeWrapper(sb.foo), "sb.foo is waived");
+  var desc = Object.getOwnPropertyDescriptor(sb.foo, 'bar');
+  var b = desc.get();
+  do_check_true(b != XPCNativeWrapper(b), "results from accessor descriptors are waived");
+}
--- a/js/xpconnect/tests/unit/xpcshell.ini
+++ b/js/xpconnect/tests/unit/xpcshell.ini
@@ -12,16 +12,17 @@ tail =
 [test_bug677864.js]
 [test_bug711404.js]
 [test_bug778409.js]
 [test_bug780370.js]
 [test_bug805807.js]
 [test_bug809652.js]
 [test_bug813901.js]
 [test_bug845201.js]
+[test_bug845862.js]
 [test_bug849730.js]
 [test_bug851895.js]
 [test_bug854558.js]
 [test_bug_442086.js]
 [test_file.js]
 [test_blob.js]
 [test_import.js]
 [test_import_fail.js]
--- a/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
+++ b/js/xpconnect/wrappers/WaiveXrayWrapper.cpp
@@ -10,40 +10,59 @@
 #include "XPCWrapper.h"
 
 #include "WaiveXrayWrapper.h"
 #include "AccessCheck.h"
 #include "WrapperFactory.h"
 
 namespace xpc {
 
+static bool
+WaiveAccessors(JSContext *cx, js::PropertyDescriptor *desc)
+{
+    if ((desc->attrs & JSPROP_GETTER) && desc->getter) {
+        JS::Value v = JS::ObjectValue(*JS_FUNC_TO_DATA_PTR(JSObject *, desc->getter));
+        if (!WrapperFactory::WaiveXrayAndWrap(cx, &v))
+            return false;
+        desc->getter = js::CastAsJSPropertyOp(&v.toObject());
+    }
+
+    if ((desc->attrs & JSPROP_SETTER) && desc->setter) {
+        JS::Value v = JS::ObjectValue(*JS_FUNC_TO_DATA_PTR(JSObject *, desc->setter));
+        if (!WrapperFactory::WaiveXrayAndWrap(cx, &v))
+            return false;
+        desc->setter = js::CastAsJSStrictPropertyOp(&v.toObject());
+    }
+    return true;
+}
+
 WaiveXrayWrapper::WaiveXrayWrapper(unsigned flags) : js::CrossCompartmentWrapper(flags)
 {
 }
 
 WaiveXrayWrapper::~WaiveXrayWrapper()
 {
 }
 
 bool
 WaiveXrayWrapper::getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*>wrapper,
                                         JS::Handle<jsid> id, js::PropertyDescriptor *desc,
                                         unsigned flags)
 {
     return CrossCompartmentWrapper::getPropertyDescriptor(cx, wrapper, id, desc, flags) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, &desc->value);
+           WrapperFactory::WaiveXrayAndWrap(cx, &desc->value) && WaiveAccessors(cx, desc);
 }
 
 bool
 WaiveXrayWrapper::getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
                                            JS::Handle<jsid> id, js::PropertyDescriptor *desc,
                                            unsigned flags)
 {
     return CrossCompartmentWrapper::getOwnPropertyDescriptor(cx, wrapper, id, desc, flags) &&
-           WrapperFactory::WaiveXrayAndWrap(cx, &desc->value);
+           WrapperFactory::WaiveXrayAndWrap(cx, &desc->value) && WaiveAccessors(cx, desc);
 }
 
 bool
 WaiveXrayWrapper::get(JSContext *cx, JS::Handle<JSObject*> wrapper,
                       JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
                       JS::MutableHandle<JS::Value> vp)
 {
     return CrossCompartmentWrapper::get(cx, wrapper, receiver, id, vp) &&