Skip to content

Commit 0d87690

Browse files
committed
new validation checks for upcoming spec tests
1 parent 816ec66 commit 0d87690

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

src/wasm-s-parser.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1402,9 +1402,10 @@ class SExpressionWasmBuilder {
14021402
}
14031403

14041404
void parseData(Element& s) {
1405+
if (!hasMemory) throw ParseException("data but no memory");
14051406
Index i = 1;
14061407
Expression* offset;
1407-
if (s[i]->isList()) {
1408+
if (i < s.size() && s[i]->isList()) {
14081409
// there is an init expression
14091410
offset = parseExpression(s[i++]);
14101411
} else {

src/wasm-validator.h

+33-3
Original file line numberDiff line numberDiff line change
@@ -197,11 +197,11 @@ struct WasmValidator : public PostWalker<WasmValidator, Visitor<WasmValidator>>
197197
}
198198
}
199199
void visitLoad(Load *curr) {
200-
validateAlignment(curr->align);
200+
validateAlignment(curr->align, curr->type, curr->bytes);
201201
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "load pointer type must be i32");
202202
}
203203
void visitStore(Store *curr) {
204-
validateAlignment(curr->align);
204+
validateAlignment(curr->align, curr->type, curr->bytes);
205205
shouldBeEqualOrFirstIsUnreachable(curr->ptr->type, i32, curr, "store pointer type must be i32");
206206
shouldBeUnequal(curr->value->type, none, curr, "store value type must not be none");
207207
shouldBeEqualOrFirstIsUnreachable(curr->value->type, curr->valueType, curr, "store value type must match");
@@ -357,6 +357,20 @@ struct WasmValidator : public PostWalker<WasmValidator, Visitor<WasmValidator>>
357357
void visitMemory(Memory *curr) {
358358
shouldBeFalse(curr->initial > curr->max, "memory", "memory max >= initial");
359359
shouldBeTrue(curr->max <= Memory::kMaxSize, "memory", "max memory must be <= 4GB");
360+
Index mustBeGreaterOrEqual = 0;
361+
for (auto& segment : curr->segments) {
362+
if (!shouldBeEqual(segment.offset->type, i32, segment.offset, "segment offset should be i32")) continue;
363+
shouldBeTrue(isConstant(segment.offset), segment.offset, "segment offset should be constant");
364+
Index size = segment.data.size();
365+
shouldBeTrue(size <= curr->initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory");
366+
if (segment.offset->is<Const>()) {
367+
Index start = segment.offset->cast<Const>()->value.geti32();
368+
Index end = start + size;
369+
shouldBeTrue(end <= curr->initial * Memory::kPageSize, segment.data.size(), "segment size should fit in memory");
370+
shouldBeTrue(start >= mustBeGreaterOrEqual, segment.data.size(), "segment size should fit in memory");
371+
mustBeGreaterOrEqual = end;
372+
}
373+
}
360374
}
361375
void visitTable(Table* curr) {
362376
for (auto& segment : curr->segments) {
@@ -476,7 +490,7 @@ struct WasmValidator : public PostWalker<WasmValidator, Visitor<WasmValidator>>
476490
return true;
477491
}
478492

479-
void validateAlignment(size_t align) {
493+
void validateAlignment(size_t align, WasmType type, Index bytes) {
480494
switch (align) {
481495
case 1:
482496
case 2:
@@ -488,6 +502,22 @@ struct WasmValidator : public PostWalker<WasmValidator, Visitor<WasmValidator>>
488502
break;
489503
}
490504
}
505+
shouldBeTrue(align <= bytes, align, "alignment must not exceed natural");
506+
switch (type) {
507+
case i32:
508+
case f32: {
509+
shouldBeTrue(align <= 4, align, "alignment must not exceed natural");
510+
break;
511+
}
512+
case i64:
513+
case f64: {
514+
shouldBeTrue(align <= 8, align, "alignment must not exceed natural");
515+
break;
516+
}
517+
default: {
518+
fail() << "bad alignment type" << std::endl;
519+
}
520+
}
491521
}
492522
};
493523

0 commit comments

Comments
 (0)