diff options
author | Alon Zakai <alonzakai@gmail.com> | 2016-09-02 17:42:34 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2016-09-07 09:56:01 -0700 |
commit | 52b0fe21ad36ef0e81193d4418916dbec7352fa4 (patch) | |
tree | 11254677d2edab0c17697aba55138a83d88389fd /src | |
parent | a07797f1b1264e60912a8c18cb673b829ae0d1a5 (diff) | |
download | binaryen-52b0fe21ad36ef0e81193d4418916dbec7352fa4.tar.gz binaryen-52b0fe21ad36ef0e81193d4418916dbec7352fa4.tar.bz2 binaryen-52b0fe21ad36ef0e81193d4418916dbec7352fa4.zip |
new validation checks for upcoming spec tests
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-s-parser.h | 3 | ||||
-rw-r--r-- | src/wasm-validator.h | 36 |
2 files changed, 34 insertions, 5 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 3d57c5ada..9abdea744 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1402,9 +1402,10 @@ private: } void parseData(Element& s) { + if (!hasMemory) throw ParseException("data but no memory"); Index i = 1; Expression* offset; - if (s[i]->isList()) { + if (i < s.size() && s[i]->isList()) { // there is an init expression offset = parseExpression(s[i++]); } else { diff --git a/src/wasm-validator.h b/src/wasm-validator.h index 92ae24688..58a30f9a3 100644 --- a/src/wasm-validator.h +++ b/src/wasm-validator.h @@ -197,11 +197,11 @@ public: } } void visitLoad(Load *curr) { - validateAlignment(curr->align); + validateAlignment(curr->align, curr->type, curr->bytes); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "load pointer type must be i32"); } void visitStore(Store *curr) { - validateAlignment(curr->align); + validateAlignment(curr->align, curr->type, curr->bytes); shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "store pointer type must be i32"); shouldBeUnequal(curr->value->type, none, curr, "store value type must not be none"); shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->valueType, curr, "store value type must match"); @@ -351,12 +351,26 @@ public: } bool isConstant(Expression* curr) { - return curr->is<Const>(); + return curr->is<Const>() || curr->is<GetGlobal>(); } void visitMemory(Memory *curr) { shouldBeFalse(curr->initial > curr->max, "memory", "memory max >= initial"); shouldBeTrue(curr->max <= Memory::kMaxSize, "memory", "max memory must be <= 4GB"); + Index mustBeGreaterOrEqual = 0; + for (auto& segment : curr->segments) { + if (!shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32")) continue; + shouldBeTrue(isConstant(segment.offset), segment.offset, "segment offset should be constant"); + Index size = segment.data.size(); + shouldBeTrue(size <= curr->initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory"); + if (segment.offset->is<Const>()) { + Index start = segment.offset->cast<Const>()->value.geti32(); + Index end = start + size; + shouldBeTrue(end <= curr->initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory"); + shouldBeTrue(start >= mustBeGreaterOrEqual, segment.data.size(), "segment size should fit in memory"); + mustBeGreaterOrEqual = end; + } + } } void visitTable(Table* curr) { for (auto& segment : curr->segments) { @@ -476,7 +490,7 @@ private: return true; } - void validateAlignment(size_t align) { + void validateAlignment(size_t align, WasmType type, Index bytes) { switch (align) { case 1: case 2: @@ -488,6 +502,20 @@ private: break; } } + shouldBeTrue(align <= bytes, align, "alignment must not exceed natural"); + switch (type) { + case i32: + case f32: { + shouldBeTrue(align <= 4, align, "alignment must not exceed natural"); + break; + } + case i64: + case f64: { + shouldBeTrue(align <= 8, align, "alignment must not exceed natural"); + break; + } + default: {} + } } }; |