Skip to content

Commit 5ee4865

Browse files
committed
Prevent an ICE on invalid transmutes
1 parent cab341f commit 5ee4865

File tree

4 files changed

+159
-2
lines changed

4 files changed

+159
-2
lines changed

src/librustc/mir/interpret/error.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,7 @@ pub enum UnsupportedOpInfo<'tcx> {
468468
HeapAllocNonPowerOfTwoAlignment(u64),
469469
ReadFromReturnPointer,
470470
PathNotFound(Vec<String>),
471+
TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
471472
}
472473

473474
impl fmt::Debug for UnsupportedOpInfo<'tcx> {
@@ -490,6 +491,9 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> {
490491
write!(f, "tried to call a function with argument of type {:?} \
491492
passing data of type {:?}",
492493
callee_ty, caller_ty),
494+
TransmuteSizeDiff(from_ty, to_ty) =>
495+
write!(f, "tried to transmute from {:?} to {:?}, but their sizes differed",
496+
from_ty, to_ty),
493497
FunctionRetMismatch(caller_ty, callee_ty) =>
494498
write!(f, "tried to call a function with return type {:?} \
495499
passing return place of type {:?}",

src/librustc_mir/interpret/place.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -939,8 +939,10 @@ where
939939
return self.copy_op(src, dest);
940940
}
941941
// We still require the sizes to match.
942-
assert!(src.layout.size == dest.layout.size,
943-
"Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
942+
if src.layout.size != dest.layout.size {
943+
error!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
944+
throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
945+
}
944946
// Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
945947
// to avoid that here.
946948
assert!(!src.layout.is_unsized() && !dest.layout.is_unsized(),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#![feature(const_transmute)]
2+
3+
fn main() {
4+
match &b""[..] {
5+
ZST => {}
6+
//~^ ERROR could not evaluate constant pattern
7+
}
8+
}
9+
10+
const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
11+
//~^ ERROR any use of this value will cause an error
12+
//~| ERROR cannot transmute between types of different sizes
13+
14+
// Once the `any use of this value will cause an error` disappears in this test, make sure to
15+
// remove the `TransmuteSizeDiff` error variant and make its emitter site an assertion again.
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
[ERROR rustc_mir::interpret::place] Size mismatch when transmuting!
2+
src: OpTy {
3+
op: Immediate(
4+
Scalar(
5+
0x0000000000000001,
6+
),
7+
),
8+
layout: TyLayout {
9+
ty: usize,
10+
details: LayoutDetails {
11+
variants: Single {
12+
index: 0,
13+
},
14+
fields: Union(
15+
0,
16+
),
17+
abi: Scalar(
18+
Scalar {
19+
value: Int(
20+
I64,
21+
false,
22+
),
23+
valid_range: 0..=18446744073709551615,
24+
},
25+
),
26+
largest_niche: None,
27+
align: AbiAndPrefAlign {
28+
abi: Align {
29+
pow2: 3,
30+
},
31+
pref: Align {
32+
pow2: 3,
33+
},
34+
},
35+
size: Size {
36+
raw: 8,
37+
},
38+
},
39+
},
40+
}
41+
dest: PlaceTy {
42+
place: Ptr(
43+
MemPlace {
44+
ptr: AllocId(0).0x0,
45+
align: Align {
46+
pow2: 3,
47+
},
48+
meta: None,
49+
},
50+
),
51+
layout: TyLayout {
52+
ty: &[u8],
53+
details: LayoutDetails {
54+
variants: Single {
55+
index: 0,
56+
},
57+
fields: Arbitrary {
58+
offsets: [
59+
Size {
60+
raw: 0,
61+
},
62+
Size {
63+
raw: 8,
64+
},
65+
],
66+
memory_index: [
67+
0,
68+
1,
69+
],
70+
},
71+
abi: ScalarPair(
72+
Scalar {
73+
value: Pointer,
74+
valid_range: 1..=18446744073709551615,
75+
},
76+
Scalar {
77+
value: Int(
78+
I64,
79+
false,
80+
),
81+
valid_range: 0..=18446744073709551615,
82+
},
83+
),
84+
largest_niche: Some(
85+
Niche {
86+
offset: Size {
87+
raw: 0,
88+
},
89+
scalar: Scalar {
90+
value: Pointer,
91+
valid_range: 1..=18446744073709551615,
92+
},
93+
},
94+
),
95+
align: AbiAndPrefAlign {
96+
abi: Align {
97+
pow2: 3,
98+
},
99+
pref: Align {
100+
pow2: 3,
101+
},
102+
},
103+
size: Size {
104+
raw: 16,
105+
},
106+
},
107+
},
108+
}
109+
error: any use of this value will cause an error
110+
--> $DIR/transmute-size-mismatch-before-typeck.rs:10:29
111+
|
112+
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
113+
| ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
114+
| |
115+
| tried to transmute from usize to &[u8], but their sizes differed
116+
|
117+
= note: `#[deny(const_err)]` on by default
118+
119+
error: could not evaluate constant pattern
120+
--> $DIR/transmute-size-mismatch-before-typeck.rs:5:9
121+
|
122+
LL | ZST => {}
123+
| ^^^
124+
125+
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
126+
--> $DIR/transmute-size-mismatch-before-typeck.rs:10:29
127+
|
128+
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
129+
| ^^^^^^^^^^^^^^^^^^^
130+
|
131+
= note: source type: `usize` (64 bits)
132+
= note: target type: `&'static [u8]` (128 bits)
133+
134+
error: aborting due to 3 previous errors
135+
136+
For more information about this error, try `rustc --explain E0512`.

0 commit comments

Comments
 (0)