summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-01-12 22:50:54 +0000
committerGitHub <noreply@github.com>2021-01-12 14:50:54 -0800
commitdc7184afcbdcc72d0a6d66e2b36fc5857050dd87 (patch)
tree1ccadec38943894c28b720920057313001f31326
parent46f0229bfd3c145873eca4d7db5e14f657ad729b (diff)
downloadbinaryen-dc7184afcbdcc72d0a6d66e2b36fc5857050dd87.tar.gz
binaryen-dc7184afcbdcc72d0a6d66e2b36fc5857050dd87.tar.bz2
binaryen-dc7184afcbdcc72d0a6d66e2b36fc5857050dd87.zip
[GC] Fix casts of non-GC data (#3483)
The code previously assumed it could always call getGCData, but that assumes the input is an array or a struct. It could also be an anyref etc. that contains something other than GC data.
-rw-r--r--src/wasm-interpreter.h12
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.txt10
-rw-r--r--test/passes/Oz_fuzz-exec_all-features.wast11
3 files changed, 31 insertions, 2 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 392b0c2bc..243542836 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1433,11 +1433,19 @@ public:
return cast;
}
cast.originalRef = ref.getSingleValue();
- auto gcData = cast.originalRef.getGCData();
- if (!gcData) {
+ if (cast.originalRef.isNull()) {
cast.outcome = cast.Null;
return cast;
}
+ // The input may not be a struct or an array; for example it could be an
+ // anyref of null (already handled above) or anything else (handled here,
+ // but this is for future use as atm the binaryen interpreter cannot
+ // represent external references).
+ if (!cast.originalRef.isGCData()) {
+ cast.outcome = cast.Failure;
+ return cast;
+ }
+ auto gcData = cast.originalRef.getGCData();
auto refRtt = gcData->rtt;
auto intendedRtt = rtt.getSingleValue();
if (!refRtt.isSubRtt(intendedRtt)) {
diff --git a/test/passes/Oz_fuzz-exec_all-features.txt b/test/passes/Oz_fuzz-exec_all-features.txt
index 8fa184345..b43681cdf 100644
--- a/test/passes/Oz_fuzz-exec_all-features.txt
+++ b/test/passes/Oz_fuzz-exec_all-features.txt
@@ -21,6 +21,8 @@
[fuzz-exec] calling br_on_cast
[LoggingExternalInterface logging 3]
[trap unreachable]
+[fuzz-exec] calling cast-null-anyref-to-gc
+[LoggingExternalInterface logging 0]
(module
(type ${mut:i32} (struct (field (mut i32))))
(type $none_=>_none (func))
@@ -32,6 +34,7 @@
(export "arrays" (func $1))
(export "rtts" (func $2))
(export "br_on_cast" (func $3))
+ (export "cast-null-anyref-to-gc" (func $4))
(func $0 (; has Stack IR ;)
(local $0 (ref null ${mut:i32}))
(call $log
@@ -194,6 +197,11 @@
)
(unreachable)
)
+ (func $4 (; has Stack IR ;)
+ (call $log
+ (i32.const 0)
+ )
+ )
)
[fuzz-exec] calling structs
[LoggingExternalInterface logging 0]
@@ -218,3 +226,5 @@
[fuzz-exec] calling br_on_cast
[LoggingExternalInterface logging 3]
[trap unreachable]
+[fuzz-exec] calling cast-null-anyref-to-gc
+[LoggingExternalInterface logging 0]
diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast
index 78313267c..7d586cffc 100644
--- a/test/passes/Oz_fuzz-exec_all-features.wast
+++ b/test/passes/Oz_fuzz-exec_all-features.wast
@@ -179,4 +179,15 @@
)
)
)
+ (func "cast-null-anyref-to-gc"
+ ;; a null anyref is a literal which is not even of GC data, as it's not an
+ ;; array or a struct, so our casting code should not assume it is. it is ok
+ ;; to try to cast it, and the result should be 0.
+ (call $log
+ (ref.test $struct
+ (ref.null any)
+ (rtt.canon $struct)
+ )
+ )
+ )
)