[wasm] Fix a bug in unreachable code

Loop fallthroughs should leave values according to their out-type on the
stack, even when the stack is polymorphic.

Bug: chromium:1217470
Change-Id: I0a7e0569fa24fc16fcac76569a5ba14b6c7b0a9f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2949090
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75043}
This commit is contained in:
Manos Koukoutos 2021-06-09 11:56:05 +00:00 committed by V8 LUCI CQ
parent 54157310c1
commit a14f4215a0
2 changed files with 11 additions and 2 deletions

View File

@ -3623,8 +3623,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(PopControl, c);
// A loop just leaves the values on the stack.
if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
// - In non-unreachable code, a loop just leaves the values on the stack.
// - In unreachable code, it is not guaranteed that we have Values of the
// correct types on the stack, so we have to make sure we do. Their values
// do not matter, so we might as well push the (uninitialized) values of
// the loop's end merge.
if (!c->is_loop() || c->unreachable()) {
PushMergeValues(c, &c->end_merge);
}
bool parent_reached =
c->reachable() || c->end_merge.reached || c->is_onearmed_if();

View File

@ -57,6 +57,8 @@ let if_unr = [kExprIf, kWasmVoid, kExprUnreachable, kExprEnd];
let if_else_unr = [kExprIf, kWasmVoid, kExprUnreachable, kExprElse, kExprUnreachable, kExprEnd];
let block_unr = [kExprBlock, kWasmVoid, kExprUnreachable, kExprEnd];
let loop_unr = [kExprLoop, kWasmVoid, kExprUnreachable, kExprEnd];
// An i32-typed loop returning a polymorphic stack.
let iloop_poly = [kExprLoop, kWasmI32, kExprUnreachable, kExprI32Const, 0, kExprSelect, kExprEnd];
let block_block_unr = [kExprBlock, kWasmVoid, kExprBlock, kWasmVoid, kExprUnreachable, kExprEnd, kExprEnd];
let block = [kExprBlock, kWasmVoid]
let iblock = [kExprBlock, kWasmI32]
@ -100,6 +102,7 @@ run(I, '0 0 ret iadd', [...zero, ...zero, ret, iadd]);
run(I, '(block U) iadd drop', [...block_unr, iadd, drop]);
run(I, '(block (block U)) iadd drop', [...block_block_unr, iadd, drop]);
run(I, '(loop U) iadd drop', [...loop_unr, iadd]);
run(V, '(iloop (iloop U 0 select)) drop', [kExprLoop, kWasmI32, ...iloop_poly, kExprEnd, drop]);
run(I, '(if 0 U U) iadd drop', [...zero, ...if_else_unr, iadd, drop]);
run(I, 'U (i_iblock leqz)', [unr, ...i_iblock, leqz, end, drop]);
run(V, 'U (i_iblock ieqz)', [unr, ...i_iblock, ieqz, end, drop]);