summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-02-04 02:33:13 +0000
committerGitHub <noreply@github.com>2021-02-03 18:33:13 -0800
commit56acee228d93d8ca36e40e4eb659e91d4a058f6f (patch)
treee9e4df4c2d0750df3f36879bd7bf270d3b5b0241
parent9ed635c3b4195e2842b155369ad09c07f1099793 (diff)
downloadbinaryen-56acee228d93d8ca36e40e4eb659e91d4a058f6f.tar.gz
binaryen-56acee228d93d8ca36e40e4eb659e91d4a058f6f.tar.bz2
binaryen-56acee228d93d8ca36e40e4eb659e91d4a058f6f.zip
[GC] Do not crash on unreachable inputs to struct.get/set (#3542)
If the reference is unreachable then we cannot find the heap type to print in the text format. Instead of crashing or emitting something invalid, print a block instead - the block contains the children so they are emitted, and as the instruction was unreachable anyhow, this has no noticeable effect. It also parallels what we do in the binary format - skip unreachable code.
-rw-r--r--src/passes/Print.cpp15
-rw-r--r--src/wasm/wasm-validator.cpp16
-rw-r--r--test/heap-types.wast8
-rw-r--r--test/heap-types.wast.from-wast13
-rw-r--r--test/heap-types.wast.fromBinary3
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo3
6 files changed, 58 insertions, 0 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 67deac35c..b7b7e1320 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -1840,7 +1840,18 @@ struct PrintExpressionContents
o << "with_rtt ";
printHeapTypeName(o, curr->rtt->type.getHeapType());
}
+ void printUnreachableReplacement() {
+ // If we cannot print a valid unreachable instruction (say, a struct.get,
+ // where if the ref is unreachable, we don't know what heap type to print),
+ // then print the children in a block, which is good enough as this
+ // instruction is never reached anyhow.
+ printMedium(o, "block ");
+ }
void visitStructGet(StructGet* curr) {
+ if (curr->ref->type == Type::unreachable) {
+ printUnreachableReplacement();
+ return;
+ }
const auto& field =
curr->ref->type.getHeapType().getStruct().fields[curr->index];
if (field.type == Type::i32 && field.packedType != Field::not_packed) {
@@ -1857,6 +1868,10 @@ struct PrintExpressionContents
o << curr->index;
}
void visitStructSet(StructSet* curr) {
+ if (curr->ref->type == Type::unreachable) {
+ printUnreachableReplacement();
+ return;
+ }
printMedium(o, "struct.set ");
printHeapTypeName(o, curr->ref->type.getHeapType());
o << ' ';
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 6a1b72476..a9a69b244 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -2296,6 +2296,14 @@ void FunctionValidator::visitStructGet(StructGet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.get requires gc to be enabled");
+ if (curr->ref->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(curr->ref->type.isStruct(),
+ curr->ref,
+ "struct.get ref must be a struct")) {
+ return;
+ }
const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
auto field = fields[curr->index];
@@ -2315,6 +2323,14 @@ void FunctionValidator::visitStructSet(StructSet* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"struct.set requires gc to be enabled");
+ if (curr->ref->type == Type::unreachable) {
+ return;
+ }
+ if (!shouldBeTrue(curr->ref->type.isStruct(),
+ curr->ref,
+ "struct.set ref must be a struct")) {
+ return;
+ }
if (curr->ref->type != Type::unreachable) {
const auto& fields = curr->ref->type.getHeapType().getStruct().fields;
shouldBeTrue(curr->index < fields.size(), curr, "bad struct.get field");
diff --git a/test/heap-types.wast b/test/heap-types.wast
index 7558e1676..87d751691 100644
--- a/test/heap-types.wast
+++ b/test/heap-types.wast
@@ -226,4 +226,12 @@
)
)
)
+ (func $unreachables
+ (drop
+ (struct.get $struct.A 0 (unreachable))
+ )
+ (drop
+ (struct.set $struct.A 0 (unreachable) (unreachable))
+ )
+ )
)
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
index a93bd0d90..458842a7b 100644
--- a/test/heap-types.wast.from-wast
+++ b/test/heap-types.wast.from-wast
@@ -282,4 +282,17 @@
)
)
)
+ (func $unreachables
+ (drop
+ (block
+ (unreachable)
+ )
+ )
+ (drop
+ (block
+ (unreachable)
+ (unreachable)
+ )
+ )
+ )
)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
index d8ddb48ed..5e48da116 100644
--- a/test/heap-types.wast.fromBinary
+++ b/test/heap-types.wast.fromBinary
@@ -281,5 +281,8 @@
)
)
)
+ (func $unreachables
+ (unreachable)
+ )
)
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
index 63f7e132e..d49d5fa1e 100644
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ b/test/heap-types.wast.fromBinary.noDebugInfo
@@ -281,5 +281,8 @@
)
)
)
+ (func $8
+ (unreachable)
+ )
)