summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-11-16 12:09:06 -0800
committerGitHub <noreply@github.com>2022-11-16 12:09:06 -0800
commit3528a593f5a588d1819c6de9645b63361c13bf6b (patch)
tree4e242ba97db33272b5917c2bcc9a10686ebe0625
parent41a2f9f394c9bb526c7a3184e571360e3813fb50 (diff)
downloadbinaryen-3528a593f5a588d1819c6de9645b63361c13bf6b.tar.gz
binaryen-3528a593f5a588d1819c6de9645b63361c13bf6b.tar.bz2
binaryen-3528a593f5a588d1819c6de9645b63361c13bf6b.zip
[Wasm GC] Fix a GUFA bug on null call_ref targets (#5262)
If the target is a bottom type then it is a heap type but it is not a signature type, and we should treat it as unreachable (and not crash).
-rw-r--r--src/ir/possible-contents.cpp6
-rw-r--r--test/lit/passes/gufa-refs.wast24
2 files changed, 28 insertions, 2 deletions
diff --git a/src/ir/possible-contents.cpp b/src/ir/possible-contents.cpp
index 5170d8fa3..0284101ed 100644
--- a/src/ir/possible-contents.cpp
+++ b/src/ir/possible-contents.cpp
@@ -763,6 +763,12 @@ struct InfoCollector
});
}
template<typename T> void handleIndirectCall(T* curr, HeapType targetType) {
+ // If the heap type is not a signature, which is the case for a bottom type
+ // (null) then nothing can be called.
+ if (!targetType.isSignature()) {
+ assert(targetType.isBottom());
+ return;
+ }
handleCall(
curr,
[&](Index i) {
diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast
index a27e07f5f..310bef59b 100644
--- a/test/lit/passes/gufa-refs.wast
+++ b/test/lit/passes/gufa-refs.wast
@@ -4504,10 +4504,10 @@
;; CHECK: (type $i2 (func_subtype (param i32) func))
(type $i2 (func (param i32)))
- ;; CHECK: (type $none_=>_i32 (func_subtype (result i32) func))
-
;; CHECK: (type $none_=>_none (func_subtype func))
+ ;; CHECK: (type $none_=>_i32 (func_subtype (result i32) func))
+
;; CHECK: (import "a" "b" (func $import (result i32)))
(import "a" "b" (func $import (result i32)))
@@ -4609,6 +4609,26 @@
(ref.func $reffed2)
)
)
+
+ ;; CHECK: (func $call_ref-nofunc (type $none_=>_none)
+ ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (ref.null nofunc)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $call_ref-nofunc
+ ;; Test a call_ref of something of type nofunc. That has a heap type, but it
+ ;; is not a signature type. We should not crash on that.
+ (call_ref $i1
+ (i32.const 1)
+ (ref.null nofunc)
+ )
+ )
)
;; Limited cone reads.