Bug 1210570 - Ensure that ToPrimitive(location) is not spoofable. r=bz.
authorJason Orendorff <jorendorff@mozilla.com>
Tue, 06 Oct 2015 10:42:17 -0500
changeset 304150 48d1f07e8d39a3ed252ab9eda43a9208ac78a639
parent 304149 2f56d15bb8d69c17a249c2de9c5f95ac4ca766c6
child 304151 b859d76b04516eac20835c742573c3e53b5e26c0
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1210570
milestone44.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 1210570 - Ensure that ToPrimitive(location) is not spoofable. r=bz.
dom/bindings/Codegen.py
js/xpconnect/tests/mochitest/test_bug793969.html
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3340,21 +3340,28 @@ def InitUnforgeablePropertiesOnHolder(de
         if array.hasNonChromeOnly():
             unforgeables.append(CGGeneric(template % array.variableName(False)))
         if array.hasChromeOnly():
             unforgeables.append(
                 CGIfWrapper(CGGeneric(template % array.variableName(True)),
                             "nsContentUtils::ThreadsafeIsCallerChrome()"))
 
     if descriptor.interface.getExtendedAttribute("Unforgeable"):
-        # We do our undefined toJSON here, not as a regular property
-        # because we don't have a concept of value props anywhere in IDL.
+        # We do our undefined toJSON and toPrimitive here, not as a regular
+        # property because we don't have a concept of value props anywhere in
+        # IDL.
         unforgeables.append(CGGeneric(fill(
             """
-            if (!JS_DefineProperty(aCx, unforgeableHolder, "toJSON", JS::UndefinedHandleValue,
+            JS::RootedId toPrimitive(aCx,
+              SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::toPrimitive)));
+            if (!JS_DefinePropertyById(aCx, unforgeableHolder, toPrimitive,
+                                       JS::UndefinedHandleValue,
+                                       JSPROP_READONLY | JSPROP_PERMANENT) ||
+                !JS_DefineProperty(aCx, unforgeableHolder, "toJSON",
+                                   JS::UndefinedHandleValue,
                                    JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
               $*{failureCode}
             }
             """,
             failureCode=failureCode)))
 
     return CGWrapper(CGList(unforgeables), pre="\n")
 
--- a/js/xpconnect/tests/mochitest/test_bug793969.html
+++ b/js/xpconnect/tests/mochitest/test_bug793969.html
@@ -39,12 +39,15 @@ checkThrows(function() { Object.definePr
 checkThrows(function() { delete location.valueOf; Object.defineProperty(location, 'valueOf', { value: function() { return 'hah'; } }); }, 'delete + defineProperty with value');
 checkThrows(function() { Object.defineProperty(location, 'valueOf', { get: function() { return 'hah'; } }); }, 'defineProperty with getter');
 checkThrows(function() { delete location.valueOf; Object.defineProperty(location, 'valueOf', { get: function() { return 'hah'; } }); }, 'delete + defineProperty with getter');
 
 Object.prototype.valueOf = function() { return 'hah'; };
 is(({}).valueOf(), 'hah', "Shadowing on Object.prototype works for vanilla objects");
 is(location.valueOf(), location, "Shadowing on Object.prototype and Location.prototype doesn't for location objects");
 
+location[Symbol.toPrimitive] = function() { return 'hah'; }
+is(location + "", location.toString(), "Should't be able to shadow with toPrimitive");
+
 </script>
 </pre>
 </body>
 </html>