Skip to content

Commit 5f5ca88

Browse files
committed
Add size assert in transmute_copy
1 parent 8c52a83 commit 5f5ca88

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

library/core/src/mem/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ pub fn copy<T: Copy>(x: &T) -> T {
10401040
#[stable(feature = "rust1", since = "1.0.0")]
10411041
#[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
10421042
pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
1043+
assert!(size_of::<T>() >= size_of::<U>(), "cannot transmute_copy if U is larger than T");
1044+
10431045
// If U has a higher alignment requirement, src might not be suitably aligned.
10441046
if align_of::<U>() > align_of::<T>() {
10451047
// SAFETY: `src` is a reference which is guaranteed to be valid for reads.

library/core/tests/mem.rs

+40
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,46 @@ fn test_transmute_copy() {
9797
assert_eq!(1, unsafe { transmute_copy(&1) });
9898
}
9999

100+
#[test]
101+
fn test_transmute_copy_shrink() {
102+
assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
103+
}
104+
105+
#[test]
106+
fn test_transmute_copy_unaligned() {
107+
#[repr(C)]
108+
#[derive(Default)]
109+
struct Unaligned {
110+
a: u8,
111+
b: [u8; 8],
112+
}
113+
114+
let u = Unaligned::default();
115+
assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
116+
}
117+
118+
#[test]
119+
#[cfg(panic = "unwind")]
120+
fn test_transmute_copy_grow_panics() {
121+
use std::panic;
122+
123+
let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
124+
let _unused: u64 = transmute_copy(&1_u8);
125+
}));
126+
127+
match err {
128+
Ok(_) => unreachable!(),
129+
Err(payload) => {
130+
payload
131+
.downcast::<&'static str>()
132+
.and_then(|s| {
133+
if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) }
134+
})
135+
.unwrap_or_else(|p| panic::resume_unwind(p));
136+
}
137+
}
138+
}
139+
100140
#[test]
101141
#[allow(dead_code)]
102142
fn test_discriminant_send_sync() {

0 commit comments

Comments
 (0)