Prevent an ICE on invalid transmutes

This commit is contained in:
Oliver Scherer 2019-12-14 00:19:24 +01:00
parent 13694de4a2
commit a0bd1a695d
4 changed files with 161 additions and 6 deletions

View File

@ -432,6 +432,7 @@ pub enum UnsupportedOpInfo<'tcx> {
HeapAllocNonPowerOfTwoAlignment(u64),
ReadFromReturnPointer,
PathNotFound(Vec<String>),
TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
}
impl fmt::Debug for UnsupportedOpInfo<'tcx> {
@ -460,6 +461,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
passing data of type {:?}",
callee_ty, caller_ty
),
TransmuteSizeDiff(from_ty, to_ty) => write!(
f,
"tried to transmute from {:?} to {:?}, but their sizes differed",
from_ty, to_ty
),
FunctionRetMismatch(caller_ty, callee_ty) => write!(
f,
"tried to call a function with return type {:?} \

View File

@ -923,12 +923,10 @@ pub fn copy_op_transmute(
return self.copy_op(src, dest);
}
// We still require the sizes to match.
assert!(
src.layout.size == dest.layout.size,
"Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}",
src,
dest
);
if src.layout.size != dest.layout.size {
error!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
throw_unsup!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
}
// Unsized copies rely on interpreting `src.meta` with `dest.layout`, we want
// to avoid that here.
assert!(

View File

@ -0,0 +1,15 @@
#![feature(const_transmute)]
fn main() {
match &b""[..] {
ZST => {}
//~^ ERROR could not evaluate constant pattern
}
}
const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
//~^ ERROR any use of this value will cause an error
//~| ERROR cannot transmute between types of different sizes
// Once the `any use of this value will cause an error` disappears in this test, make sure to
// remove the `TransmuteSizeDiff` error variant and make its emitter site an assertion again.

View File

@ -0,0 +1,136 @@
[ERROR rustc_mir::interpret::place] Size mismatch when transmuting!
src: OpTy {
op: Immediate(
Scalar(
0x0000000000000001,
),
),
layout: TyLayout {
ty: usize,
details: LayoutDetails {
variants: Single {
index: 0,
},
fields: Union(
0,
),
abi: Scalar(
Scalar {
value: Int(
I64,
false,
),
valid_range: 0..=18446744073709551615,
},
),
largest_niche: None,
align: AbiAndPrefAlign {
abi: Align {
pow2: 3,
},
pref: Align {
pow2: 3,
},
},
size: Size {
raw: 8,
},
},
},
}
dest: PlaceTy {
place: Ptr(
MemPlace {
ptr: AllocId(0).0x0,
align: Align {
pow2: 3,
},
meta: None,
},
),
layout: TyLayout {
ty: &[u8],
details: LayoutDetails {
variants: Single {
index: 0,
},
fields: Arbitrary {
offsets: [
Size {
raw: 0,
},
Size {
raw: 8,
},
],
memory_index: [
0,
1,
],
},
abi: ScalarPair(
Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
Scalar {
value: Int(
I64,
false,
),
valid_range: 0..=18446744073709551615,
},
),
largest_niche: Some(
Niche {
offset: Size {
raw: 0,
},
scalar: Scalar {
value: Pointer,
valid_range: 1..=18446744073709551615,
},
},
),
align: AbiAndPrefAlign {
abi: Align {
pow2: 3,
},
pref: Align {
pow2: 3,
},
},
size: Size {
raw: 16,
},
},
},
}
error: any use of this value will cause an error
--> $DIR/transmute-size-mismatch-before-typeck.rs:10:29
|
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
| ----------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^---
| |
| tried to transmute from usize to &[u8], but their sizes differed
|
= note: `#[deny(const_err)]` on by default
error: could not evaluate constant pattern
--> $DIR/transmute-size-mismatch-before-typeck.rs:5:9
|
LL | ZST => {}
| ^^^
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> $DIR/transmute-size-mismatch-before-typeck.rs:10:29
|
LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `usize` (64 bits)
= note: target type: `&'static [u8]` (128 bits)
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0512`.