Bug 1267364 - Check isNative every time in GetStringDataProperty. r=h4writer, a=sylvestre
authorTooru Fujisawa <arai_a@mac.com>
Tue, 26 Apr 2016 08:08:46 +0900
changeset 332611 cbeae0c4410bef3864b3d3f4ad939321c61cb15b
parent 332610 ca6ab5be342e2d7817b0015447872dab3ecd5ef1
child 332612 88c0b444691016e0fd49c901a8e54f82d4c6a665
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer, sylvestre
bugs1267364
milestone48.0a2
Bug 1267364 - Check isNative every time in GetStringDataProperty. r=h4writer, a=sylvestre
js/src/builtin/RegExp.cpp
js/src/builtin/RegExpGlobalReplaceOpt.h.js
js/src/jit-test/tests/self-hosting/GetStringDataProperty.js
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -1654,23 +1654,32 @@ js::intrinsic_GetElemBaseForLambda(JSCon
  * propety value is a string.  Otherwise it returns undefined.
  */
 bool
 js::intrinsic_GetStringDataProperty(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     MOZ_ASSERT(args.length() == 2);
 
-    RootedNativeObject obj(cx, &args[0].toObject().as<NativeObject>());
+    RootedObject obj(cx, &args[0].toObject());
+    if (!obj->isNative()) {
+        // The object is already checked to be native in GetElemBaseForLambda,
+        // but it can be swapped to the other class that is non-native.
+        // Return undefined to mark failure to get the property.
+        args.rval().setUndefined();
+        return true;
+    }
+
+    RootedNativeObject nobj(cx, &obj->as<NativeObject>());
     RootedString name(cx, args[1].toString());
 
     RootedAtom atom(cx, AtomizeString(cx, name));
     if (!atom)
         return false;
 
     RootedValue v(cx);
-    if (HasDataProperty(cx, obj, AtomToId(atom), v.address()) && v.isString())
+    if (HasDataProperty(cx, nobj, AtomToId(atom), v.address()) && v.isString())
         args.rval().set(v);
     else
         args.rval().setUndefined();
 
     return true;
 }
--- a/js/src/builtin/RegExpGlobalReplaceOpt.h.js
+++ b/js/src/builtin/RegExpGlobalReplaceOpt.h.js
@@ -75,20 +75,22 @@ function FUNC_NAME(rx, S, lengthS, repla
 #elif defined(SUBSTITUTION)
         replacement = RegExpGetComplexReplacement(result, matched, S, position,
 
                                                   nCaptures, replaceValue,
                                                   false, firstDollarIndex);
 #elif defined(ELEMBASE)
         if (IsObject(elemBase)) {
             var prop = GetStringDataProperty(elemBase, matched);
-            if (prop !== undefined)
+            if (prop !== undefined) {
+                assert(typeof prop === "string", "GetStringDataProperty should return either string or undefined");
                 replacement = prop;
-            else
+            } else {
                 elemBase = undefined;
+            }
         }
 
         if (!IsObject(elemBase)) {
             // Steps 14.a-b (reordered).
             nCaptures = std_Math_max(result.length - 1, 0);
 
             replacement = RegExpGetComplexReplacement(result, matched, S, position,
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/self-hosting/GetStringDataProperty.js
@@ -0,0 +1,33 @@
+// Bug 1267364 - GetStringDataProperty should return undefined when the object
+// is non-native.
+
+var GetStringDataProperty = getSelfHostedValue("GetStringDataProperty");
+
+function testProxy() {
+    var obj = new Proxy({"foo": "10"}, {});
+    var v = GetStringDataProperty(obj, "foo");
+    assertEq(v, undefined);
+}
+
+function testMaybeUnboxed() {
+    // Use JSON.parse to create unboxed object if availbale.
+    var obj = JSON.parse("[" + '{"foo": "10"},'.repeat(100) +"{}]");
+
+    // GetStringDataProperty may return "10" or undefined, depending on whether
+    // `obj` is unboxed or not
+    var v = GetStringDataProperty(obj[0], "foo");
+    assertEq(v == undefined || v == "10", true);
+}
+
+function testTypedObject() {
+    var {StructType, string} = TypedObject;
+    var S = new StructType({foo: string});
+    var obj = new S({foo: "10"});
+    var v = GetStringDataProperty(obj, "foo");
+    assertEq(v, undefined);
+}
+
+testProxy();
+testMaybeUnboxed();
+if (typeof TypedObject !== "undefined")
+    testTypedObject();