summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-validator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r--src/wasm/wasm-validator.cpp102
1 files changed, 73 insertions, 29 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 5e3fdc6e7..ba309ddea 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2110,13 +2110,12 @@ void FunctionValidator::visitRefNull(RefNull* curr) {
shouldBeTrue(!getFunction() || getModule()->features.hasReferenceTypes(),
curr,
"ref.null requires reference-types to be enabled");
+ if (!shouldBeTrue(
+ curr->type.isNullable(), curr, "ref.null types must be nullable")) {
+ return;
+ }
shouldBeTrue(
- curr->type.isNullable(), curr, "ref.null types must be nullable");
-
- // The type of the null must also be valid for the features.
- shouldBeTrue(curr->type.getFeatures() <= getModule()->features,
- curr->type,
- "ref.null type should be allowed");
+ curr->type.isNull(), curr, "ref.null must have a bottom heap type");
}
void FunctionValidator::visitRefIs(RefIs* curr) {
@@ -2454,12 +2453,15 @@ void FunctionValidator::visitCallRef(CallRef* curr) {
validateReturnCall(curr);
shouldBeTrue(
getModule()->features.hasGC(), curr, "call_ref requires gc to be enabled");
- if (curr->target->type != Type::unreachable) {
- if (shouldBeTrue(curr->target->type.isFunction(),
- curr,
- "call_ref target must be a function reference")) {
- validateCallParamsAndResult(curr, curr->target->type.getHeapType());
- }
+ if (curr->target->type == Type::unreachable ||
+ (curr->target->type.isRef() &&
+ curr->target->type.getHeapType() == HeapType::nofunc)) {
+ return;
+ }
+ if (shouldBeTrue(curr->target->type.isFunction(),
+ curr,
+ "call_ref target must be a function reference")) {
+ validateCallParamsAndResult(curr, curr->target->type.getHeapType());
}
}
@@ -2580,7 +2582,7 @@ void FunctionValidator::visitStructGet(StructGet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.get requires gc to be enabled");
- if (curr->ref->type == Type::unreachable) {
+ if (curr->type == Type::unreachable || curr->ref->type.isNull()) {
return;
}
if (!shouldBeTrue(curr->ref->type.isStruct(),
@@ -2610,22 +2612,28 @@ void FunctionValidator::visitStructSet(StructSet* curr) {
if (curr->ref->type == Type::unreachable) {
return;
}
- if (!shouldBeTrue(curr->ref->type.isStruct(),
+ if (!shouldBeTrue(curr->ref->type.isRef(),
curr->ref,
- "struct.set ref must be a struct")) {
+ "struct.set ref must be a reference type")) {
return;
}
- if (curr->ref->type != Type::unreachable) {
- const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
- shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
- auto& field = fields[curr->index];
- shouldBeSubType(curr->value->type,
- field.type,
- curr,
- "struct.set must have the proper type");
- shouldBeEqual(
- field.mutable_, Mutable, curr, "struct.set field must be mutable");
+ auto type = curr->ref->type.getHeapType();
+ if (type == HeapType::none) {
+ return;
}
+ if (!shouldBeTrue(
+ type.isStruct(), curr->ref, "struct.set ref must be a struct")) {
+ return;
+ }
+ const auto& fields = type.getStruct().fields;
+ shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
+ auto& field = fields[curr->index];
+ shouldBeSubType(curr->value->type,
+ field.type,
+ curr,
+ "struct.set must have the proper type");
+ shouldBeEqual(
+ field.mutable_, Mutable, curr, "struct.set field must be mutable");
}
void FunctionValidator::visitArrayNew(ArrayNew* curr) {
@@ -2688,7 +2696,18 @@ void FunctionValidator::visitArrayGet(ArrayGet* curr) {
if (curr->type == Type::unreachable) {
return;
}
- const auto& element = curr->ref->type.getHeapType().getArray().element;
+ // TODO: array rather than data once we've implemented that.
+ if (!shouldBeSubType(curr->ref->type,
+ Type(HeapType::data, Nullable),
+ curr,
+ "array.get target should be an array reference")) {
+ return;
+ }
+ auto heapType = curr->ref->type.getHeapType();
+ if (heapType == HeapType::none) {
+ return;
+ }
+ const auto& element = heapType.getArray().element;
// If the type is not packed, it must be marked internally as unsigned, by
// convention.
if (element.type != Type::i32 || element.packedType == Field::not_packed) {
@@ -2706,6 +2725,17 @@ void FunctionValidator::visitArraySet(ArraySet* curr) {
if (curr->type == Type::unreachable) {
return;
}
+ // TODO: array rather than data once we've implemented that.
+ if (!shouldBeSubType(curr->ref->type,
+ Type(HeapType::data, Nullable),
+ curr,
+ "array.set target should be an array reference")) {
+ return;
+ }
+ auto heapType = curr->ref->type.getHeapType();
+ if (heapType == HeapType::none) {
+ return;
+ }
const auto& element = curr->ref->type.getHeapType().getArray().element;
shouldBeSubType(curr->value->type,
element.type,
@@ -2736,9 +2766,23 @@ void FunctionValidator::visitArrayCopy(ArrayCopy* curr) {
if (curr->type == Type::unreachable) {
return;
}
- const auto& srcElement = curr->srcRef->type.getHeapType().getArray().element;
- const auto& destElement =
- curr->destRef->type.getHeapType().getArray().element;
+ if (!shouldBeSubType(curr->srcRef->type,
+ Type(HeapType::data, Nullable),
+ curr,
+ "array.copy source should be an array reference") ||
+ !shouldBeSubType(curr->destRef->type,
+ Type(HeapType::data, Nullable),
+ curr,
+ "array.copy destination should be an array reference")) {
+ return;
+ }
+ auto srcHeapType = curr->srcRef->type.getHeapType();
+ auto destHeapType = curr->destRef->type.getHeapType();
+ if (srcHeapType == HeapType::none || destHeapType == HeapType::none) {
+ return;
+ }
+ const auto& srcElement = srcHeapType.getArray().element;
+ const auto& destElement = destHeapType.getArray().element;
shouldBeSubType(srcElement.type,
destElement.type,
curr,