Bug 1267364 - Check isNative every time in GetStringDataProperty. r=h4writer
authorTooru Fujisawa <arai_a@mac.com>
Tue, 26 Apr 2016 08:08:46 +0900
changeset 294845 09aaae5469188c49e28668f407853a25e242aa58
parent 294844 e6e9e16e010ff25f3fd1ff2c2911dee4d1b8b0d2
child 294846 04c75201afd55809655aec766b6b7d7856cfddf9
push id30213
push usercbook@mozilla.com
push dateTue, 26 Apr 2016 11:45:11 +0000
treeherdermozilla-central@9ce31e9f90cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersh4writer
bugs1267364
milestone48.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 1267364 - Check isNative every time in GetStringDataProperty. r=h4writer
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
@@ -1706,23 +1706,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();