diff options
-rw-r--r-- | src/wasm-binary.h | 1 | ||||
-rw-r--r-- | src/wasm-builder.h | 1 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 29 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 6 | ||||
-rw-r--r-- | test/badvartype.wasm | bin | 0 -> 698 bytes | |||
-rw-r--r-- | test/badvartype.wasm.fromBinary | 344 |
6 files changed, 373 insertions, 8 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 4b4a37888..eb3567bf5 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -840,6 +840,7 @@ public: int32_t getS32LEB(); int64_t getS64LEB(); Type getType(); + Type getConcreteType(); Name getString(); Name getInlineString(); void verifyInt8(int8_t x); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 02304acec..b8de8ce25 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -375,6 +375,7 @@ public: static Index addVar(Function* func, Name name, Type type) { // always ok to add a var, it does not affect other indices + assert(isConcreteType(type)); Index index = func->getNumLocals(); if (name.is()) { func->localIndices[name] = index; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index e0c75badc..aae59e6f7 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1491,6 +1491,14 @@ Type WasmBinaryBuilder::getType() { } } +Type WasmBinaryBuilder::getConcreteType() { + auto type = getType(); + if (!isConcreteType(type)) { + throw ParseException("non-concrete type when one expected"); + } + return type; +} + Name WasmBinaryBuilder::getString() { if (debug) std::cerr << "<==" << std::endl; size_t offset = getInt32(); @@ -1579,7 +1587,7 @@ void WasmBinaryBuilder::readSignatures() { size_t numParams = getU32LEB(); if (debug) std::cerr << "num params: " << numParams << std::endl; for (size_t j = 0; j < numParams; j++) { - curr->params.push_back(getType()); + curr->params.push_back(getConcreteType()); } auto numResults = getU32LEB(); if (numResults == 0) { @@ -1667,7 +1675,7 @@ void WasmBinaryBuilder::readImports() { } case ExternalKind::Global: { curr->name = Name(std::string("gimport$") + std::to_string(i)); - curr->globalType = getType(); + curr->globalType = getConcreteType(); auto globalMutable = getU32LEB(); // TODO: actually use the globalMutable flag. Currently mutable global // imports is a future feature, to be implemented with thread support. @@ -1734,7 +1742,7 @@ void WasmBinaryBuilder::readFunctions() { size_t numLocalTypes = getU32LEB(); for (size_t t = 0; t < numLocalTypes; t++) { auto num = getU32LEB(); - auto type = getType(); + auto type = getConcreteType(); while (num > 0) { vars.emplace_back(addVar(), type); num--; @@ -1943,7 +1951,7 @@ void WasmBinaryBuilder::readGlobals() { if (debug) std::cerr << "num: " << num << std::endl; for (size_t i = 0; i < num; i++) { if (debug) std::cerr << "read one" << std::endl; - auto type = getType(); + auto type = getConcreteType(); auto mutable_ = getU32LEB(); if (bool(mutable_) != mutable_) throw ParseException("Global mutability must be 0 or 1"); auto* init = readExpression(); @@ -2057,11 +2065,16 @@ Expression* WasmBinaryBuilder::popNonVoidExpression() { block->list.push_back(expressions.back()); expressions.pop_back(); } - auto type = block->list[0]->type; requireFunctionContext("popping void where we need a new local"); - auto local = builder.addVar(currFunction, type); - block->list[0] = builder.makeSetLocal(local, block->list[0]); - block->list.push_back(builder.makeGetLocal(local, type)); + auto type = block->list[0]->type; + if (isConcreteType(type)) { + auto local = builder.addVar(currFunction, type); + block->list[0] = builder.makeSetLocal(local, block->list[0]); + block->list.push_back(builder.makeGetLocal(local, type)); + } else { + assert(type == unreachable); + // nothing to do here - unreachable anyhow + } block->finalize(); return block; } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index d6c6e7bd0..2e432b174 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -795,6 +795,12 @@ void FunctionValidator::visitHost(Host* curr) { } void FunctionValidator::visitFunction(Function* curr) { + for (auto type : curr->params) { + shouldBeTrue(isConcreteType(type), curr, "params must be concretely typed"); + } + for (auto type : curr->vars) { + shouldBeTrue(isConcreteType(type), curr, "vars must be concretely typed"); + } // if function has no result, it is ignored // if body is unreachable, it might be e.g. a return if (curr->body->type != unreachable) { diff --git a/test/badvartype.wasm b/test/badvartype.wasm Binary files differnew file mode 100644 index 000000000..05637e5f6 --- /dev/null +++ b/test/badvartype.wasm diff --git a/test/badvartype.wasm.fromBinary b/test/badvartype.wasm.fromBinary new file mode 100644 index 000000000..c1441870c --- /dev/null +++ b/test/badvartype.wasm.fromBinary @@ -0,0 +1,344 @@ +(module + (type $0 (func (param i32) (result f32))) + (type $1 (func)) + (type $2 (func (param i64) (result f64))) + (type $3 (func (param f32 i32 i32 i64 i64 i32 i32) (result f64))) + (type $4 (func (param f32 f32) (result i64))) + (type $5 (func (result i64))) + (type $6 (func (param i32 i32))) + (type $7 (func (param f32) (result f32))) + (type $8 (func (param f64) (result f64))) + (global $global$0 (mut i32) (i32.const 255)) + (global $global$1 (mut i32) (i32.const -7045592)) + (global $global$2 (mut i64) (i64.const -9223372036854775808)) + (global $global$3 (mut f32) (f32.const -268435456)) + (global $global$4 (mut f64) (f64.const -2251799813685248)) + (global $global$5 (mut i32) (i32.const 10)) + (table 2 anyfunc) + (elem (i32.const 0) $1 $5) + (memory $0 (shared 1 1)) + (data (i32.const 0) "\00\00\00\00\00\00\00\00X\00\00\00U\00\00\0b\00\00\00\00\00\00\00k\00\00") + (export "func_0" (func $0)) + (export "func_2_invoker" (func $3)) + (export "hangLimitInitializer" (func $7)) + (func $0 (; 0 ;) (type $0) (param $var$0 i32) (result f32) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return + (f32.const -nan:0x1d717c) + ) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (block $label$3 (result f32) + (nop) + (return + (f32.const 137438953472) + ) + ) + ) + (func $1 (; 1 ;) (type $2) (param $var$0 i64) (result f64) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return + (f64.const 128) + ) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (block $label$3 (result f64) + (nop) + (return + (f64.const 1) + ) + ) + ) + (func $2 (; 2 ;) (type $3) (param $var$0 f32) (param $var$1 i32) (param $var$2 i32) (param $var$3 i64) (param $var$4 i64) (param $var$5 i32) (param $var$6 i32) (result f64) + (local $var$7 i32) + (local $var$8 i32) + (local $var$9 i64) + (local $var$10 f32) + (local $var$11 f32) + (local $var$12 f32) + (local $var$13 f64) + (local $var$14 f64) + (local $var$15 f64) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return + (get_local $var$13) + ) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (f64.const 65489) + ) + (func $3 (; 3 ;) (type $1) + (drop + (call $2 + (f32.const 2199023255552) + (i32.const 50) + (i32.const 0) + (i64.const 32767) + (i64.const -65535) + (i32.const -2147483648) + (i32.const -84) + ) + ) + (drop + (f32.const 70368744177664) + ) + (drop + (i32.const -53) + ) + (drop + (i32.const -46) + ) + (drop + (i64.const -12216) + ) + (drop + (i64.const 0) + ) + (unreachable) + ) + (func $4 (; 4 ;) (type $4) (param $var$0 f32) (param $var$1 f32) (result i64) + (local $var$2 i32) + (local $var$3 i32) + (local $var$4 i32) + (local $var$5 i32) + (local $var$6 i32) + (local $var$7 i64) + (local $var$8 i64) + (local $var$9 f32) + (local $var$10 f32) + (local $var$11 f32) + (local $var$12 f64) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return + (get_local $var$8) + ) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (unreachable) + ) + (func $5 (; 5 ;) (type $5) (result i64) + (local $0 i64) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return + (block (result i64) + (set_local $0 + (i64.const 0) + ) + (nop) + (get_local $0) + ) + ) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (i64.const 3832563226) + ) + (func $6 (; 6 ;) (type $6) (param $var$0 i32) (param $var$1 i32) + (local $var$2 i64) + (block $label$1 + (if + (i32.eqz + (get_global $global$5) + ) + (return) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (block $label$3 + (br_if $label$3 + (get_local $var$1) + ) + (if + (i32.eqz + (get_local $var$1) + ) + (block $label$5 + (nop) + (br_if $label$3 + (tee_local $var$1 + (tee_local $var$1 + (tee_local $var$1 + (if (result i32) + (i32.eqz + (get_local $var$1) + ) + (block $label$7 (result i32) + (set_local $var$2 + (block $label$8 (result i64) + (loop $label$9 + (block $label$10 + (if + (i32.eqz + (get_global $global$5) + ) + (return) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (block $label$12 + (block $label$13 + (set_local $var$1 + (br_if $label$7 + (get_local $var$0) + (i32.eqz + (get_local $var$1) + ) + ) + ) + (if + (i32.eqz + (get_local $var$1) + ) + (br_if $label$5 + (i32.eqz + (br_if $label$7 + (i32.const -125) + (loop $label$15 (result i32) + (block $label$16 + (if + (i32.eqz + (get_global $global$5) + ) + (return) + ) + (set_global $global$5 + (i32.sub + (get_global $global$5) + (i32.const 1) + ) + ) + ) + (block $label$18 (result i32) + (nop) + (br_if $label$15 + (i32.eqz + (tee_local $var$1 + (i32.const 32767) + ) + ) + ) + (i32.const -2147483648) + ) + ) + ) + ) + ) + (block + (drop + (i64.add + (get_local $var$2) + (get_local $var$2) + ) + ) + (nop) + ) + ) + ) + (br_if $label$9 + (get_local $var$1) + ) + (nop) + ) + ) + (get_local $var$2) + ) + ) + (get_local $var$1) + ) + (i32.const -7059178) + ) + ) + ) + ) + ) + ) + (nop) + ) + ) + ) + (func $7 (; 7 ;) (type $1) + (set_global $global$5 + (i32.const 10) + ) + ) + (func $8 (; 8 ;) (type $7) (param $var$0 f32) (result f32) + (if (result f32) + (f32.eq + (get_local $var$0) + (get_local $var$0) + ) + (get_local $var$0) + (f32.const 0) + ) + ) + (func $9 (; 9 ;) (type $8) (param $var$0 f64) (result f64) + (if (result f64) + (f64.eq + (get_local $var$0) + (get_local $var$0) + ) + (get_local $var$0) + (f64.const 0) + ) + ) +) + |