Fix out-of-bounds type stack read after rethrow in c-writer#2798
Fix out-of-bounds type stack read after rethrow in c-writer#2798aizu-m wants to merge 2 commits into
Conversation
| 0x36, 0x02, 0x00, // i32.store (unreachable) | ||
| 0x0b, // end try | ||
| 0x0b, // end func | ||
| }; |
There was a problem hiding this comment.
Why make this a unit test rather then a normal file-based test in test/wasm2c/?
Also does this mean non of the spec tests have this case? Perhaps we should upstream something?
There was a problem hiding this comment.
Moved it to a file-based test: test/wasm2c/unreachable-after-rethrow.txt, run-spec-wasm2c with --enable-exceptions. Verified it aborts on the unpatched tree at c-writer.cc:1246 and passes (1/1) with the fix in place. Dropped the gtest and the Features plumbing it needed.
On the spec suite: the existing exception-handling tests all translate through wasm2c cleanly, so none of them put an operand-consuming instruction in the unreachable tail after rethrow, which is what drives the StackVar underflow. legacy/rethrow.wast is the closest but its rethrow sits at the end of the block. Agreed it's worth having upstream. I can send a case over to the testsuite repo separately and keep this local regression test in the meantime.
wasm2c on a valid exceptions module, ASan/debug build:
Worked backwards from the StackVar read. The rethrow case in
Write(const ExprList&)ends inbreak, so the loop carries on and emits the instructions after it. The validator has already marked those unreachable (OnRethrowmakes the stack polymorphic), so a valid module can put operations there that pop operands which are not really on the stack. StackVar then underflowstype_stack_and reads off the end. Release builds drop the assert and take the out-of-bounds read;DropTypesdoes an out-of-bounds erase on the same tail.br, br_table, return, unreachable, throw, throw_ref and the return_call family all return here to stop walking the list. rethrow was the one that fell through, so it now does the same.
Repro:
(func try nop catch_all rethrow 0 i32.store end)assembled with--enable-exceptions, then run through wasm2c.