diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 7cc87a0649a..1e7463e9291 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp @@ -2250,6 +2250,16 @@ Result<> IRBuilder::makeStructWait(HeapType type, Index index) { if (!type.isStruct()) { return Err{"expected struct type annotation on struct.wait"}; } + // This is likely checked in the caller by the `fieldidx` parser. + if (index >= type.getStruct().fields.size()) { + return Err{"struct.wait field index out of bounds"}; + } + + if (type.getStruct().fields.at(index).packedType != + Field::PackedType::WaitQueue) { + return Err{"struct.wait field index must contain a `waitqueue`"}; + } + StructWait curr(wasm.allocator); curr.index = index; CHECK_ERR(ChildPopper{*this}.visitStructWait(&curr, type)); diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index f79c96aeadd..ae862a32ff8 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -3517,25 +3517,12 @@ void FunctionValidator::visitStructWait(StructWait* curr) { curr, "struct.wait timeout must be an i64"); - if (curr->ref->type == Type::unreachable || curr->ref->type.isNull()) { - return; - } - - // In practice this likely fails during parsing instead. - if (!shouldBeTrue(curr->index < - curr->ref->type.getHeapType().getStruct().fields.size(), - curr, - "struct.wait index immediate should be less than the field " - "count of the struct")) { - return; - } - - shouldBeTrue(curr->ref->type.getHeapType() - .getStruct() - .fields.at(curr->index) - .packedType == Field::WaitQueue, - curr, - "struct.wait struct field must be a waitqueue"); + // Checks to the ref argument's type are done in IRBuilder where we have the + // type annotation immediate available. We check that + // * The reference arg is a subtype of the type immediate + // * The index immediate is a valid field index of the type immediate (and + // thus valid for the reference's type too) + // * The index points to a packed waitqueue field } void FunctionValidator::visitArrayNew(ArrayNew* curr) { diff --git a/test/spec/waitqueue.wast b/test/spec/waitqueue.wast index 7383d4eb7c3..8e837088bd5 100644 --- a/test/spec/waitqueue.wast +++ b/test/spec/waitqueue.wast @@ -4,7 +4,7 @@ (func (param $expected i32) (param $timeout i64) (result i32) (struct.wait $t 0 (ref.null $t) (local.get $expected) (local.get $timeout)) ) - ) "struct.wait struct field must be a waitqueue" + ) "struct.wait struct field index must contain a `waitqueue`" ) (assert_invalid @@ -38,7 +38,7 @@ ;; unreachable is allowed (module - (type $t (struct (field i32))) + (type $t (struct (field waitqueue))) (func (param $expected i32) (param $timeout i64) (result i32) (struct.wait $t 0 (unreachable) (local.get $expected) (local.get $timeout)) )