From 863ac809d9968ba0ba2fe9765cbe98acd4bae2de Mon Sep 17 00:00:00 2001 From: Wander Lairson Costa Date: Mon, 16 Sep 2019 18:59:23 -0300 Subject: [PATCH] [codegen] Check for downcasting in bitcast instruction Bitcasting to a smaller size is invalid. closes #854 --- cranelift/codegen/src/verifier/mod.rs | 29 +++++++++++++++++++ .../filetests/filetests/verifier/bitcast.clif | 23 +++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 cranelift/filetests/filetests/verifier/bitcast.clif diff --git a/cranelift/codegen/src/verifier/mod.rs b/cranelift/codegen/src/verifier/mod.rs index 5bc10d9d92..2244947f0f 100644 --- a/cranelift/codegen/src/verifier/mod.rs +++ b/cranelift/codegen/src/verifier/mod.rs @@ -696,6 +696,13 @@ impl<'a> Verifier<'a> { } } + Unary { + opcode: Opcode::Bitcast, + arg, + } => { + self.verify_bitcast(inst, arg, errors)?; + } + // Exhaustive list so we can't forget to add new formats Unary { .. } | UnaryImm { .. } @@ -981,6 +988,28 @@ impl<'a> Verifier<'a> { } } + fn verify_bitcast( + &self, + inst: Inst, + arg: Value, + errors: &mut VerifierErrors, + ) -> VerifierStepResult<()> { + let typ = self.func.dfg.ctrl_typevar(inst); + let value_type = self.func.dfg.value_type(arg); + + if typ.lane_bits() < value_type.lane_bits() { + fatal!( + errors, + inst, + "The bitcast argument {} doesn't fit in a type of {} bits", + arg, + typ.lane_bits() + ) + } else { + Ok(()) + } + } + fn domtree_integrity( &self, domtree: &DominatorTree, diff --git a/cranelift/filetests/filetests/verifier/bitcast.clif b/cranelift/filetests/filetests/verifier/bitcast.clif new file mode 100644 index 0000000000..eb5303cfc0 --- /dev/null +++ b/cranelift/filetests/filetests/verifier/bitcast.clif @@ -0,0 +1,23 @@ +test verifier + +; bitcast between two types of equal size if ok +function %valid_bitcast1(i32) -> f32 { ; Ok +ebb0(v0: i32): + v1 = bitcast.f32 v0 + return v1 +} + +; bitcast to a type larger than the operand is ok +function %valid_bitcast2(i32) -> i64 { ; Ok +ebb0(v0: i32): + v1 = bitcast.i64 v0 + return v1 +} + +; bitcast to a smaller type is not ok +function %bad_bitcast(i64) -> i32 { +ebb0(v0: i64): + v1 = bitcast.i32 v0 ; error: The bitcast argument v0 doesn't fit in a type of 32 bits + return v1 +} +