Bug 1098961 - Prohibit use of .next() iteration in self hosted code, r=nmatsakis.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 18 Nov 2014 09:05:00 -0700
changeset 216305 52f500342c8835e97098fa4bb3e3483c69aec6eb
parent 216304 e6fdb771bce0482f65b7058d35706fb6e8df4350
child 216306 1608ca65d899951b980be5a86f9073546ff6bad2
push id27845
push userkwierso@gmail.com
push dateWed, 19 Nov 2014 02:08:01 +0000
treeherdermozilla-central@64e7a6391916 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnmatsakis
bugs1098961
milestone36.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 1098961 - Prohibit use of .next() iteration in self hosted code, r=nmatsakis.
js/src/builtin/TypedObject.js
js/src/frontend/BytecodeEmitter.cpp
js/src/jit-test/tests/TypedObject/bug1098961.js
--- a/js/src/builtin/TypedObject.js
+++ b/js/src/builtin/TypedObject.js
@@ -786,17 +786,17 @@ function BuildTypedSeqImpl(arrayType, le
     // RangeError("bad depth")
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   // For example, if we have as input
   //    ArrayType(ArrayType(T, 4), 5)
   // and a depth of 2, we get
   //    grainType = T
   //    iterationSpace = [5, 4]
-  var [iterationSpace, grainType, totalLength] =
+  var {iterationSpace, grainType, totalLength} =
     ComputeIterationSpace(arrayType, depth, len);
 
   // Create a zeroed instance with no data
   var result = new arrayType();
 
   var indices = NewDenseArray(depth);
   for (var i = 0; i < depth; i++) {
     indices[i] = 0;
@@ -840,17 +840,19 @@ function ComputeIterationSpace(arrayType
       iterationSpace[i] = grainLen;
       totalLength *= grainLen;
       grainType = grainType.elementType;
     } else {
       // RangeError("Depth "+depth+" too high");
       ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
     }
   }
-  return [iterationSpace, grainType, totalLength];
+  return { iterationSpace: iterationSpace,
+           grainType: grainType,
+           totalLength: totalLength };
 }
 
 function IncrementIterationSpace(indices, iterationSpace) {
   // Increment something like
   //     [5, 5, 7, 8]
   // in an iteration space of
   //     [9, 9, 9, 9]
   // to
@@ -932,21 +934,21 @@ function MapTypedSeqImpl(inArray, depth,
   assert(IsObject(inArray) && ObjectIsTypedObject(inArray), "Map/From called on non-object or untyped input array.");
   assert(TypeDescrIsArrayType(outputType), "Map/From called on non array-type outputType");
 
   if (depth <= 0 || TO_INT32(depth) !== depth)
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
 
   // Compute iteration space for input and output and check for compatibility.
   var inputType = TypeOfTypedObject(inArray);
-  var [inIterationSpace, inGrainType, _] =
+  var {iterationSpace:inIterationSpace, grainType:inGrainType} =
     ComputeIterationSpace(inputType, depth, inArray.length);
   if (!IsObject(inGrainType) || !ObjectIsTypeDescr(inGrainType))
     ThrowError(JSMSG_TYPEDOBJECT_BAD_ARGS);
-  var [iterationSpace, outGrainType, totalLength] =
+  var {iterationSpace, grainType:outGrainType, totalLength} =
     ComputeIterationSpace(outputType, depth, outputType.length);
   for (var i = 0; i < depth; i++)
     if (inIterationSpace[i] !== iterationSpace[i])
       // TypeError("Incompatible iteration space in input and output type");
       ThrowError(JSMSG_TYPEDOBJECT_ARRAYTYPE_BAD_ARGS);
 
   // Create a zeroed instance with no data
   var result = new outputType();
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -3420,16 +3420,20 @@ static bool EmitIterator(ExclusiveContex
 
 /**
  * EmitIteratorNext will pop iterator from the top of the stack.
  * It will push the result of |.next()| onto the stack.
  */
 static bool
 EmitIteratorNext(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn=nullptr)
 {
+    MOZ_ASSERT(bce->emitterMode != BytecodeEmitter::SelfHosting,
+               ".next() iteration is prohibited in self-hosted code because it "
+               "can run user-modifiable iteration code");
+
     if (Emit1(cx, bce, JSOP_DUP) < 0)                          // ... ITER ITER
         return false;
     if (!EmitAtomOp(cx, cx->names().next, JSOP_CALLPROP, bce)) // ... ITER NEXT
         return false;
     if (Emit1(cx, bce, JSOP_SWAP) < 0)                         // ... NEXT ITER
         return false;
     if (EmitCall(cx, bce, JSOP_CALL, 0, pn) < 0)               // ... RESULT
         return false;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/TypedObject/bug1098961.js
@@ -0,0 +1,9 @@
+if (!this.hasOwnProperty("TypedObject"))
+    quit();
+
+Array.prototype[Symbol.iterator] = function() {
+    for (var i = 3; --i >= 0;) {
+        yield this[i]
+    }
+}
+new TypedObject.ArrayType(TypedObject.int32, 0).build(1, x => 1)