diff --git a/src/tools/wasm-reduce/wasm-reduce.cpp b/src/tools/wasm-reduce/wasm-reduce.cpp index bba5cda3cb1..04676109acf 100644 --- a/src/tools/wasm-reduce/wasm-reduce.cpp +++ b/src/tools/wasm-reduce/wasm-reduce.cpp @@ -1102,6 +1102,7 @@ struct Reducer auto* block = ChildLocalizer(curr, getFunction(), *getModule(), getPassOptions()) .getChildrenReplacement(); + auto originalType = curr->type; auto* replacement = builder.replaceWithIdenticalType(curr); // We may have failed to come up with a replacement (e.g. for // non-nullable references), so manually add an `unreachable` in that @@ -1110,7 +1111,7 @@ struct Reducer replacement = builder.makeUnreachable(); } block->list.push_back(replacement); - block->type = curr->type; + block->type = originalType; replaceCurrent(block); } void visitRefFunc(RefFunc* curr) { diff --git a/test/lit/wasm-reduce/reduce-validation-error.wast b/test/lit/wasm-reduce/reduce-validation-error.wast new file mode 100644 index 00000000000..74ef8f13864 --- /dev/null +++ b/test/lit/wasm-reduce/reduce-validation-error.wast @@ -0,0 +1,19 @@ +;; This is a regression test for a crash in wasm-reduce where in-place mutation +;; of a Call node during replaceWithIdenticalType caused the replacement block +;; type to be set incorrectly to nullref instead of the original type, leading +;; to a validation error. + +;; RUN: wasm-reduce %s -t %t.t.wast -w %t.w.wast \ +;; RUN: --command='wasm-opt %t.t.wast -all --fuzz-exec' + +(module + (func $to_remove (result anyref) + (ref.null none) + ) + + (func $main (export "main") (result anyref) + ;; This will be replaced with a nullref. This should not cause validation + ;; failures and cause wasm-reduce to crash. + (call $to_remove) + ) +)