diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index c7a95ccabc..8e6b008f08 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -395,7 +395,7 @@ pub fn translate_operator( let i = state.control_stack.len() - 1 - (min_depth as usize); let min_depth_frame = &state.control_stack[i]; if min_depth_frame.is_loop() { - 0 + min_depth_frame.num_param_values() } else { min_depth_frame.num_return_values() } diff --git a/tests/misc_testsuite/br-table-fuzzbug.wast b/tests/misc_testsuite/br-table-fuzzbug.wast new file mode 100644 index 0000000000..a4a3493e00 --- /dev/null +++ b/tests/misc_testsuite/br-table-fuzzbug.wast @@ -0,0 +1,640 @@ +;; From https://bugzilla.mozilla.org/show_bug.cgi?id=1657062. +;; +;; This just tests that Cranelift can compile this function; it previously +;; triggered a validator error on the CLIF that is generated by the wasm crate. + +(module + (type (;0;) (func (param i32 i32 i32) (result i32))) + (func $main (type 0) (param i32 i32 i32) (result i32) + local.get 1 + i32.const 6150 + local.get 2 + i32.const -63 + br_if 0 (;@0;) + loop (param i32 i32 i32) (result i32) ;; label = @1 + i32.const -59 + local.get 1 + i32.const -49 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + i32.const 0 + i32.const 0 + br_if 0 (;@1;) + i32.const 0 + i32.const 27 + select + i32.const 24 + select + local.get 0 + i32.const 27 + i32.const 32 + br_if 0 (;@1;) + i32.const 32 + br_if 0 (;@1;) + i32.const 452672 + i32.const 32 + br_if 1 (;@0;) + i32.const -23 + i32.div_s + local.get 1 + if ;; label = @2 + nop + i32.const -52 + if ;; label = @3 + nop + i32.const -52 + local.tee 1 + br_table 1 (;@2;) 0 (;@3;) + end + local.get 2 + br_table 0 (;@2;) 0 (;@2;) + end + local.get 1 + nop + i32.const -23 + i32.div_s + nop + i32.const -25 + i32.popcnt + select + select + i32.const 139 + select + drop + i32.const -8051 + nop + drop + i32.const 27 + i32.const -63 + local.get 1 + i32.const 1 + i32.const -63 + i32.const 2 + i32.const -6145 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + select + local.get 1 + i32.const -7937 + i32.const 2 + i32.const 0 + i32.ge_u + i32.eqz + i32.const -49 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 32 + call $main + i32.const -1 + i32.rem_s + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const -49 + i32.const 0 + i32.const 0 + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + call $main + i32.const -1 + i32.rem_s + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 3 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + br_if 0 (;@1;) + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + nop + i32.const -59 + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.const 32 + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + br_if 0 (;@1;) + i32.const 4 + i32.rem_s + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.const -19 + nop + nop + i32.const -23 + i32.div_s + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -63 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.div_s + local.get 1 + i32.const 1 + i32.const -63 + i32.const 2 + i32.const 1 + drop + i32.const -63 + i32.const 27 + select + i32.const 27 + select + local.tee 0 + i32.const 27 + i32.const 32 + br_if 0 (;@1;) + i32.const 32 + br_if 0 (;@1;) + i32.const 452672 + i32.const 32 + br_if 1 (;@0;) + i32.const -23 + i32.div_s + local.get 1 + if ;; label = @2 + nop + i32.const -52 + if ;; label = @3 + nop + i32.const -52 + local.tee 1 + br_table 1 (;@2;) 0 (;@3;) + end + local.get 2 + br_table 0 (;@2;) 0 (;@2;) + end + local.get 1 + nop + i32.const -23 + i32.div_s + nop + i32.const -25 + i32.popcnt + select + select + i32.const 139 + select + drop + i32.const -64 + i32.ge_u + br_if 0 (;@1;) + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + nop + i32.const -59 + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.const 32 + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + br_if 0 (;@1;) + i32.const 4 + i32.rem_s + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.const -19 + nop + nop + i32.const -23 + i32.div_s + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -63 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.div_s + local.get 1 + i32.const 1 + i32.const -63 + i32.const 2 + i32.const 1 + drop + nop + i32.const -49 + br_if 0 (;@1;) + local.set 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + i32.const 0 + i32.const 0 + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + call $main + i32.const -1 + i32.rem_s + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + br_if 0 (;@1;) + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + nop + i32.const -59 + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.const 32 + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + br_if 0 (;@1;) + i32.const 4 + i32.rem_s + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -63 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.div_s + local.get 1 + i32.const 1 + i32.const -63 + i32.const 2 + i32.const 1 + drop + i32.const -63 + i32.const 27 + select + i32.const 27 + select + local.tee 0 + i32.const 27 + i32.const 32 + br_if 0 (;@1;) + i32.const 32 + br_if 0 (;@1;) + i32.const 452672 + i32.const 32 + br_if 1 (;@0;) + i32.const -23 + i32.div_s + local.get 1 + if ;; label = @2 + nop + i32.const -52 + if ;; label = @3 + nop + i32.const -52 + local.tee 1 + br_table 1 (;@2;) 0 (;@3;) + end + local.get 2 + br_table 0 (;@2;) 0 (;@2;) + end + local.get 1 + nop + i32.const -23 + i32.div_s + nop + i32.const -25 + i32.popcnt + select + select + i32.const 139 + select + drop + i32.const -64 + i32.ge_u + br_if 0 (;@1;) + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + nop + i32.const -59 + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.const 32 + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + br_if 0 (;@1;) + i32.const 4 + i32.rem_s + i32.const 2 + i32.const 0 + br_table 0 (;@1;) + unreachable + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.const -19 + nop + nop + i32.const -23 + i32.div_s + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -63 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.div_s + local.get 1 + i32.const 1 + i32.const -63 + i32.const 2 + i32.const 1 + drop + nop + i32.const -49 + br_if 0 (;@1;) + local.set 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + i32.const 0 + i32.const 0 + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 32 + call $main + i32.const -1 + i32.rem_s + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + br_if 0 (;@1;) + select + br_if 0 (;@1;) + i32.const 0 + local.get 1 + select + i32.const 2 + i32.const 0 + i32.ge_u + br_if 0 (;@1;) + i32.const -64 + i32.ge_u + i32.const 2 + i32.const 0 + i32.const 2 + i32.const 0 + i32.ge_u + i32.ge_u + br_if 0 (;@1;) + i32.const 0 + i32.ge_u + nop + i32.const -59 + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.eqz + i32.const 32 + select + br_if 0 (;@1;) + i32.const 0 + i32.const 2 + i32.const 0 + i32.const 2 + i32.const -63 + i32.const 27 + i32.const -63 + i32.eqz + i32.eqz + br 0 (;@1;) + end + unreachable + i32.div_s + unreachable + i32.rem_s + i32.div_s + return + br_if 0 (;@0;) + i32.const 0 + i32.extend8_s + unreachable + unreachable + unreachable + unreachable + i32.ctz + unreachable + i32.ge_u + unreachable + unreachable + i32.popcnt + unreachable + unreachable + i32.popcnt) + (export "main" (func $main)))