summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-07-24 13:54:13 -0700
committerGitHub <noreply@github.com>2024-07-24 13:54:13 -0700
commit017b473f05b8dde4da8aadd154e6d2606071d2cb (patch)
treedd4bf67b0d12d371aaf2fcae62b197948f5fcba1
parent353e19e3343fb06eacdd8b438b305b536291bdd5 (diff)
downloadbinaryen-017b473f05b8dde4da8aadd154e6d2606071d2cb.tar.gz
binaryen-017b473f05b8dde4da8aadd154e6d2606071d2cb.tar.bz2
binaryen-017b473f05b8dde4da8aadd154e6d2606071d2cb.zip
Validate RefAsNonNull (#6785)
Fixes #6781
-rw-r--r--src/wasm/wasm-validator.cpp13
-rw-r--r--src/wasm/wasm.cpp8
-rw-r--r--test/lit/validation/non-ref.wast13
3 files changed, 31 insertions, 3 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 3abb106b3..ce7d0df3c 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2230,10 +2230,19 @@ void FunctionValidator::visitRefIsNull(RefIsNull* curr) {
}
void FunctionValidator::visitRefAs(RefAs* curr) {
+ if (curr->value->type != Type::unreachable &&
+ !shouldBeTrue(
+ curr->value->type.isRef(), curr, "ref.as value must be reference")) {
+ return;
+ }
switch (curr->op) {
- default:
- // TODO: validate all the other ref.as_*
+ case RefAsNonNull: {
+ shouldBeTrue(
+ getModule()->features.hasReferenceTypes(),
+ curr,
+ "ref.as requires reference-types [--enable-reference-types]");
break;
+ }
case AnyConvertExtern: {
shouldBeTrue(getModule()->features.hasGC(),
curr,
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 4c30a4e32..b17250e6c 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1223,7 +1223,13 @@ void ArrayInitElem::finalize() {
}
void RefAs::finalize() {
- if (value->type == Type::unreachable) {
+ // An unreachable child means we are unreachable. Also set ourselves to
+ // unreachable when the child is invalid (say, it is an i32 or some other non-
+ // reference), which avoids getHeapType() erroring right after us (in this
+ // situation, the validator will report an error later).
+ // TODO: Remove that part when we solve the validation issue more generally,
+ // see https://github.com/WebAssembly/binaryen/issues/6781
+ if (!value->type.isRef()) {
type = Type::unreachable;
return;
}
diff --git a/test/lit/validation/non-ref.wast b/test/lit/validation/non-ref.wast
new file mode 100644
index 000000000..a065b6723
--- /dev/null
+++ b/test/lit/validation/non-ref.wast
@@ -0,0 +1,13 @@
+;; RUN: not wasm-opt %s -all 2>&1 | filecheck %s
+
+;; CHECK: ref.as value must be reference
+
+(module
+ (func $test
+ (drop
+ (ref.as_non_null
+ (i32.const 42)
+ )
+ )
+ )
+)