From 030166757c01db52805a55792224c15955e8af02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 3 Jul 2017 13:57:18 -0700 Subject: [PATCH] Fix transmute on ByValPair Fixes #227 --- src/eval_context.rs | 4 ++++ src/terminator/intrinsic.rs | 12 +++--------- tests/compile-fail/transmute-pair-undef.rs | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 tests/compile-fail/transmute-pair-undef.rs diff --git a/src/eval_context.rs b/src/eval_context.rs index 630f878f723..1248d74b3d9 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -1111,6 +1111,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { dest: Lvalue<'tcx>, dest_ty: Ty<'tcx>, ) -> EvalResult<'tcx> { + // Note that it is really important that the type here is the right one, and matches the type things are read at. + // In case `src_val` is a `ByValPair`, we don't do any magic here to handle padding properly, which is only + // correct if we never look at this data with the wrong type. + match dest { Lvalue::Global(cid) => { let dest = *self.globals.get_mut(&cid).expect("global should be cached"); diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 360842ac547..13e037f28b6 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -395,16 +395,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "transmute" => { let src_ty = substs.type_at(0); let dest_ty = substs.type_at(1); - let src_align = self.type_align(src_ty)?; - let dest_align = self.type_align(dest_ty)?; let size = self.type_size(dest_ty)?.expect("transmute() type must be sized"); - if dest_align < src_align { - let ptr = self.force_allocation(dest)?.to_ptr()?; - self.memory.mark_packed(ptr, size); - self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), dest_ty)?; - } else { - self.write_value(arg_vals[0], dest, dest_ty)?; - } + let ptr = self.force_allocation(dest)?.to_ptr()?; + self.memory.mark_packed(ptr, size); + self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), src_ty)?; } "uninit" => { diff --git a/tests/compile-fail/transmute-pair-undef.rs b/tests/compile-fail/transmute-pair-undef.rs new file mode 100644 index 00000000000..fad51215dd3 --- /dev/null +++ b/tests/compile-fail/transmute-pair-undef.rs @@ -0,0 +1,17 @@ +#![feature(core_intrinsics)] + +fn main() { + let x: Option> = unsafe { + let z = std::intrinsics::add_with_overflow(0usize, 0usize); + std::mem::transmute::<(usize, bool), Option>>(z) + }; + let y = &x; + // Now read this bytewise. There should be 9 def bytes followed by 7 undef bytes (the padding after the bool) in there. + let z : *const u8 = y as *const _ as *const _; + for i in 0..9 { + let byte = unsafe { *z.offset(i) }; + assert_eq!(byte, 0); + } + let v = unsafe { *z.offset(9) }; + if v == 0 {} //~ ERROR attempted to read undefined bytes +}