diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 6b9586b74c6..d34ad08dba3 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -2254,6 +2254,10 @@ class ExpressionRunner : public OverriddenVisitor { VISIT(expected, curr->expected) VISIT(timeout, curr->timeout) + if (!curr->ref->type.getHeapType().isShared()) { + trap("cannot struct.wait a non-shared object"); + } + auto data = ref.getSingleValue().getGCData(); if (!data) { trap("null ref"); diff --git a/test/spec/waitqueue.wast b/test/spec/waitqueue.wast index 2dd030204b5..608ce34944b 100644 --- a/test/spec/waitqueue.wast +++ b/test/spec/waitqueue.wast @@ -76,7 +76,7 @@ ) (module - (type $t (struct (field (mut waitqueue)))) + (type $t (shared (struct (field (mut waitqueue))))) (global $g (mut (ref null $t)) (struct.new $t (i32.const 0))) @@ -117,3 +117,16 @@ (assert_trap (invoke "struct.wait" (i32.const 0) (i64.const 0)) "null ref") (assert_trap (invoke "struct.notify" (i32.const 0)) "null ref") + +;; Waiting on a non-shared struct should trap. +(module + (type $t (struct (field (mut waitqueue)))) + + (global $g (mut (ref null $t)) (struct.new $t (i32.const 0))) + + (func (export "struct.wait") (param $expected i32) (param $timeout i64) (result i32) + (struct.wait $t 0 (global.get $g) (local.get $expected) (local.get $timeout)) + ) +) +(assert_trap (invoke "struct.wait" (i32.const 0) (i64.const 100)) "not shared") +