Skip to content

Commit fa05ca9

Browse files
authored
Merge pull request rust-lang#233 from RalfJung/transmute
Fix transmute on ByValPair
2 parents 8ff5d59 + bdcdb60 commit fa05ca9

File tree

3 files changed

+27
-9
lines changed

3 files changed

+27
-9
lines changed

src/eval_context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11111111
dest: Lvalue<'tcx>,
11121112
dest_ty: Ty<'tcx>,
11131113
) -> EvalResult<'tcx> {
1114+
// Note that it is really important that the type here is the right one, and matches the type things are read at.
1115+
// In case `src_val` is a `ByValPair`, we don't do any magic here to handle padding properly, which is only
1116+
// correct if we never look at this data with the wrong type.
1117+
11141118
match dest {
11151119
Lvalue::Global(cid) => {
11161120
let dest = *self.globals.get_mut(&cid).expect("global should be cached");

src/terminator/intrinsic.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -395,16 +395,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
395395
"transmute" => {
396396
let src_ty = substs.type_at(0);
397397
let dest_ty = substs.type_at(1);
398-
let src_align = self.type_align(src_ty)?;
399-
let dest_align = self.type_align(dest_ty)?;
400398
let size = self.type_size(dest_ty)?.expect("transmute() type must be sized");
401-
if dest_align < src_align {
402-
let ptr = self.force_allocation(dest)?.to_ptr()?;
403-
self.memory.mark_packed(ptr, size);
404-
self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), dest_ty)?;
405-
} else {
406-
self.write_value(arg_vals[0], dest, dest_ty)?;
407-
}
399+
let ptr = self.force_allocation(dest)?.to_ptr()?;
400+
self.memory.mark_packed(ptr, size);
401+
self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), src_ty)?;
408402
}
409403

410404
"uninit" => {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(core_intrinsics)]
2+
3+
use std::mem;
4+
5+
fn main() {
6+
let x: Option<Box<[u8]>> = unsafe {
7+
let z = std::intrinsics::add_with_overflow(0usize, 0usize);
8+
std::mem::transmute::<(usize, bool), Option<Box<[u8]>>>(z)
9+
};
10+
let y = &x;
11+
// Now read this bytewise. There should be (ptr_size+1) def bytes followed by (ptr_size-1) undef bytes (the padding after the bool) in there.
12+
let z : *const u8 = y as *const _ as *const _;
13+
let first_undef = mem::size_of::<usize>() as isize + 1;
14+
for i in 0..first_undef {
15+
let byte = unsafe { *z.offset(i) };
16+
assert_eq!(byte, 0);
17+
}
18+
let v = unsafe { *z.offset(first_undef) };
19+
if v == 0 {} //~ ERROR attempted to read undefined bytes
20+
}

0 commit comments

Comments
 (0)