Bug 1305318: Reject a typed jump to the top of a loop in a br_table; r=sunfish
authorBenjamin Bouvier <benj@benj.me>
Fri, 30 Sep 2016 16:07:13 +0200
changeset 316082 56f95c86c04c893ecf87a0dad7b2d1ff91b5b1c7
parent 316081 e517fba7718a4ffd0c7dbfc1d133da7dc39e71f3
child 316083 a08af19f3b3c08a431da4951537ac76ed58c7da2
push id30759
push userphilringnalda@gmail.com
push dateSat, 01 Oct 2016 06:25:09 +0000
treeherdermozilla-central@fcc62bbf09ee [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssunfish
bugs1305318
milestone52.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 1305318: Reject a typed jump to the top of a loop in a br_table; r=sunfish MozReview-Commit-ID: 2THEPuKEXq7
js/src/asmjs/WasmBinaryIterator.h
js/src/asmjs/WasmIonCompile.cpp
js/src/asmjs/WasmTextToBinary.cpp
js/src/jit-test/tests/wasm/regress/misc-control-flow.js
--- a/js/src/asmjs/WasmBinaryIterator.h
+++ b/js/src/asmjs/WasmBinaryIterator.h
@@ -1107,37 +1107,41 @@ template <typename Policy>
 inline bool
 ExprIter<Policy>::readBrTableEntry(ExprType* type, Value* value, uint32_t* depth)
 {
     MOZ_ASSERT(Classify(expr_) == ExprKind::BrTable);
 
     if (!readVarU32(depth))
         return false;
 
+    ExprType knownType = *type;
+
     if (MOZ_LIKELY(reachable_)) {
         ControlStackEntry<ControlItem>* controlItem = nullptr;
         if (!getControl(*depth, &controlItem))
             return false;
 
         if (controlItem->kind() != LabelKind::Loop) {
             controlItem->setReachable();
 
             // If we've already seen one label, we know the type and can check
             // that the type for the current label matches it.
-            ExprType knownType = *type;
             if (knownType != ExprType::Limit)
                 return checkType(knownType, controlItem->type());
 
             // This is the first label; record the type and the value now.
             ExprType expectedType = controlItem->type();
             if (!IsVoid(expectedType)) {
                 *type = expectedType;
                 return popWithType(NonVoidToValType(expectedType), value);
             }
         }
+
+        if (knownType != ExprType::Limit && knownType != ExprType::Void)
+            return typeMismatch(knownType, ExprType::Void);
     }
 
     *type = ExprType::Void;
     if (Output)
         *value = Value();
     return true;
 }
 
--- a/js/src/asmjs/WasmIonCompile.cpp
+++ b/js/src/asmjs/WasmIonCompile.cpp
@@ -1660,45 +1660,45 @@ EmitBlock(FunctionCompiler& f)
 }
 
 static bool
 EmitLoop(FunctionCompiler& f)
 {
     if (!f.iter().readLoop())
         return false;
 
-    MBasicBlock *loopHeader;
+    MBasicBlock* loopHeader;
     if (!f.startLoop(&loopHeader))
         return false;
 
     f.addInterruptCheck();
 
     f.iter().controlItem() = loopHeader;
     return true;
 }
 
 static bool
 EmitIf(FunctionCompiler& f)
 {
-    MDefinition* condition;
+    MDefinition* condition = nullptr;
     if (!f.iter().readIf(&condition))
         return false;
 
     MBasicBlock* elseBlock;
     if (!f.branchAndStartThen(condition, &elseBlock))
         return false;
 
     f.iter().controlItem() = elseBlock;
     return true;
 }
 
 static bool
 EmitElse(FunctionCompiler& f)
 {
-    MBasicBlock *block = f.iter().controlItem();
+    MBasicBlock* block = f.iter().controlItem();
 
     ExprType thenType;
     MDefinition* thenValue;
     if (!f.iter().readElse(&thenType, &thenValue))
         return false;
 
     if (!IsVoid(thenType))
         f.pushDef(thenValue);
@@ -1707,28 +1707,28 @@ EmitElse(FunctionCompiler& f)
         return false;
 
     return true;
 }
 
 static bool
 EmitEnd(FunctionCompiler& f)
 {
-    MBasicBlock *block = f.iter().controlItem();
+    MBasicBlock* block = f.iter().controlItem();
 
     LabelKind kind;
     ExprType type;
     MDefinition* value;
     if (!f.iter().readEnd(&kind, &type, &value))
         return false;
 
     if (!IsVoid(type))
         f.pushDef(value);
 
-    MDefinition* def;
+    MDefinition* def = nullptr;
     switch (kind) {
       case LabelKind::Block:
         if (!f.finishBlock(&def))
             return false;
         break;
       case LabelKind::Loop:
         if (!f.closeLoop(block, &def))
             return false;
@@ -1744,18 +1744,20 @@ EmitEnd(FunctionCompiler& f)
             return false;
         break;
       case LabelKind::Else:
         if (!f.joinIfElse(block, &def))
             return false;
         break;
     }
 
-    if (!IsVoid(type))
+    if (!IsVoid(type)) {
+        MOZ_ASSERT_IF(!f.inDeadCode(), def);
         f.iter().setResult(def);
+    }
 
     return true;
 }
 
 static bool
 EmitBr(FunctionCompiler& f)
 {
     uint32_t relativeDepth;
--- a/js/src/asmjs/WasmTextToBinary.cpp
+++ b/js/src/asmjs/WasmTextToBinary.cpp
@@ -2348,17 +2348,17 @@ ParseBranchTable(WasmParseContext& c, Wa
 
     AstRef target;
     while (c.ts.getIfRef(&target)) {
         if (!table.append(target))
             return nullptr;
     }
 
     if (table.empty()) {
-        c.ts.generateError(brTable, c.error);
+        c.ts.generateError(c.ts.get(), c.error);
         return nullptr;
     }
 
     AstRef def = table.popCopy();
 
     AstExpr* index = ParseExpr(c, inParens);
     if (!index)
         return nullptr;
--- a/js/src/jit-test/tests/wasm/regress/misc-control-flow.js
+++ b/js/src/jit-test/tests/wasm/regress/misc-control-flow.js
@@ -190,8 +190,38 @@ wasmEvalText(`
     ))
     (i32.const 0)
    )
    (i32.const 13)
   )
  )
 )
 `);
+
+wasmFailValidateText(`
+(module
+    (func (result i32)
+      (loop
+        (i32.const 0)
+        (br_table 1 0 (i32.const 15))
+      )
+    )
+)`, mismatchError("i32", "void"));
+
+wasmFailValidateText(`
+(module
+  (func (result i32)
+    (loop i32
+      (i32.const 0)
+      (br_table 1 0 (i32.const 15))
+    )
+  )
+)`, mismatchError("i32", "void"));
+
+wasmValidateText(`
+(module
+    (func
+        (loop
+          (i32.const 0)
+          (br_table 1 0 (i32.const 15))
+        )
+    )
+)`);