summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2016-09-02 17:42:34 -0700
committerAlon Zakai <alonzakai@gmail.com>2016-09-07 09:56:01 -0700
commit52b0fe21ad36ef0e81193d4418916dbec7352fa4 (patch)
tree11254677d2edab0c17697aba55138a83d88389fd /src
parenta07797f1b1264e60912a8c18cb673b829ae0d1a5 (diff)
downloadbinaryen-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.h3
-rw-r--r--src/wasm-validator.h36
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: {}
+ }
}
};