[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:
parent
54157310c1
commit
a14f4215a0
@ -3623,8 +3623,14 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
|||||||
|
|
||||||
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(PopControl, c);
|
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(PopControl, c);
|
||||||
|
|
||||||
// A loop just leaves the values on the stack.
|
// - In non-unreachable code, a loop just leaves the values on the stack.
|
||||||
if (!c->is_loop()) PushMergeValues(c, &c->end_merge);
|
// - 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 =
|
bool parent_reached =
|
||||||
c->reachable() || c->end_merge.reached || c->is_onearmed_if();
|
c->reachable() || c->end_merge.reached || c->is_onearmed_if();
|
||||||
|
@ -57,6 +57,8 @@ let if_unr = [kExprIf, kWasmVoid, kExprUnreachable, kExprEnd];
|
|||||||
let if_else_unr = [kExprIf, kWasmVoid, kExprUnreachable, kExprElse, kExprUnreachable, kExprEnd];
|
let if_else_unr = [kExprIf, kWasmVoid, kExprUnreachable, kExprElse, kExprUnreachable, kExprEnd];
|
||||||
let block_unr = [kExprBlock, kWasmVoid, kExprUnreachable, kExprEnd];
|
let block_unr = [kExprBlock, kWasmVoid, kExprUnreachable, kExprEnd];
|
||||||
let loop_unr = [kExprLoop, 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_block_unr = [kExprBlock, kWasmVoid, kExprBlock, kWasmVoid, kExprUnreachable, kExprEnd, kExprEnd];
|
||||||
let block = [kExprBlock, kWasmVoid]
|
let block = [kExprBlock, kWasmVoid]
|
||||||
let iblock = [kExprBlock, kWasmI32]
|
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 U) iadd drop', [...block_unr, iadd, drop]);
|
||||||
run(I, '(block (block U)) iadd drop', [...block_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(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, '(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(I, 'U (i_iblock leqz)', [unr, ...i_iblock, leqz, end, drop]);
|
||||||
run(V, 'U (i_iblock ieqz)', [unr, ...i_iblock, ieqz, end, drop]);
|
run(V, 'U (i_iblock ieqz)', [unr, ...i_iblock, ieqz, end, drop]);
|
||||||
|
Loading…
Reference in New Issue
Block a user