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.cpp140
1 files changed, 76 insertions, 64 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index b7354ff3f..92f6c76bf 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -499,7 +499,10 @@ private:
validateCallParamsAndResult(curr, sigType, curr);
}
- Type indexType() { return getModule()->memory.indexType; }
+ Type indexType(Name memoryName) {
+ auto memory = getModule()->getMemory(memoryName);
+ return memory->indexType;
+ }
};
void FunctionValidator::noteLabelName(Name name) {
@@ -934,8 +937,8 @@ void FunctionValidator::visitGlobalSet(GlobalSet* curr) {
}
void FunctionValidator::visitLoad(Load* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.load memory must exist");
if (curr->isAtomic) {
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
@@ -954,7 +957,7 @@ void FunctionValidator::visitLoad(Load* curr) {
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"load pointer type must match memory index type");
if (curr->isAtomic) {
@@ -965,8 +968,8 @@ void FunctionValidator::visitLoad(Load* curr) {
}
void FunctionValidator::visitStore(Store* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.store memory must exist");
if (curr->isAtomic) {
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
@@ -986,7 +989,7 @@ void FunctionValidator::visitStore(Store* curr) {
curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"store pointer must match memory index type");
shouldBeUnequal(curr->value->type,
@@ -1002,15 +1005,15 @@ void FunctionValidator::visitStore(Store* curr) {
}
void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.atomicRMW memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
"Atomic operation (atomics are disabled)");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"AtomicRMW pointer type must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->type,
@@ -1022,15 +1025,15 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
}
void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.atomicCmpxchg memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
"Atomic operation (atomics are disabled)");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"cmpxchg pointer must match memory index type");
if (curr->expected->type != Type::unreachable &&
@@ -1055,8 +1058,8 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
}
void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.atomicWait memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
"Atomic operation (atomics are disabled)");
@@ -1064,7 +1067,7 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
curr->type, Type(Type::i32), curr, "AtomicWait must have type i32");
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"AtomicWait pointer must match memory index type");
shouldBeIntOrUnreachable(
@@ -1081,8 +1084,8 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
}
void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.atomicNotify memory must exist");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
"Atomic operation (atomics are disabled)");
@@ -1090,7 +1093,7 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32");
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"AtomicNotify pointer must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
@@ -1101,8 +1104,8 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
}
void FunctionValidator::visitAtomicFence(AtomicFence* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ shouldBeFalse(
+ getModule()->memories.empty(), curr, "Memory operations require a memory");
shouldBeTrue(getModule()->features.hasAtomics(),
curr,
"Atomic operation (atomics are disabled)");
@@ -1240,15 +1243,15 @@ void FunctionValidator::visitSIMDShift(SIMDShift* curr) {
}
void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.SIMDLoad memory must exist");
shouldBeTrue(
getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::v128), curr, "load_splat must have type v128");
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"load_splat address must match memory index type");
Type memAlignType = Type::none;
@@ -1275,8 +1278,8 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
}
void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.SIMDLoadStoreLane memory must exist");
shouldBeTrue(
getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
if (curr->isLoad()) {
@@ -1288,7 +1291,7 @@ void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
}
shouldBeEqualOrFirstIsUnreachable(
curr->ptr->type,
- indexType(),
+ indexType(curr->memory),
curr,
"loadX_lane or storeX_lane address must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
@@ -1335,7 +1338,7 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
curr->type, Type(Type::none), curr, "memory.init must have type none");
shouldBeEqualOrFirstIsUnreachable(
curr->dest->type,
- indexType(),
+ indexType(curr->memory),
curr,
"memory.init dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->offset->type,
@@ -1344,9 +1347,8 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
"memory.init offset must be an i32");
shouldBeEqualOrFirstIsUnreachable(
curr->size->type, Type(Type::i32), curr, "memory.init size must be an i32");
- if (!shouldBeTrue(getModule()->memory.exists,
- curr,
- "Memory operations require a memory")) {
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ if (!shouldBeTrue(!!memory, curr, "memory.init memory must exist")) {
return;
}
shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
@@ -1360,9 +1362,9 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) {
"Bulk memory operation (bulk memory is disabled)");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "data.drop must have type none");
- if (!shouldBeTrue(getModule()->memory.exists,
- curr,
- "Memory operations require a memory")) {
+ if (!shouldBeFalse(getModule()->memories.empty(),
+ curr,
+ "Memory operations require a memory")) {
return;
}
shouldBeTrue(curr->segment < getModule()->dataSegments.size(),
@@ -1376,23 +1378,30 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
"Bulk memory operation (bulk memory is disabled)");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.copy must have type none");
+ auto* destMemory = getModule()->getMemoryOrNull(curr->destMemory);
+ shouldBeTrue(!!destMemory, curr, "memory.copy destMemory must exist");
+ auto* sourceMemory = getModule()->getMemoryOrNull(curr->sourceMemory);
+ shouldBeTrue(!!sourceMemory, curr, "memory.copy sourceMemory must exist");
shouldBeEqualOrFirstIsUnreachable(
curr->dest->type,
- indexType(),
+ indexType(curr->destMemory),
curr,
- "memory.copy dest must match memory index type");
+ "memory.copy dest must match destMemory index type");
shouldBeEqualOrFirstIsUnreachable(
curr->source->type,
- indexType(),
+ indexType(curr->sourceMemory),
curr,
- "memory.copy source must match memory index type");
+ "memory.copy source must match sourceMemory index type");
shouldBeEqualOrFirstIsUnreachable(
curr->size->type,
- indexType(),
+ indexType(curr->destMemory),
curr,
- "memory.copy size must match memory index type");
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ "memory.copy size must match destMemory index type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->size->type,
+ indexType(curr->sourceMemory),
+ curr,
+ "memory.copy size must match destMemory index type");
}
void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
@@ -1403,7 +1412,7 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
curr->type, Type(Type::none), curr, "memory.fill must have type none");
shouldBeEqualOrFirstIsUnreachable(
curr->dest->type,
- indexType(),
+ indexType(curr->memory),
curr,
"memory.fill dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->value->type,
@@ -1412,11 +1421,11 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
"memory.fill value must be an i32");
shouldBeEqualOrFirstIsUnreachable(
curr->size->type,
- indexType(),
+ indexType(curr->memory),
curr,
"memory.fill size must match memory index type");
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.fill memory must exist");
}
void FunctionValidator::validateMemBytes(uint8_t bytes,
@@ -2020,15 +2029,15 @@ void FunctionValidator::visitReturn(Return* curr) {
}
void FunctionValidator::visitMemorySize(MemorySize* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.size memory must exist");
}
void FunctionValidator::visitMemoryGrow(MemoryGrow* curr) {
- shouldBeTrue(
- getModule()->memory.exists, curr, "Memory operations require a memory");
+ auto* memory = getModule()->getMemoryOrNull(curr->memory);
+ shouldBeTrue(!!memory, curr, "memory.grow memory must exist");
shouldBeEqualOrFirstIsUnreachable(curr->delta->type,
- indexType(),
+ indexType(curr->memory),
curr,
"memory.grow must match memory index type");
}
@@ -2940,7 +2949,7 @@ static void validateExports(Module& module, ValidationInfo& info) {
name,
"module table exports must be found");
} else if (exp->kind == ExternalKind::Memory) {
- info.shouldBeTrue(name == Name("0") || name == module.memory.name,
+ info.shouldBeTrue(module.getMemoryOrNull(name),
name,
"module memory exports must be found");
} else if (exp->kind == ExternalKind::Tag) {
@@ -2982,25 +2991,28 @@ static void validateGlobals(Module& module, ValidationInfo& info) {
}
static void validateMemory(Module& module, ValidationInfo& info) {
- auto& curr = module.memory;
+ if (module.memories.empty()) {
+ return;
+ }
+ auto& curr = module.memories[0];
info.shouldBeFalse(
- curr.initial > curr.max, "memory", "memory max >= initial");
- if (curr.is64()) {
+ curr->initial > curr->max, "memory", "memory max >= initial");
+ if (curr->is64()) {
info.shouldBeTrue(module.features.hasMemory64(),
"memory",
"memory is 64-bit, but memory64 is disabled");
} else {
- info.shouldBeTrue(curr.initial <= Memory::kMaxSize32,
+ info.shouldBeTrue(curr->initial <= Memory::kMaxSize32,
"memory",
"initial memory must be <= 4GB");
- info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize32,
+ info.shouldBeTrue(!curr->hasMax() || curr->max <= Memory::kMaxSize32,
"memory",
"max memory must be <= 4GB, or unlimited");
}
- info.shouldBeTrue(!curr.shared || curr.hasMax(),
+ info.shouldBeTrue(!curr->shared || curr->hasMax(),
"memory",
"shared memory must have max size");
- if (curr.shared) {
+ if (curr->shared) {
info.shouldBeTrue(module.features.hasAtomics(),
"memory",
"memory is shared, but atomics are disabled");
@@ -3016,7 +3028,7 @@ static void validateMemory(Module& module, ValidationInfo& info) {
segment->offset,
"passive segment should not have an offset");
} else {
- if (curr.is64()) {
+ if (curr->is64()) {
if (!info.shouldBeEqual(segment->offset->type,
Type(Type::i64),
segment->offset,
@@ -3033,14 +3045,14 @@ static void validateMemory(Module& module, ValidationInfo& info) {
}
info.shouldBeTrue(checkSegmentOffset(segment->offset,
segment->data.size(),
- curr.initial * Memory::kPageSize,
+ curr->initial * Memory::kPageSize,
module.features),
segment->offset,
"memory segment offset should be reasonable");
if (segment->offset->is<Const>()) {
auto start = segment->offset->cast<Const>()->value.getUnsigned();
auto end = start + size;
- info.shouldBeTrue(end <= curr.initial * Memory::kPageSize,
+ info.shouldBeTrue(end <= curr->initial * Memory::kPageSize,
segment->data.size(),
"segment size should fit in memory (end)");
}
@@ -3049,8 +3061,8 @@ static void validateMemory(Module& module, ValidationInfo& info) {
// If the memory is imported we don't actually know its initial size.
// Specifically wasm dll's import a zero sized memory which is perfectly
// valid.
- if (!curr.imported()) {
- info.shouldBeTrue(size <= curr.initial * Memory::kPageSize,
+ if (!curr->imported()) {
+ info.shouldBeTrue(size <= curr->initial * Memory::kPageSize,
segment->data.size(),
"segment size should fit in memory (initial)");
}